From b1be5ca53587d23e7aeb77b26861fdc0a181ffd8 Mon Sep 17 00:00:00 2001 From: Eurogiciel-BOT Date: Thu, 4 Sep 2014 09:27:37 +0000 Subject: [PATCH 1/1] Upstream version 9.37.197.0 Upstream commit-id 9b0155ddca7fd02ab92817b9537eca761789f7ab Change-Id: Ic59b134814a319519a26394b68308f519c5f4fc3 Signed-off-by: Eurogiciel-BOT --- packaging/crosswalk.spec | 7 +- src/.DEPS.git | 6 +- src/DEPS | 8 +- src/android_webview/DEPS | 3 +- src/android_webview/android_webview.gyp | 3 +- src/android_webview/android_webview_tests.gypi | 12 + .../renderer_host/aw_render_view_host_ext.cc | 5 - .../renderer_host/aw_render_view_host_ext.h | 2 - src/android_webview/common/render_view_messages.h | 5 - .../src/org/chromium/android_webview/AwAssets.java | 38 +++ .../org/chromium/android_webview/AwContents.java | 16 +- .../chromium/android_webview/AwLayoutSizer.java | 97 +------ .../org/chromium/android_webview/AwSettings.java | 44 +++ .../android_webview/AwWebContentsDelegate.java | 2 +- .../AwWebContentsDelegateAdapter.java | 65 ++++- .../test/AndroidViewIntegrationTest.java | 5 +- .../android_webview/test/AwLayoutSizerTest.java | 165 ++--------- .../android_webview/test/AwSettingsTest.java | 154 +++++++++++ src/android_webview/lib/main/aw_main_delegate.cc | 8 +- src/android_webview/native/DEPS | 1 + .../native/android_webview_jni_registrar.cc | 2 + src/android_webview/native/aw_assets.cc | 41 +++ src/android_webview/native/aw_assets.h | 32 +++ src/android_webview/native/aw_contents.cc | 8 - src/android_webview/native/aw_contents.h | 4 - .../native/aw_media_url_interceptor.cc | 32 +++ .../native/aw_media_url_interceptor.h | 26 ++ .../native/aw_media_url_interceptor_unittest.cc | 73 +++++ src/android_webview/native/aw_settings.cc | 8 + .../native/aw_web_contents_delegate.cc | 10 +- src/android_webview/native/webview_native.gyp | 6 + src/android_webview/renderer/aw_render_view_ext.cc | 7 - src/android_webview/renderer/aw_render_view_ext.h | 2 - .../test/unittest/assets/asset_file.ogg | 7 + src/ash/strings/ash_strings_ar.xtb | 2 +- src/ash/strings/ash_strings_fil.xtb | 2 +- src/ash/strings/ash_strings_fr.xtb | 2 +- src/ash/strings/ash_strings_gu.xtb | 2 +- src/ash/strings/ash_strings_hr.xtb | 2 +- src/ash/strings/ash_strings_id.xtb | 2 +- src/ash/strings/ash_strings_it.xtb | 2 +- src/ash/strings/ash_strings_iw.xtb | 2 +- src/ash/strings/ash_strings_kn.xtb | 2 +- src/ash/strings/ash_strings_ko.xtb | 2 +- src/ash/strings/ash_strings_nl.xtb | 2 +- src/ash/wm/toplevel_window_event_handler.cc | 7 +- .../wm/toplevel_window_event_handler_unittest.cc | 32 +++ .../src/org/chromium/base/ContentUriUtils.java | 34 ++- src/base/android/jni_array.cc | 13 + src/base/android/jni_array.h | 6 + src/base/win/iat_patch_function.cc | 101 +++---- src/base/win/iat_patch_function.h | 3 + src/chrome/VERSION | 2 +- .../java/res/drawable-hdpi/pageinfo_bad.png | Bin 2389 -> 3291 bytes .../drawable-hdpi/pageinfo_enterprise_managed.png | Bin 839 -> 3046 bytes .../java/res/drawable-hdpi/pageinfo_good.png | Bin 1933 -> 3286 bytes .../java/res/drawable-hdpi/pageinfo_info.png | Bin 2119 -> 3067 bytes .../res/drawable-hdpi/pageinfo_warning_minor.png | Bin 1548 -> 3306 bytes .../drawable-ldrtl-sw600dp-hdpi/edge_menu_bg.9.png | Bin 0 -> 5233 bytes .../drawable-ldrtl-sw600dp-mdpi/edge_menu_bg.9.png | Bin 0 -> 4033 bytes .../edge_menu_bg.9.png | Bin 0 -> 6399 bytes .../edge_menu_bg.9.png | Bin 0 -> 9638 bytes .../java/res/drawable-mdpi/pageinfo_bad.png | Bin 1472 -> 3110 bytes .../drawable-mdpi/pageinfo_enterprise_managed.png | Bin 686 -> 2915 bytes .../java/res/drawable-mdpi/pageinfo_good.png | Bin 1170 -> 3095 bytes .../java/res/drawable-mdpi/pageinfo_info.png | Bin 1130 -> 2929 bytes .../res/drawable-mdpi/pageinfo_warning_minor.png | Bin 1240 -> 3106 bytes .../res/drawable-sw600dp-hdpi/edge_menu_bg.9.png | Bin 0 -> 5180 bytes .../res/drawable-sw600dp-mdpi/edge_menu_bg.9.png | Bin 0 -> 4041 bytes .../res/drawable-sw600dp-xhdpi/edge_menu_bg.9.png | Bin 0 -> 6339 bytes .../res/drawable-sw600dp-xxhdpi/edge_menu_bg.9.png | Bin 0 -> 9541 bytes .../java/res/drawable-xhdpi/pageinfo_bad.png | Bin 3675 -> 3605 bytes .../drawable-xhdpi/pageinfo_enterprise_managed.png | Bin 1057 -> 3113 bytes .../java/res/drawable-xhdpi/pageinfo_good.png | Bin 2765 -> 3513 bytes .../java/res/drawable-xhdpi/pageinfo_info.png | Bin 2973 -> 3132 bytes .../res/drawable-xhdpi/pageinfo_warning_minor.png | Bin 2071 -> 3585 bytes .../java/res/drawable-xxhdpi/pageinfo_bad.png | Bin 0 -> 3991 bytes .../java/res/drawable-xxhdpi/pageinfo_good.png | Bin 0 -> 3948 bytes .../java/res/drawable-xxhdpi/pageinfo_info.png | Bin 0 -> 3342 bytes .../res/drawable-xxhdpi/pageinfo_warning_minor.png | Bin 0 -> 3931 bytes .../android/java/res/layout/website_settings.xml | 56 ++-- .../android/java/res/values-sw600dp/dimens.xml | 11 + src/chrome/android/java/res/values/colors.xml | 3 + src/chrome/android/java/res/values/dimens.xml | 4 +- .../chromium/chrome/browser/CertificateViewer.java | 2 +- .../chromium/chrome/browser/TtsPlatformImpl.java | 16 +- .../chrome/browser/WebsiteSettingsPopup.java | 77 ++++-- .../chromium/chrome/browser/appmenu/AppMenu.java | 28 +- .../browser/appmenu/AppMenuButtonHelper.java | 13 +- .../chrome/browser/SmartClipProviderTest.java | 182 ++++++++++++ src/chrome/android/shell/java/AndroidManifest.xml | 3 + .../app/resources/generated_resources_ar.xtb | 2 +- .../app/resources/generated_resources_fil.xtb | 2 +- .../app/resources/generated_resources_fr.xtb | 2 +- .../app/resources/generated_resources_gu.xtb | 2 +- .../app/resources/generated_resources_hr.xtb | 2 +- .../app/resources/generated_resources_id.xtb | 6 +- .../app/resources/generated_resources_it.xtb | 2 +- .../app/resources/generated_resources_iw.xtb | 2 +- .../app/resources/generated_resources_kn.xtb | 2 +- .../app/resources/generated_resources_ko.xtb | 2 +- .../app/resources/generated_resources_nl.xtb | 2 +- .../app/resources/generated_resources_sr.xtb | 2 +- .../app/resources/generated_resources_ta.xtb | 6 +- .../app/resources/generated_resources_zh-TW.xtb | 4 +- src/chrome/browser/android/most_visited_sites.cc | 3 +- .../browser/chromeos/app_mode/kiosk_app_data.cc | 3 +- .../browser/chromeos/app_mode/kiosk_app_manager.cc | 9 + .../browser/chromeos/app_mode/kiosk_app_manager.h | 2 + .../chromeos/input_method/input_method_engine.cc | 45 ++- .../input_method_engine_browsertests.cc | 48 ++++ .../chromeos/login/ui/user_adding_screen.cc | 7 + .../api/system_cpu/cpu_info_provider_linux.cc | 18 +- .../browser/extensions/webstore_data_fetcher.cc | 8 +- .../browser/extensions/webstore_data_fetcher.h | 8 + src/chrome/browser/history/in_memory_url_index.cc | 19 ++ src/chrome/browser/history/in_memory_url_index.h | 2 - src/chrome/browser/profiles/profile_info_cache.cc | 5 + .../profiles/profile_info_cache_unittest.cc | 3 + .../chromevox/chromevox/injected/event_watcher.js | 7 +- .../chromeos/login/oobe_screen_hid_detection.css | 2 +- .../browser/resources/hotword_helper/manifest.json | 2 +- .../supervised_user/supervised_user_service.cc | 15 +- .../supervised_user/supervised_user_service.h | 3 + .../ui/android/website_settings_popup_android.cc | 24 +- .../passwords/manage_passwords_bubble_view.cc | 3 +- src/chrome/browser/ui/views/tabs/tab.cc | 5 + .../browser/ui/views/tabs/window_finder_ash.cc | 3 +- .../chromeos/login/hid_detection_screen_handler.cc | 5 +- .../webui/chromeos/login/kiosk_app_menu_handler.cc | 14 +- .../webui/chromeos/login/kiosk_app_menu_handler.h | 15 +- .../browser/ui/webui/chromeos/login/oobe_ui.cc | 2 +- .../chromevox/chromeVoxChromeBackgroundScript.js | 2 +- .../chromevox/chromeVoxChromeOptionsScript.js | 2 +- .../chromevox/chromeVoxChromePageScript.js | 2 +- src/chrome_elf/blacklist/blacklist.cc | 8 + .../policy/resources/policy_templates_fa.xtb | 2 +- .../policy/resources/policy_templates_id.xtb | 4 +- src/components/strings/components_strings_sr.xtb | 2 +- .../browser/android/content_view_core_impl.cc | 28 +- .../browser/android/content_view_core_impl.h | 11 +- .../synchronous_compositor_factory_impl.cc | 9 +- .../media/android/browser_media_player_manager.cc | 34 ++- .../media/android/browser_media_player_manager.h | 6 + .../media/android/media_resource_getter_impl.cc | 52 +++- .../media/android/media_resource_getter_impl.h | 7 + .../renderer_host/input/gesture_text_selector.cc | 74 +++++ .../renderer_host/input/gesture_text_selector.h | 65 +++++ .../input/gesture_text_selector_unittest.cc | 221 +++++++++++++++ .../renderer_host/input/motion_event_android.cc | 60 +++- .../renderer_host/input/motion_event_android.h | 9 +- .../renderer_host/input/motion_event_web.cc | 11 + .../browser/renderer_host/input/motion_event_web.h | 2 + .../renderer_host/render_widget_host_impl.cc | 12 + .../renderer_host/render_widget_host_impl.h | 3 +- .../render_widget_host_view_android.cc | 45 ++- .../render_widget_host_view_android.h | 17 +- .../browser/web_contents/web_contents_android.cc | 6 + .../browser/web_contents/web_contents_android.h | 2 + .../common/media/media_player_messages_android.h | 1 + src/content/common/view_messages.h | 9 +- src/content/content_browser.gypi | 2 + src/content/content_renderer.gypi | 4 +- src/content/content_tests.gypi | 1 + src/content/public/OWNERS | 2 + .../res/drawable-hdpi/pageinfo_warning_major.png | Bin 1327 -> 2954 bytes .../res/drawable-mdpi/pageinfo_warning_major.png | Bin 877 -> 2897 bytes .../res/drawable-xhdpi/pageinfo_warning_major.png | Bin 1715 -> 3076 bytes .../res/drawable-xxhdpi/pageinfo_warning_major.png | Bin 0 -> 3287 bytes .../org/chromium/content/browser/ContentView.java | 40 ++- .../chromium/content/browser/ContentViewCore.java | 104 ++++++- .../content/browser/MediaResourceGetter.java | 36 +++ .../content/browser/SmartClipProvider.java | 27 ++ .../browser/webcontents/WebContentsImpl.java | 6 + .../content_public/browser/WebContents.java | 5 + .../content/browser/MediaResourceGetterTest.java | 32 ++- .../public/common/common_param_traits_macros.h | 1 + src/content/renderer/OWNERS | 6 + .../renderer/media/android/media_info_loader.cc | 12 +- .../renderer/media/android/media_info_loader.h | 14 +- .../media/android/media_info_loader_unittest.cc | 8 +- .../media/android/renderer_media_player_manager.cc | 5 +- .../media/android/renderer_media_player_manager.h | 3 +- .../media/android/webmediaplayer_android.cc | 90 +++--- .../media/android/webmediaplayer_android.h | 19 +- src/content/renderer/render_font_warmup_win.cc | 204 ++++++++++++++ src/content/renderer/render_view_impl_android.cc | 6 +- src/content/renderer/renderer_font_platform_win.cc | 305 +++++++++++++++++++++ src/content/renderer/renderer_font_platform_win.h | 17 ++ .../shell/android/shell_apk/AndroidManifest.xml | 2 + src/google_apis/gcm/engine/gcm_store_impl.cc | 3 +- .../gcm/engine/gcm_store_impl_unittest.cc | 19 ++ .../command_buffer/service/gles2_cmd_decoder.cc | 6 +- src/gpu/config/gpu_driver_bug_list_json.cc | 18 +- src/media/audio/pulse/pulse_output.cc | 49 +++- src/media/audio/pulse/pulse_util.cc | 6 +- src/media/audio/win/audio_device_listener_win.cc | 3 - .../src/org/chromium/media/MediaPlayerBridge.java | 21 ++ src/media/base/android/media_player_bridge.cc | 104 +++++-- src/media/base/android/media_player_bridge.h | 11 +- src/media/base/android/media_player_manager.h | 6 +- src/media/base/android/media_resource_getter.h | 10 +- .../base/android/media_source_player_unittest.cc | 4 + src/media/base/android/media_url_interceptor.h | 36 +++ src/media/filters/ffmpeg_demuxer.cc | 40 +-- src/media/filters/ffmpeg_demuxer.h | 1 - src/media/media.gyp | 1 + .../src/org/chromium/net/ProxyChangeListener.java | 12 +- ...ve-pending-sheet-html-import-crash-expected.txt | 3 + .../remove-pending-sheet-html-import-crash.html | 3 + .../import-layout-with-pending-sheet.html | 11 + .../WebKit/Source/core/dom/Document.cpp | 5 +- .../WebKit/Source/core/frame/Settings.in | 4 + .../WebKit/Source/core/frame/SmartClip.cpp | 31 +-- .../WebKit/Source/core/frame/SmartClip.h | 3 +- .../WebKit/Source/web/WebLocalFrameImpl.h | 6 +- .../WebKit/Source/web/WebSettingsImpl.cpp | 5 + .../WebKit/Source/web/WebSettingsImpl.h | 1 + src/third_party/WebKit/Source/web/WebViewImpl.cpp | 45 ++- src/third_party/WebKit/Source/web/WebViewImpl.h | 4 + .../WebKit/Source/web/tests/WebFrameTest.cpp | 80 ++++++ .../WebKit/Source/web/tests/WebViewTest.cpp | 26 +- src/third_party/WebKit/public/web/WebSettings.h | 1 + src/third_party/WebKit/public/web/WebView.h | 6 + .../angle/src/compiler/translator/OutputHLSL.cpp | 6 +- .../src/org/chromium/ui/base/SelectFileDialog.java | 64 +++-- src/ui/aura/window_event_dispatcher.cc | 3 + src/ui/aura/window_event_dispatcher_unittest.cc | 13 + src/ui/base/ime/chromeos/ime_keymap.cc | 27 +- src/ui/base/ime/chromeos/ime_keymap.h | 3 + src/ui/events/BUILD.gn | 4 +- src/ui/events/events.gyp | 4 +- .../gesture_detection/gesture_provider_unittest.cc | 3 +- src/ui/events/gesture_detection/motion_event.h | 17 ++ .../touch_disposition_gesture_filter_unittest.cc | 4 +- .../gesture_detection/velocity_tracker_unittest.cc | 3 +- src/ui/events/gestures/motion_event_aura.cc | 10 + src/ui/events/gestures/motion_event_aura.h | 2 + .../mock_motion_event.cc | 52 +++- .../mock_motion_event.h | 9 + src/v8/src/mark-compact.cc | 15 +- src/v8/src/objects.cc | 4 +- src/v8/src/version.cc | 2 +- src/webkit/common/webpreferences.cc | 1 + src/webkit/common/webpreferences.h | 1 + src/webkit/glue/resources/webkit_strings_sr.xtb | 2 +- src/xwalk/DEPS.xwalk | 6 +- src/xwalk/VERSION | 2 +- src/xwalk/application/browser/application.cc | 4 + src/xwalk/application/browser/application.h | 6 +- .../application/browser/application_system.cc | 5 + .../browser/linux/running_applications_manager.cc | 5 +- .../common/installer/package_installer.cc | 2 + .../application/common/installer/signature_data.h | 10 - .../common/installer/signature_parser.cc | 49 +--- .../common/installer/tizen/signature_validator.cc | 11 +- .../common/installer/tizen/signature_validator.h | 6 - src/xwalk/application/common/signature_types.h | 24 -- .../application/tools/linux/xwalk_launcher_main.cc | 11 +- src/xwalk/application/tools/linux/xwalkctl_main.cc | 23 -- src/xwalk/packaging/crosswalk.spec | 7 +- .../src/org/xwalk/core/internal/XWalkContent.java | 19 +- .../org/xwalk/core/internal/XWalkViewInternal.java | 1 + src/xwalk/runtime/app/xwalk_main_delegate.cc | 2 +- src/xwalk/runtime/app/xwalk_main_delegate.h | 2 +- .../browser/devtools/xwalk_devtools_delegate.cc | 8 +- src/xwalk/runtime/browser/runtime.cc | 1 + src/xwalk/runtime/browser/runtime.h | 6 + .../runtime/browser/ui/native_app_window_tizen.h | 4 +- src/xwalk/sysapps/raw_socket/udp_socket_object.cc | 2 +- .../xwview/test/EnterAndLeaveFullscreenTest.java | 48 ++++ .../test/android/data/fullscreen_enter_exit.html | 19 ++ src/xwalk/xwalk_android_tests.gypi | 2 + 273 files changed, 3678 insertions(+), 934 deletions(-) create mode 100644 src/android_webview/java/src/org/chromium/android_webview/AwAssets.java create mode 100644 src/android_webview/native/aw_assets.cc create mode 100644 src/android_webview/native/aw_assets.h create mode 100644 src/android_webview/native/aw_media_url_interceptor.cc create mode 100644 src/android_webview/native/aw_media_url_interceptor.h create mode 100644 src/android_webview/native/aw_media_url_interceptor_unittest.cc create mode 100644 src/android_webview/test/unittest/assets/asset_file.ogg create mode 100644 src/chrome/android/java/res/drawable-ldrtl-sw600dp-hdpi/edge_menu_bg.9.png create mode 100644 src/chrome/android/java/res/drawable-ldrtl-sw600dp-mdpi/edge_menu_bg.9.png create mode 100644 src/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi/edge_menu_bg.9.png create mode 100644 src/chrome/android/java/res/drawable-ldrtl-sw600dp-xxhdpi/edge_menu_bg.9.png create mode 100644 src/chrome/android/java/res/drawable-sw600dp-hdpi/edge_menu_bg.9.png create mode 100644 src/chrome/android/java/res/drawable-sw600dp-mdpi/edge_menu_bg.9.png create mode 100644 src/chrome/android/java/res/drawable-sw600dp-xhdpi/edge_menu_bg.9.png create mode 100644 src/chrome/android/java/res/drawable-sw600dp-xxhdpi/edge_menu_bg.9.png create mode 100644 src/chrome/android/java/res/drawable-xxhdpi/pageinfo_bad.png create mode 100644 src/chrome/android/java/res/drawable-xxhdpi/pageinfo_good.png create mode 100644 src/chrome/android/java/res/drawable-xxhdpi/pageinfo_info.png create mode 100644 src/chrome/android/java/res/drawable-xxhdpi/pageinfo_warning_minor.png create mode 100644 src/chrome/android/java/res/values-sw600dp/dimens.xml create mode 100644 src/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java create mode 100644 src/content/browser/renderer_host/input/gesture_text_selector.cc create mode 100644 src/content/browser/renderer_host/input/gesture_text_selector.h create mode 100644 src/content/browser/renderer_host/input/gesture_text_selector_unittest.cc create mode 100644 src/content/public/OWNERS create mode 100644 src/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png create mode 100644 src/content/public/android/java/src/org/chromium/content/browser/SmartClipProvider.java create mode 100644 src/content/renderer/render_font_warmup_win.cc create mode 100644 src/content/renderer/renderer_font_platform_win.cc create mode 100644 src/content/renderer/renderer_font_platform_win.h create mode 100644 src/media/base/android/media_url_interceptor.h create mode 100644 src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash-expected.txt create mode 100644 src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash.html create mode 100644 src/third_party/WebKit/LayoutTests/fast/css/resources/import-layout-with-pending-sheet.html rename src/ui/events/{gesture_detection => test}/mock_motion_event.cc (81%) rename src/ui/events/{gesture_detection => test}/mock_motion_event.h (91%) delete mode 100644 src/xwalk/application/common/signature_types.h create mode 100644 src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/EnterAndLeaveFullscreenTest.java create mode 100644 src/xwalk/test/android/data/fullscreen_enter_exit.html diff --git a/packaging/crosswalk.spec b/packaging/crosswalk.spec index d84106c..6bd9331 100644 --- a/packaging/crosswalk.spec +++ b/packaging/crosswalk.spec @@ -16,7 +16,7 @@ %endif Name: crosswalk -Version: 9.37.195.0 +Version: 9.37.197.0 Release: 0 Summary: Crosswalk is an app runtime based on Chromium License: (BSD-3-Clause and LGPL-2.1+) @@ -176,11 +176,6 @@ GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Ddisable_nacl=%{_disable_nacl}" GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Ddisable_fatal_linker_warnings=1" %endif -# Temporarily disable Alsa support while snd_seq_* support is not enabled on -# Tizen. See https://codereview.chromium.org/264973012 and -# https://review.tizen.org/gerrit/#/c/24336/ -GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_alsa=0" - # Temporarily disable WebRTC support because its build currently hardcodes # dependencies on X11 and OpenSSL. We are still trying to get some # clarifications as to whether this is really necessary. See XWALK-2160. diff --git a/src/.DEPS.git b/src/.DEPS.git index ce27c26..25bbc01 100644 --- a/src/.DEPS.git +++ b/src/.DEPS.git @@ -9,9 +9,9 @@ vars = { 'git_url': 'https://chromium.googlesource.com', 'webkit_rev': - '@052a22b0345eccf119172f8ee6bae904d04fe172', + '@85b8bad59be0f106c1123b12043fc14d9a0034de', 'angle_revision': - '75551cf9a7c65bcdb9f9fe44ac78ca15da37942e' + 'f4126d2b9eb008d4e792fff2592f338e19c68569' } deps = { @@ -170,7 +170,7 @@ deps = { 'src/tools/swarming_client': Var('git_url') + '/external/swarming.client.git@c333224ef8cf5cc41ab91f6ee9cb1fdbe3689f19', 'src/v8': - Var('git_url') + '/external/v8.git@644e49bdbb46608c3292d19df9145c0793927e54', + Var('git_url') + '/external/v8.git@14b092be52bd160007e9b57fa6692f5093d071c4', } deps_os = { diff --git a/src/DEPS b/src/DEPS index 2252ce4..14f8f5b 100644 --- a/src/DEPS +++ b/src/DEPS @@ -185,7 +185,7 @@ deps_os = { 'src/third_party/WebKit/LayoutTests/w3c/web-platform-tests': None, 'src/chrome/test/data/extensions/api_test/permissions/nacl_enabled/bin': None, 'src/third_party/WebKit/public': - (Var("blink")) + '/branches/chromium/2062/public@180122', + (Var("blink")) + '/branches/chromium/2062/public@180557', 'src/native_client': None, 'src/tools/page_cycler/acid3': None, 'src/testing/iossim/third_party/class-dump': @@ -281,7 +281,7 @@ deps = { 'src/third_party/libwebm/source': (Var("git.chromium.org")) + '/webm/libwebm.git@8be63972fdd7ae8c041778f8ba674ade903395c9', 'src/third_party/WebKit': - (Var("blink")) + '/branches/chromium/2062@180122', + (Var("blink")) + '/branches/chromium/2062@180557', 'src/third_party/openmax_dl': (Var("webrtc")) + '/deps/third_party/openmax@6483', 'src/third_party/libc++abi/trunk': @@ -345,7 +345,7 @@ deps = { 'src/sdch/open-vcdiff': (Var("open-vcdiff")) + '/trunk@42', 'src/third_party/angle': - (Var("git.chromium.org")) + '/angle/angle.git@75551cf9a7c65bcdb9f9fe44ac78ca15da37942e', + (Var("git.chromium.org")) + '/angle/angle.git@f4126d2b9eb008d4e792fff2592f338e19c68569', 'build/third_party/lighttpd': '/trunk/deps/third_party/lighttpd@58968', 'src/buildtools': @@ -419,7 +419,7 @@ deps = { 'src/third_party/libsrtp': '/trunk/deps/third_party/libsrtp@261337', 'src/v8': - (Var("v8")) + '/branches/3.27@22914', + (Var("v8")) + '/branches/3.27@23158', 'src/third_party/pywebsocket/src': (Var("pywebsocket")) + '/trunk/src@790', 'src/third_party/libvpx': diff --git a/src/android_webview/DEPS b/src/android_webview/DEPS index 91ac0f5..fe7f839 100644 --- a/src/android_webview/DEPS +++ b/src/android_webview/DEPS @@ -1,4 +1,4 @@ -# Please include joth@ and (joi@ or erikwright@) on the review for any changes +# Please include benm@ and (erikwright@) on the review for any changes # to DEPS files under android_webview/ # Do not add any includes under chrome/ anywhere in android_webview. @@ -8,6 +8,7 @@ include_rules = [ "-android_webview/lib", "+components/data_reduction_proxy", + "+content/browser/media/android", "+content/public/common", "+gpu", "+jni", diff --git a/src/android_webview/android_webview.gyp b/src/android_webview/android_webview.gyp index 2efc46c..1a04365 100644 --- a/src/android_webview/android_webview.gyp +++ b/src/android_webview/android_webview.gyp @@ -99,6 +99,7 @@ '../components/components.gyp:visitedlink_renderer', '../components/components.gyp:web_contents_delegate_android', '../content/content.gyp:content_app_both', + '../content/content.gyp:content_browser', '../gpu/gpu.gyp:command_buffer_service', '../gpu/gpu.gyp:gles2_implementation', '../gpu/gpu.gyp:gl_in_process_context', @@ -268,7 +269,7 @@ 'includes': [ '../build/java.gypi' ], }, ], - }, { # android_webview_build==1 + }, { # android_webview_build==1 'targets': [ { 'target_name': 'android_webview_jarjar_ui_resources', diff --git a/src/android_webview/android_webview_tests.gypi b/src/android_webview/android_webview_tests.gypi index 390732a..1639e60 100644 --- a/src/android_webview/android_webview_tests.gypi +++ b/src/android_webview/android_webview_tests.gypi @@ -105,6 +105,7 @@ 'browser/net/input_stream_reader_unittest.cc', 'lib/main/webview_tests.cc', 'native/aw_contents_client_bridge_unittest.cc', + 'native/aw_media_url_interceptor_unittest.cc', 'native/input_stream_unittest.cc', 'native/permission/media_access_permission_request_unittest.cc', 'native/permission/permission_request_handler_unittest.cc', @@ -145,7 +146,18 @@ ], 'variables': { 'test_suite_name': 'android_webview_unittests', + 'additional_input_paths': [ + '<(PRODUCT_DIR)/android_webview_unittests_apk/assets/asset_file.ogg', + ], }, + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/android_webview_unittests_apk/assets', + 'files': [ + 'test/unittest/assets/asset_file.ogg', + ], + }, + ], 'includes': [ '../build/apk_test.gypi' ], }, ], diff --git a/src/android_webview/browser/renderer_host/aw_render_view_host_ext.cc b/src/android_webview/browser/renderer_host/aw_render_view_host_ext.cc index 787a647..676616a 100644 --- a/src/android_webview/browser/renderer_host/aw_render_view_host_ext.cc +++ b/src/android_webview/browser/renderer_host/aw_render_view_host_ext.cc @@ -74,11 +74,6 @@ void AwRenderViewHostExt::SetTextZoomFactor(float factor) { Send(new AwViewMsg_SetTextZoomFactor(web_contents()->GetRoutingID(), factor)); } -void AwRenderViewHostExt::SetFixedLayoutSize(const gfx::Size& size) { - DCHECK(CalledOnValidThread()); - Send(new AwViewMsg_SetFixedLayoutSize(web_contents()->GetRoutingID(), size)); -} - void AwRenderViewHostExt::ResetScrollAndScaleState() { DCHECK(CalledOnValidThread()); Send(new AwViewMsg_ResetScrollAndScaleState(web_contents()->GetRoutingID())); diff --git a/src/android_webview/browser/renderer_host/aw_render_view_host_ext.h b/src/android_webview/browser/renderer_host/aw_render_view_host_ext.h index f56d0a6..773e504 100644 --- a/src/android_webview/browser/renderer_host/aw_render_view_host_ext.h +++ b/src/android_webview/browser/renderer_host/aw_render_view_host_ext.h @@ -69,8 +69,6 @@ class AwRenderViewHostExt : public content::WebContentsObserver, // Text Autosizing. void SetTextZoomFactor(float factor); - void SetFixedLayoutSize(const gfx::Size& size); - void ResetScrollAndScaleState(); // Sets the initial page scale. This overrides initial scale set by diff --git a/src/android_webview/common/render_view_messages.h b/src/android_webview/common/render_view_messages.h index 0b8f315..7592fb7 100644 --- a/src/android_webview/common/render_view_messages.h +++ b/src/android_webview/common/render_view_messages.h @@ -67,11 +67,6 @@ IPC_MESSAGE_ROUTED0(AwViewMsg_ResetScrollAndScaleState) IPC_MESSAGE_ROUTED1(AwViewMsg_SetInitialPageScale, double /* page_scale_factor */) -// Makes the blink::WebView use the given size for layout regardless of what -// the size of the RenderWidget or viewport settings are. -IPC_MESSAGE_ROUTED1(AwViewMsg_SetFixedLayoutSize, - gfx::Size /* size */) - // Sets the base background color for this view. IPC_MESSAGE_ROUTED1(AwViewMsg_SetBackgroundColor, SkColor) diff --git a/src/android_webview/java/src/org/chromium/android_webview/AwAssets.java b/src/android_webview/java/src/org/chromium/android_webview/AwAssets.java new file mode 100644 index 0000000..97e292f --- /dev/null +++ b/src/android_webview/java/src/org/chromium/android_webview/AwAssets.java @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.android_webview; + +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.content.res.AssetManager; +import android.util.Log; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; + +import java.io.IOException; + +/** + * A utility class to retrieve references to uncompressed assets insides the apk. A reference is + * defined as tuple (file descriptor, offset, size) enabling direct mapping without deflation. + */ +@JNINamespace("android_webview") +public class AwAssets { + private static final String LOGTAG = "AwAssets"; + + @CalledByNative + public static long[] openAsset(Context context, String fileName) { + try { + AssetManager manager = context.getAssets(); + AssetFileDescriptor afd = manager.openFd(fileName); + return new long[] { afd.getParcelFileDescriptor().detachFd(), + afd.getStartOffset(), + afd.getLength() }; + } catch (IOException e) { + Log.e(LOGTAG, "Error while loading asset " + fileName + ": " + e.getMessage()); + return new long[] {-1, -1, -1}; + } + } +} diff --git a/src/android_webview/java/src/org/chromium/android_webview/AwContents.java b/src/android_webview/java/src/org/chromium/android_webview/AwContents.java index 79f919f..3745228 100644 --- a/src/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/src/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -418,16 +418,15 @@ public class AwContents { } @Override - public void setFixedLayoutSize(int widthDip, int heightDip) { - if (mNativeAwContents == 0) return; - nativeSetFixedLayoutSize(mNativeAwContents, widthDip, heightDip); - } - - @Override public boolean isLayoutParamsHeightWrapContent() { return mContainerView.getLayoutParams() != null && mContainerView.getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT; } + + @Override + public void setForceZeroLayoutHeight(boolean forceZeroHeight) { + getSettings().setForceZeroLayoutHeight(forceZeroHeight); + } } //-------------------------------------------------------------------------------------------- @@ -571,7 +570,8 @@ public class AwContents { mDIPScale = DeviceDisplayInfo.create(mContext).getDIPScale(); mLayoutSizer.setDelegate(new AwLayoutSizerDelegate()); mLayoutSizer.setDIPScale(mDIPScale); - mWebContentsDelegate = new AwWebContentsDelegateAdapter(contentsClient, mContainerView); + mWebContentsDelegate = new AwWebContentsDelegateAdapter( + contentsClient, mContainerView, mContext); mContentsClientBridge = new AwContentsClientBridge(contentsClient, mBrowserContext.getKeyStore(), AwContentsStatics.getClientCertLookupTable()); mZoomControls = new AwZoomControls(this); @@ -2438,8 +2438,6 @@ public class AwContents { private native void nativeOnAttachedToWindow(long nativeAwContents, int w, int h); private static native void nativeOnDetachedFromWindow(long nativeAwContents); private native void nativeSetDipScale(long nativeAwContents, float dipScale); - private native void nativeSetFixedLayoutSize(long nativeAwContents, - int widthDip, int heightDip); // Returns null if save state fails. private native byte[] nativeGetOpaqueState(long nativeAwContents); diff --git a/src/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java b/src/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java index 3789dc7..6957a97 100644 --- a/src/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java +++ b/src/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java @@ -11,8 +11,6 @@ import android.view.View.MeasureSpec; * Helper methods used to manage the layout of the View that contains AwContents. */ public class AwLayoutSizer { - public static final int FIXED_LAYOUT_HEIGHT = 0; - // These are used to prevent a re-layout if the content size changes within a dimension that is // fixed by the view system. private boolean mWidthMeasurementIsFixed; @@ -25,8 +23,6 @@ public class AwLayoutSizer { // Page scale factor. This is set to zero initially so that we don't attempt to do a layout if // we get the content size change notification first and a page scale change second. private float mPageScaleFactor = 0.0f; - // The page scale factor that was used in the most recent onMeasure call. - private float mLastMeasuredPageScaleFactor = 0.0f; // Whether to postpone layout requests. private boolean mFreezeLayoutRequests; @@ -40,22 +36,17 @@ public class AwLayoutSizer { // If mHeightMeasurementLimited is true then this contains the height limit. private int mHeightMeasurementLimit; - // The most recent width and height seen in onSizeChanged. - private int mLastWidth; - private int mLastHeight; - - // Used to prevent sending multiple setFixedLayoutSize notifications with the same values. - private int mLastSentFixedLayoutSizeWidth = -1; - private int mLastSentFixedLayoutSizeHeight = -1; - // Callback object for interacting with the View. private Delegate mDelegate; + /** + * Delegate interface through which the AwLayoutSizer communicates with the view it's sizing. + */ public interface Delegate { void requestLayout(); void setMeasuredDimension(int measuredWidth, int measuredHeight); - void setFixedLayoutSize(int widthDip, int heightDip); boolean isLayoutParamsHeightWrapContent(); + void setForceZeroLayoutHeight(boolean forceZeroHeight); } /** @@ -136,10 +127,6 @@ public class AwLayoutSizer { } else { mDelegate.requestLayout(); } - } else if (pageScaleChanged && mLastWidth != 0) { - // Because the fixed layout size is directly impacted by the pageScaleFactor we must - // update it even if the physical size of the view doesn't change. - updateFixedLayoutSize(mLastWidth, mLastHeight, mPageScaleFactor); } } @@ -159,8 +146,6 @@ public class AwLayoutSizer { int measuredHeight = contentHeightPix; int measuredWidth = contentWidthPix; - mLastMeasuredPageScaleFactor = mPageScaleFactor; - // Always use the given size unless unspecified. This matches WebViewClassic behavior. mWidthMeasurementIsFixed = (widthMode != MeasureSpec.UNSPECIFIED); mHeightMeasurementIsFixed = (heightMode == MeasureSpec.EXACTLY); @@ -193,9 +178,7 @@ public class AwLayoutSizer { * changed. */ public void onSizeChanged(int w, int h, int ow, int oh) { - mLastWidth = w; - mLastHeight = h; - updateFixedLayoutSize(mLastWidth, mLastHeight, mLastMeasuredPageScaleFactor); + updateLayoutSettings(); } /** @@ -204,72 +187,12 @@ public class AwLayoutSizer { * This should be called after onSizeChanged regardless of whether the size has changed or not. */ public void onLayoutChange() { - updateFixedLayoutSize(mLastWidth, mLastHeight, mLastMeasuredPageScaleFactor); + updateLayoutSettings(); } - private void setFixedLayoutSize(int widthDip, int heightDip) { - if (widthDip == mLastSentFixedLayoutSizeWidth && - heightDip == mLastSentFixedLayoutSizeHeight) - return; - mLastSentFixedLayoutSizeWidth = widthDip; - mLastSentFixedLayoutSizeHeight = heightDip; - - mDelegate.setFixedLayoutSize(widthDip, heightDip); - } - - // This needs to be called every time either the physical size of the view is changed or the - // pageScale is changed. Since we need to ensure that this is called immediately after - // onSizeChanged we can't just wait for onLayoutChange. At the same time we can't only make this - // call from onSizeChanged, since onSizeChanged won't fire if the view's physical size doesn't - // change. - private void updateFixedLayoutSize(int w, int h, float pageScaleFactor) { - boolean wrapContentForHeight = mDelegate.isLayoutParamsHeightWrapContent(); - // If the WebView's size in the Android view system depends on the size of its contents then - // the viewport size cannot be directly calculated from the WebView's physical size as that - // can result in the layout being unstable (for example loading the following contents - //
a - // would cause the WebView to indefinitely attempt to increase its height by 50%). - // If both the width and height are fixed (specified by the parent View) then content size - // changes will not cause subsequent layout passes and so we don't need to do anything - // special. - // We assume the width is 'fixed' if the parent View specified an EXACT or an AT_MOST - // measureSpec for the width (in which case the AT_MOST upper bound is the width). - // That means that the WebView will ignore LayoutParams.width set to WRAP_CONTENT and will - // instead try to take up as much width as possible. This is necessary because it's not - // practical to do web layout without a set width. - // For height the behavior is different because for a given width it is possible to - // calculate the minimum height required to display all of the content. As such the WebView - // can size itself vertically to match the content height. Because certain container views - // (LinearLayout with a WRAP_CONTENT height, for example) can result in onMeasure calls with - // both EXACTLY and AT_MOST height measureSpecs it is not possible to infer the sizing - // policy for the whole subtree based on the parameters passed to the onMeasure call. - // For that reason the LayoutParams.height property of the WebView is used. This behaves - // more predictably and means that toggling the fixedLayoutSize mode (which can have - // significant impact on how the web contents is laid out) is a direct consequence of the - // developer's choice. The downside is that it could result in the Android layout being - // unstable if a parent of the WebView has a wrap_content height while the WebView itself - // has height set to match_parent. Unfortunately addressing this edge case is costly so it - // will have to stay as is (this is compatible with Classic behavior). - if ((mWidthMeasurementIsFixed && !wrapContentForHeight) || pageScaleFactor == 0) { - setFixedLayoutSize(0, 0); - return; - } - - final double dipAndPageScale = pageScaleFactor * mDIPScale; - final int contentWidthPix = (int) (mContentWidthCss * dipAndPageScale); - - int widthDip = (int) Math.ceil(w / dipAndPageScale); - - // Make sure that we don't introduce rounding errors if the viewport is to be exactly as - // wide as the contents. - if (w == contentWidthPix) { - widthDip = mContentWidthCss; - } - - // This is workaround due to the fact that in wrap content mode we need to use a fixed - // layout size independent of view height, otherwise things like
- // cause the webview to grow indefinitely. We need to use a height independent of the - // webview's height. 0 is the value used in WebViewClassic. - setFixedLayoutSize(widthDip, FIXED_LAYOUT_HEIGHT); + // This needs to be called every time either the physical size of the view is changed or layout + // params are updated. + private void updateLayoutSettings() { + mDelegate.setForceZeroLayoutHeight(mDelegate.isLayoutParamsHeightWrapContent()); } } diff --git a/src/android_webview/java/src/org/chromium/android_webview/AwSettings.java b/src/android_webview/java/src/org/chromium/android_webview/AwSettings.java index 587ca48..76f6adb 100644 --- a/src/android_webview/java/src/org/chromium/android_webview/AwSettings.java +++ b/src/android_webview/java/src/org/chromium/android_webview/AwSettings.java @@ -87,6 +87,8 @@ public class AwSettings { private boolean mDomStorageEnabled = false; private boolean mDatabaseEnabled = false; private boolean mUseWideViewport = false; + private boolean mZeroLayoutHeightDisablesViewportQuirk = false; + private boolean mForceZeroLayoutHeight = false; private boolean mLoadWithOverviewMode = false; private boolean mMediaPlaybackRequiresUserGesture = true; private String mDefaultVideoPosterURL; @@ -1211,6 +1213,48 @@ public class AwSettings { return mUseWideViewport; } + public void setZeroLayoutHeightDisablesViewportQuirk(boolean enabled) { + synchronized (mAwSettingsLock) { + if (mZeroLayoutHeightDisablesViewportQuirk != enabled) { + mZeroLayoutHeightDisablesViewportQuirk = enabled; + mEventHandler.updateWebkitPreferencesLocked(); + } + } + } + + public boolean getZeroLayoutHeightDisablesViewportQuirk() { + synchronized (mAwSettingsLock) { + return getZeroLayoutHeightDisablesViewportQuirkLocked(); + } + } + + @CalledByNative + private boolean getZeroLayoutHeightDisablesViewportQuirkLocked() { + assert Thread.holdsLock(mAwSettingsLock); + return mZeroLayoutHeightDisablesViewportQuirk; + } + + public void setForceZeroLayoutHeight(boolean enabled) { + synchronized (mAwSettingsLock) { + if (mForceZeroLayoutHeight != enabled) { + mForceZeroLayoutHeight = enabled; + mEventHandler.updateWebkitPreferencesLocked(); + } + } + } + + public boolean getForceZeroLayoutHeight() { + synchronized (mAwSettingsLock) { + return getForceZeroLayoutHeightLocked(); + } + } + + @CalledByNative + private boolean getForceZeroLayoutHeightLocked() { + assert Thread.holdsLock(mAwSettingsLock); + return mForceZeroLayoutHeight; + } + @CalledByNative private boolean getPasswordEchoEnabledLocked() { assert Thread.holdsLock(mAwSettingsLock); diff --git a/src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java b/src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java index bdc5637..bf707eb 100644 --- a/src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java +++ b/src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java @@ -37,5 +37,5 @@ public abstract class AwWebContentsDelegate extends WebContentsDelegateAndroid { // Call in response to a prior runFileChooser call. protected static native void nativeFilesSelectedInChooser(int processId, int renderId, - int mode_flags, String[] filePath); + int mode_flags, String[] filePath, String[] displayName); } diff --git a/src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java b/src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java index 2edef84..96e3b5d 100644 --- a/src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java +++ b/src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java @@ -4,14 +4,20 @@ package org.chromium.android_webview; +import android.content.ContentResolver; +import android.content.Context; +import android.net.Uri; +import android.os.AsyncTask; import android.os.Handler; import android.os.Message; +import android.provider.MediaStore; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.webkit.ConsoleMessage; import android.webkit.ValueCallback; +import org.chromium.base.ContentUriUtils; import org.chromium.base.ThreadUtils; import org.chromium.content.browser.ContentViewCore; @@ -25,11 +31,13 @@ class AwWebContentsDelegateAdapter extends AwWebContentsDelegate { final AwContentsClient mContentsClient; View mContainerView; + final Context mContext; public AwWebContentsDelegateAdapter(AwContentsClient contentsClient, - View containerView) { + View containerView, Context context) { mContentsClient = contentsClient; setContainerView(containerView); + mContext = context; } public void setContainerView(View containerView) { @@ -160,10 +168,10 @@ class AwWebContentsDelegateAdapter extends AwWebContentsDelegate { } @Override - public void runFileChooser(final int processId, final int renderId, final int mode_flags, + public void runFileChooser(final int processId, final int renderId, final int modeFlags, String acceptTypes, String title, String defaultFilename, boolean capture) { AwContentsClient.FileChooserParams params = new AwContentsClient.FileChooserParams(); - params.mode = mode_flags; + params.mode = modeFlags; params.acceptTypes = acceptTypes; params.title = title; params.defaultFilename = defaultFilename; @@ -177,7 +185,14 @@ class AwWebContentsDelegateAdapter extends AwWebContentsDelegate { throw new IllegalStateException("Duplicate showFileChooser result"); } completed = true; - nativeFilesSelectedInChooser(processId, renderId, mode_flags, results); + if (results == null) { + nativeFilesSelectedInChooser( + processId, renderId, modeFlags, null, null); + return; + } + GetDisplayNameTask task = new GetDisplayNameTask( + mContext.getContentResolver(), processId, renderId, modeFlags, results); + task.execute(); } }, params); } @@ -191,4 +206,46 @@ class AwWebContentsDelegateAdapter extends AwWebContentsDelegate { public void activateContents() { mContentsClient.onRequestFocus(); } + + private static class GetDisplayNameTask extends AsyncTask { + final int mProcessId; + final int mRenderId; + final int mModeFlags; + final String[] mFilePaths; + final ContentResolver mContentResolver; + + public GetDisplayNameTask(ContentResolver contentResolver, int processId, int renderId, + int modeFlags, String[] filePaths) { + mProcessId = processId; + mRenderId = renderId; + mModeFlags = modeFlags; + mFilePaths = filePaths; + mContentResolver = contentResolver; + } + + @Override + protected String[] doInBackground(Void...voids) { + String[] displayNames = new String[mFilePaths.length]; + for (int i = 0; i < mFilePaths.length; i++) { + displayNames[i] = resolveFileName(mFilePaths[i]); + } + return displayNames; + } + + @Override + protected void onPostExecute(String[] result) { + nativeFilesSelectedInChooser(mProcessId, mRenderId, mModeFlags, mFilePaths, result); + } + + /** + * @return the display name of a path if it is a content URI and is present in the database + * or an empty string otherwise. + */ + private String resolveFileName(String filePath) { + if (mContentResolver == null || filePath == null) return ""; + Uri uri = Uri.parse(filePath); + return ContentUriUtils.getDisplayName( + uri, mContentResolver, MediaStore.MediaColumns.DISPLAY_NAME); + } + } } diff --git a/src/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java b/src/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java index 3ada155..9776f10 100644 --- a/src/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java +++ b/src/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java @@ -343,10 +343,7 @@ public class AndroidViewIntegrationTest extends AwTestBase { final int expectedWidthCss = (int) Math.ceil(getRootLayoutWidthOnMainThread() / deviceDIPScale); - final int expectedHeightCss = contentHeightCss + - // The second div in the contents is styled to have 150% of the viewport height, hence - // the 1.5. - (int) (AwLayoutSizer.FIXED_LAYOUT_HEIGHT * 1.5); + final int expectedHeightCss = contentHeightCss; loadPageOfSizeAndWaitForSizeChange(testContainerView.getAwContents(), mOnContentSizeChangedHelper, expectedWidthCss, contentHeightCss, true); diff --git a/src/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java b/src/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java index 4ef786b..18e06eb 100644 --- a/src/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java +++ b/src/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java @@ -12,14 +12,16 @@ import android.view.View.MeasureSpec; import org.chromium.android_webview.AwLayoutSizer; import org.chromium.base.test.util.Feature; +/** + * Unittests for the AwLayoutSizer class. + */ public class AwLayoutSizerTest extends InstrumentationTestCase { static class LayoutSizerDelegate implements AwLayoutSizer.Delegate { public int requestLayoutCallCount; public boolean setMeasuredDimensionCalled; public int measuredWidth; public int measuredHeight; - public int fixedLayoutWidth; - public int fixedLayoutHeight; + public boolean forceZeroHeight; public boolean heightWrapContent; @Override @@ -35,9 +37,8 @@ public class AwLayoutSizerTest extends InstrumentationTestCase { } @Override - public void setFixedLayoutSize(int widthDip, int heightDip) { - fixedLayoutWidth = widthDip; - fixedLayoutHeight = heightDip; + public void setForceZeroLayoutHeight(boolean forceZeroHeight) { + this.forceZeroHeight = forceZeroHeight; } @Override @@ -347,16 +348,6 @@ public class AwLayoutSizerTest extends InstrumentationTestCase { MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY)); assertEquals(measuredWidth, delegate.measuredWidth & View.MEASURED_SIZE_MASK); assertEquals(measuredHeight, delegate.measuredHeight & View.MEASURED_SIZE_MASK); - - layoutSizer.onSizeChanged(measuredWidth, measuredHeight, 0, 0); - - assertEquals(0, delegate.fixedLayoutWidth); - assertEquals(0, delegate.fixedLayoutHeight); - - layoutSizer.onPageScaleChanged(2.0f); - - assertEquals(0, delegate.fixedLayoutWidth); - assertEquals(0, delegate.fixedLayoutHeight); } @SmallTest @@ -388,54 +379,6 @@ public class AwLayoutSizerTest extends InstrumentationTestCase { @SmallTest @Feature({"AndroidWebView"}) - public void testViewportWithUnspecifiedMeasureSpec() { - AwLayoutSizer layoutSizer = new AwLayoutSizer(); - LayoutSizerDelegate delegate = new LayoutSizerDelegate(); - layoutSizer.setDelegate(delegate); - - final float dipScale = 1.5f; - final int pageScale = 2; - final int dipAndPageScale = (int) (dipScale * pageScale); - - int contentWidth = 800; - int contentHeight = 400; - int atMostWidth = contentWidth * dipAndPageScale; - int atMostHeight = contentHeight * dipAndPageScale; - - layoutSizer.setDIPScale(dipScale); - layoutSizer.onContentSizeChanged(contentWidth, contentHeight); - layoutSizer.onPageScaleChanged(pageScale); - layoutSizer.onMeasure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - - assertTrue(delegate.setMeasuredDimensionCalled); - int measuredWidth = delegate.measuredWidth & View.MEASURED_SIZE_MASK; - int measuredHeight = delegate.measuredHeight & View.MEASURED_SIZE_MASK; - - int sizeWidth = measuredWidth; - int sizeHeight = measuredHeight; - layoutSizer.onSizeChanged(sizeWidth, sizeHeight, 0, 0); - - assertEquals(contentWidth, delegate.fixedLayoutWidth); - assertEquals(AwLayoutSizer.FIXED_LAYOUT_HEIGHT, delegate.fixedLayoutHeight); - - sizeWidth = measuredWidth * 2; - sizeHeight = measuredHeight * 2; - layoutSizer.onSizeChanged(sizeWidth, sizeHeight, 0, 0); - - assertEquals(sizeWidth / dipAndPageScale, delegate.fixedLayoutWidth); - assertEquals(AwLayoutSizer.FIXED_LAYOUT_HEIGHT, delegate.fixedLayoutHeight); - - sizeWidth = measuredWidth / 2; - sizeHeight = measuredHeight / 2; - layoutSizer.onSizeChanged(sizeWidth, sizeHeight, 0, 0); - - assertEquals(sizeWidth / dipAndPageScale, delegate.fixedLayoutWidth); - assertEquals(AwLayoutSizer.FIXED_LAYOUT_HEIGHT, delegate.fixedLayoutHeight); - } - - @SmallTest - @Feature({"AndroidWebView"}) public void testViewportWithAtMostMeasureSpec() { AwLayoutSizer layoutSizer = new AwLayoutSizer(); LayoutSizerDelegate delegate = new LayoutSizerDelegate(); @@ -451,6 +394,8 @@ public class AwLayoutSizerTest extends InstrumentationTestCase { int contentWidthPix = contentWidth * dipAndPageScale; int contentHeightPix = contentHeight * dipAndPageScale; + assertFalse(delegate.forceZeroHeight); + layoutSizer.setDIPScale(dipScale); layoutSizer.onContentSizeChanged(contentWidth, contentHeight); layoutSizer.onPageScaleChanged(pageScale); @@ -458,54 +403,21 @@ public class AwLayoutSizerTest extends InstrumentationTestCase { MeasureSpec.makeMeasureSpec(contentHeightPix * 2, MeasureSpec.AT_MOST)); assertTrue(delegate.setMeasuredDimensionCalled); + assertFalse(delegate.forceZeroHeight); + int measuredWidth = delegate.measuredWidth & View.MEASURED_SIZE_MASK; int measuredHeight = delegate.measuredHeight & View.MEASURED_SIZE_MASK; + layoutSizer.onSizeChanged(measuredWidth, measuredHeight, 0, 0); - int sizeWidth = measuredWidth; - int sizeHeight = measuredHeight; - layoutSizer.onSizeChanged(sizeWidth, sizeHeight, 0, 0); - - assertEquals(contentWidth, delegate.fixedLayoutWidth); - assertEquals(AwLayoutSizer.FIXED_LAYOUT_HEIGHT, delegate.fixedLayoutHeight); - } - - @SmallTest - @Feature({"AndroidWebView"}) - public void testFixedLayoutViewportGoesBackToZeroWithWrapContentMeasureSpec() { - AwLayoutSizer layoutSizer = new AwLayoutSizer(); - LayoutSizerDelegate delegate = new LayoutSizerDelegate(); - layoutSizer.setDelegate(delegate); - layoutSizer.setDIPScale(DIP_SCALE); - - layoutSizer.onContentSizeChanged(FIRST_CONTENT_WIDTH, FIRST_CONTENT_HEIGHT); - layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE); - layoutSizer.onMeasure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - layoutSizer.onSizeChanged((int) (FIRST_CONTENT_WIDTH * DIP_SCALE), - (int) (FIRST_CONTENT_HEIGHT * DIP_SCALE), 0, 0); - - assertTrue(delegate.fixedLayoutWidth != 0); - assertEquals(AwLayoutSizer.FIXED_LAYOUT_HEIGHT, delegate.fixedLayoutHeight); - - layoutSizer.onContentSizeChanged(FIRST_CONTENT_WIDTH, AwLayoutSizer.FIXED_LAYOUT_HEIGHT); - layoutSizer.onSizeChanged((int) (FIRST_CONTENT_WIDTH * DIP_SCALE), - (int) (FIRST_CONTENT_HEIGHT * DIP_SCALE), 0, 0); - assertTrue(delegate.fixedLayoutWidth != 0); - assertEquals(0, delegate.fixedLayoutHeight); - - layoutSizer.onContentSizeChanged(FIRST_CONTENT_WIDTH, 0); - layoutSizer.onSizeChanged((int) (FIRST_CONTENT_WIDTH * DIP_SCALE), - (int) (FIRST_CONTENT_HEIGHT * DIP_SCALE), 0, 0); - assertTrue(delegate.fixedLayoutWidth != 0); - assertEquals(0, delegate.fixedLayoutHeight); + assertTrue(delegate.forceZeroHeight); } @SmallTest @Feature({"AndroidWebView"}) - public void testFixedLayoutSizeUpdatedOnPageScaleChangeItNoLayoutRequest() { + public void testFixedLayoutSizeDependsOnHeightWrapContent() { AwLayoutSizer layoutSizer = new AwLayoutSizer(); LayoutSizerDelegate delegate = new LayoutSizerDelegate(); - delegate.heightWrapContent = true; + delegate.heightWrapContent = false; layoutSizer.setDelegate(delegate); layoutSizer.setDIPScale(DIP_SCALE); @@ -516,44 +428,12 @@ public class AwLayoutSizerTest extends InstrumentationTestCase { MeasureSpec.makeMeasureSpec(AT_MOST_MEASURE_SIZE, MeasureSpec.AT_MOST)); layoutSizer.onSizeChanged(AT_MOST_MEASURE_SIZE, AT_MOST_MEASURE_SIZE, 0, 0); - assertTrue(delegate.fixedLayoutWidth != 0); - final int fixedLayoutWidth = delegate.fixedLayoutWidth; - final int requestLayoutCallCount = delegate.requestLayoutCallCount; - layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE * 2f); - assertEquals(requestLayoutCallCount, delegate.requestLayoutCallCount); - assertEquals(fixedLayoutWidth / 2, delegate.fixedLayoutWidth); - } - - @SmallTest - @Feature({"AndroidWebView"}) - public void testFixedLayoutSizeUpdatedIfNoSizeChangeAfterLayoutRequested() { - AwLayoutSizer layoutSizer = new AwLayoutSizer(); - LayoutSizerDelegate delegate = new LayoutSizerDelegate(); - layoutSizer.setDelegate(delegate); - layoutSizer.setDIPScale(DIP_SCALE); - - layoutSizer.onContentSizeChanged(FIRST_CONTENT_WIDTH, FIRST_CONTENT_HEIGHT); - layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE); - layoutSizer.onMeasure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - - layoutSizer.onSizeChanged((int) (FIRST_CONTENT_WIDTH * DIP_SCALE), - (int) (FIRST_CONTENT_HEIGHT * DIP_SCALE), 0, 0); - - assertTrue(delegate.fixedLayoutWidth != 0); - final int fixedLayoutWidth = delegate.fixedLayoutWidth; - final int requestLayoutCallCount = delegate.requestLayoutCallCount; - layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE * 0.5f); - assertEquals(requestLayoutCallCount + 1, delegate.requestLayoutCallCount); - assertEquals(fixedLayoutWidth, delegate.fixedLayoutWidth); + assertFalse(delegate.forceZeroHeight); - // onMeasure and onLayoutChange should always be called as a result of the AwLayoutSizer - // calling Delegate.requestLayout. - layoutSizer.onMeasure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - layoutSizer.onLayoutChange(); + delegate.heightWrapContent = true; + layoutSizer.onSizeChanged(AT_MOST_MEASURE_SIZE, AT_MOST_MEASURE_SIZE, 0, 0); - assertEquals(fixedLayoutWidth * 2, delegate.fixedLayoutWidth); + assertTrue(delegate.forceZeroHeight); } @SmallTest @@ -572,7 +452,12 @@ public class AwLayoutSizerTest extends InstrumentationTestCase { MeasureSpec.makeMeasureSpec(AT_MOST_MEASURE_SIZE, MeasureSpec.AT_MOST)); layoutSizer.onSizeChanged(AT_MOST_MEASURE_SIZE, AT_MOST_MEASURE_SIZE, 0, 0); - assertEquals(0, delegate.fixedLayoutWidth); - assertEquals(0, delegate.fixedLayoutHeight); + assertFalse(delegate.forceZeroHeight); + + layoutSizer.onMeasure( + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + layoutSizer.onSizeChanged(AT_MOST_MEASURE_SIZE, AT_MOST_MEASURE_SIZE, 0, 0); + assertFalse(delegate.forceZeroHeight); } } diff --git a/src/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/src/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java index d6ac546..2cadb07 100644 --- a/src/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java +++ b/src/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java @@ -1355,6 +1355,127 @@ public class AwSettingsTest extends AwTestBase { private int mOnScaleChangedCallCount; } + class AwSettingsForceZeroLayoutHeightTestHelper extends AwSettingsTestHelper { + + AwSettingsForceZeroLayoutHeightTestHelper( + AwTestContainerView containerView, + TestAwContentsClient contentViewClient, + boolean withViewPortTag) throws Throwable { + super(containerView, contentViewClient, true); + mWithViewPortTag = withViewPortTag; + mAwSettings.setUseWideViewPort(true); + } + + @Override + protected Boolean getAlteredValue() { + return ENABLED; + } + + @Override + protected Boolean getInitialValue() { + return DISABLED; + } + + @Override + protected Boolean getCurrentValue() { + return mAwSettings.getForceZeroLayoutHeight(); + } + + @Override + protected void setCurrentValue(Boolean value) { + mAwSettings.setForceZeroLayoutHeight(value); + } + + @Override + protected void doEnsureSettingHasValue(Boolean value) throws Throwable { + loadDataSync(getData()); + int height = Integer.parseInt(getTitleOnUiThread()); + if (value) { + assertEquals(0, height); + } else { + assertTrue("Div should be at least 50px high, was: " + height, height >= 50); + } + } + + private String getData() { + return "" + + (mWithViewPortTag ? "" : "") + + " " + + "" + + " " + + "
test
" + + "
" + + ""; + } + + private final boolean mWithViewPortTag; + } + + class AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper extends + AwSettingsTestHelper { + + AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper( + AwTestContainerView containerView, + TestAwContentsClient contentViewClient) throws Throwable { + super(containerView, contentViewClient, true); + mAwSettings.setUseWideViewPort(true); + mAwSettings.setForceZeroLayoutHeight(true); + } + + @Override + protected Boolean getAlteredValue() { + return ENABLED; + } + + @Override + protected Boolean getInitialValue() { + return DISABLED; + } + + @Override + protected Boolean getCurrentValue() { + return mAwSettings.getZeroLayoutHeightDisablesViewportQuirk(); + } + + @Override + protected void setCurrentValue(Boolean value) { + mAwSettings.setZeroLayoutHeightDisablesViewportQuirk(value); + } + + @Override + protected void doEnsureSettingHasValue(Boolean value) throws Throwable { + DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(mContext); + int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale()); + + loadDataSync(getData()); + int width = Integer.parseInt(getTitleOnUiThread()); + if (value) { + assertEquals(displayWidth, width); + } else { + assertEquals(3000, width); + } + } + + private String getData() { + return "" + + "" + + " " + + "" + + " " + + "
test
" + + "
" + + ""; + } + } + // The test verifies that JavaScript is disabled upon WebView // creation without accessing AwSettings. If the test passes, // it means that WebView-specific web preferences configuration @@ -2481,6 +2602,39 @@ public class AwSettingsTest extends AwTestBase { @SmallTest @Feature({"AndroidWebView", "Preferences"}) + public void testForceZeroLayoutHeightWithTwoViews() throws Throwable { + ViewPair views = createViews(); + runPerViewSettingsTest( + new AwSettingsForceZeroLayoutHeightTestHelper( + views.getContainer0(), views.getClient0(), false), + new AwSettingsForceZeroLayoutHeightTestHelper( + views.getContainer1(), views.getClient1(), false)); + } + + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) + public void testForceZeroLayoutHeightViewportTagWithTwoViews() throws Throwable { + ViewPair views = createViews(); + runPerViewSettingsTest( + new AwSettingsForceZeroLayoutHeightTestHelper( + views.getContainer0(), views.getClient0(), true), + new AwSettingsForceZeroLayoutHeightTestHelper( + views.getContainer1(), views.getClient1(), true)); + } + + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) + public void testZeroLayoutHeightDisablesViewportQuirkWithTwoViews() throws Throwable { + ViewPair views = createViews(); + runPerViewSettingsTest( + new AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper( + views.getContainer0(), views.getClient0()), + new AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper( + views.getContainer1(), views.getClient1())); + } + + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) public void testLoadWithOverviewModeWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( diff --git a/src/android_webview/lib/main/aw_main_delegate.cc b/src/android_webview/lib/main/aw_main_delegate.cc index 1102806..1ad7934 100644 --- a/src/android_webview/lib/main/aw_main_delegate.cc +++ b/src/android_webview/lib/main/aw_main_delegate.cc @@ -9,6 +9,7 @@ #include "android_webview/browser/gpu_memory_buffer_factory_impl.h" #include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h" #include "android_webview/lib/aw_browser_dependency_factory_impl.h" +#include "android_webview/native/aw_media_url_interceptor.h" #include "android_webview/native/aw_quota_manager_bridge_impl.h" #include "android_webview/native/aw_web_contents_view_delegate.h" #include "android_webview/native/aw_web_preferences_populater_impl.h" @@ -20,6 +21,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/threading/thread_restrictions.h" +#include "content/browser/media/android/browser_media_player_manager.h" #include "content/public/browser/browser_main_runner.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" @@ -48,13 +50,17 @@ AwMainDelegate::~AwMainDelegate() { bool AwMainDelegate::BasicStartupComplete(int* exit_code) { content::SetContentClient(&content_client_); + + CommandLine* cl = CommandLine::ForCurrentProcess(); gpu::InProcessCommandBuffer::SetGpuMemoryBufferFactory( gpu_memory_buffer_factory_.get()); + content::BrowserMediaPlayerManager::RegisterMediaUrlInterceptor( + new AwMediaUrlInterceptor()); + BrowserViewRenderer::CalculateTileMemoryPolicy(); - CommandLine* cl = CommandLine::ForCurrentProcess(); cl->AppendSwitch(switches::kEnableBeginFrameScheduling); cl->AppendSwitch(switches::kEnableZeroCopy); cl->AppendSwitch(switches::kEnableImplSidePainting); diff --git a/src/android_webview/native/DEPS b/src/android_webview/native/DEPS index ecc29cb..c3bef64 100644 --- a/src/android_webview/native/DEPS +++ b/src/android_webview/native/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+content/public/browser", "+content/public/test", + "+media/base/android", "+ui/gfx", "+ui/shell_dialogs", diff --git a/src/android_webview/native/android_webview_jni_registrar.cc b/src/android_webview/native/android_webview_jni_registrar.cc index 8db9713..253a070 100644 --- a/src/android_webview/native/android_webview_jni_registrar.cc +++ b/src/android_webview/native/android_webview_jni_registrar.cc @@ -5,6 +5,7 @@ #include "android_webview/native/android_webview_jni_registrar.h" #include "android_webview/native/android_protocol_handler.h" +#include "android_webview/native/aw_assets.h" #include "android_webview/native/aw_autofill_client.h" #include "android_webview/native/aw_contents.h" #include "android_webview/native/aw_contents_client_bridge.h" @@ -35,6 +36,7 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = { // Register JNI for android_webview classes. { "AndroidProtocolHandler", RegisterAndroidProtocolHandler }, { "AwAutofillClient", RegisterAwAutofillClient }, + { "AwAssets", RegisterAwAssets }, { "AwContents", RegisterAwContents }, { "AwContentsClientBridge", RegisterAwContentsClientBridge }, { "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl }, diff --git a/src/android_webview/native/aw_assets.cc b/src/android_webview/native/aw_assets.cc new file mode 100644 index 0000000..6d5ad72 --- /dev/null +++ b/src/android_webview/native/aw_assets.cc @@ -0,0 +1,41 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "android_webview/native/aw_assets.h" + +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" +#include "jni/AwAssets_jni.h" + +namespace android_webview { +namespace AwAssets { + +bool OpenAsset(const std::string& filename, + int* fd, + int64* offset, + int64* size) { + JNIEnv* env = base::android::AttachCurrentThread(); + ScopedJavaLocalRef jarr = Java_AwAssets_openAsset( + env, + base::android::GetApplicationContext(), + base::android::ConvertUTF8ToJavaString(env, filename).Release()); + std::vector results; + base::android::JavaLongArrayToLongVector(env, jarr.obj(), &results); + DCHECK_EQ(3U, results.size()); + *fd = static_cast(results[0]); + *offset = results[1]; + *size = results[2]; + return *fd != -1; +} + +} // namespace AwAssets + +bool RegisterAwAssets(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace android_webview diff --git a/src/android_webview/native/aw_assets.h b/src/android_webview/native/aw_assets.h new file mode 100644 index 0000000..229392c --- /dev/null +++ b/src/android_webview/native/aw_assets.h @@ -0,0 +1,32 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANDROID_WEBVIEW_NATIVE_AW_ASSETS_H_ +#define ANDROID_WEBVIEW_NATIVE_AW_ASSETS_H_ + +#include + +#include "base/android/jni_android.h" + +namespace android_webview { +namespace AwAssets { + +// Called by native to retrieve an asset (e.g. a .pak file) from the apk. +// Returns: true in case of success, false otherwise. +// Output arguments: +// - |fd|: file descriptor to the apk. The caller takes the ownership. +// - |offset|: offset in bytes from the start of the file +// - |size|: size in bytes of the asset / resource. +bool OpenAsset(const std::string& filename, + int* fd, + int64* offset, + int64* size); + +} // namespace AwAssets + +bool RegisterAwAssets(JNIEnv* env); + +} // namsespace android_webview + +#endif // ANDROID_WEBVIEW_NATIVE_AW_ASSETS_H_ diff --git a/src/android_webview/native/aw_contents.cc b/src/android_webview/native/aw_contents.cc index cc5e6a3..4e857c9 100644 --- a/src/android_webview/native/aw_contents.cc +++ b/src/android_webview/native/aw_contents.cc @@ -1058,14 +1058,6 @@ void AwContents::SetDipScale(JNIEnv* env, jobject obj, jfloat dip_scale) { browser_view_renderer_.SetDipScale(dip_scale); } -void AwContents::SetFixedLayoutSize(JNIEnv* env, - jobject obj, - jint width_dip, - jint height_dip) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - render_view_host_ext_->SetFixedLayoutSize(gfx::Size(width_dip, height_dip)); -} - void AwContents::ScrollTo(JNIEnv* env, jobject obj, jint x, jint y) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); browser_view_renderer_.ScrollTo(gfx::Vector2d(x, y)); diff --git a/src/android_webview/native/aw_contents.h b/src/android_webview/native/aw_contents.h index ddfeaf3..ffdbea3 100644 --- a/src/android_webview/native/aw_contents.h +++ b/src/android_webview/native/aw_contents.h @@ -211,10 +211,6 @@ class AwContents : public FindHelper::Listener, void ScrollTo(JNIEnv* env, jobject obj, jint x, jint y); void SetDipScale(JNIEnv* env, jobject obj, jfloat dip_scale); - void SetFixedLayoutSize(JNIEnv* env, - jobject obj, - jint width_dip, - jint height_dip); void SetSaveFormData(bool enabled); // Sets the java client diff --git a/src/android_webview/native/aw_media_url_interceptor.cc b/src/android_webview/native/aw_media_url_interceptor.cc new file mode 100644 index 0000000..1b214da --- /dev/null +++ b/src/android_webview/native/aw_media_url_interceptor.cc @@ -0,0 +1,32 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "android_webview/common/url_constants.h" +#include "android_webview/native/aw_assets.h" +#include "android_webview/native/aw_media_url_interceptor.h" +#include "base/strings/string_util.h" +#include "content/public/common/url_constants.h" + +namespace android_webview { + +bool AwMediaUrlInterceptor::Intercept(const std::string& url, + int* fd, int64* offset, int64* size) const{ + const std::string asset_file_prefix( + std::string(url::kFileScheme) + + std::string(url::kStandardSchemeSeparator) + + android_webview::kAndroidAssetPath); + + if (StartsWithASCII(url, asset_file_prefix, true)) { + std::string filename(url); + ReplaceFirstSubstringAfterOffset(&filename, 0, asset_file_prefix, ""); + return AwAssets::OpenAsset(filename, fd, offset, size); + } + + return false; +} + +} // namespace android_webview + diff --git a/src/android_webview/native/aw_media_url_interceptor.h b/src/android_webview/native/aw_media_url_interceptor.h new file mode 100644 index 0000000..b059c02 --- /dev/null +++ b/src/android_webview/native/aw_media_url_interceptor.h @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANDROID_WEBVIEW_NATIVE_AW_MEDIA_URL_INTERCEPTOR_H_ +#define ANDROID_WEBVIEW_NATIVE_AW_MEDIA_URL_INTERCEPTOR_H_ + +#include + +#include "base/android/jni_android.h" +#include "media/base/android/media_url_interceptor.h" + +namespace android_webview { + +// Interceptor to handle urls for media assets in the apk. +class AwMediaUrlInterceptor : public media::MediaUrlInterceptor { + public: + virtual bool Intercept(const std::string& url, + int* fd, + int64* offset, + int64* size) const OVERRIDE; +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_NATIVE_AW_MEDIA_URL_INTERCEPTOR_H_ diff --git a/src/android_webview/native/aw_media_url_interceptor_unittest.cc b/src/android_webview/native/aw_media_url_interceptor_unittest.cc new file mode 100644 index 0000000..be519e5 --- /dev/null +++ b/src/android_webview/native/aw_media_url_interceptor_unittest.cc @@ -0,0 +1,73 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "android_webview/native/aw_media_url_interceptor.h" +#include "base/memory/scoped_ptr.h" + +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Test; + +namespace android_webview { + +namespace { + +// Sentinel value to check whether the fields have been set. +const int UNSET_VALUE = -1; + +class AwMediaUrlInterceptorTest : public Test { + public: + AwMediaUrlInterceptorTest() + : fd_(UNSET_VALUE), offset_(UNSET_VALUE), size_(UNSET_VALUE), + url_interceptor_(new AwMediaUrlInterceptor()){ + } + protected: + int fd_; + int64 offset_; + int64 size_; + scoped_ptr url_interceptor_; +}; + +} // namespace + +TEST_F(AwMediaUrlInterceptorTest, TestInterceptValidAssetUrl) { + // This asset file exists in the android_webview_unittests-debug.apk. + // See gyp rule android_webview_unittests_apk. + const std::string valid_asset_url( + "file:///android_asset/asset_file.ogg"); + + ASSERT_TRUE(url_interceptor_->Intercept( + valid_asset_url, &fd_, &offset_, &size_)); + EXPECT_NE(UNSET_VALUE, fd_); + EXPECT_NE(UNSET_VALUE, offset_); + EXPECT_NE(UNSET_VALUE, size_); +} + +TEST_F(AwMediaUrlInterceptorTest, TestInterceptInvalidAssetUrl) { + // This asset file does not exist in the android_webview_unittests-debug.apk. + // See gyp rule android_webview_unittests_apk. + const std::string invalid_asset_url( + "file:///android_asset/file_does_not_exist.ogg"); + + ASSERT_FALSE(url_interceptor_->Intercept( + invalid_asset_url, &fd_, &offset_, &size_)); + EXPECT_EQ(UNSET_VALUE, fd_); + EXPECT_EQ(UNSET_VALUE, offset_); + EXPECT_EQ(UNSET_VALUE, size_); +} + +TEST_F(AwMediaUrlInterceptorTest, TestInterceptNonAssetUrl) { + // This url does not refer to an asset in the apk. + const std::string non_asset_url("file:///sdcard/file.txt"); + + ASSERT_FALSE(url_interceptor_->Intercept( + non_asset_url, &fd_, &offset_, &size_)); + EXPECT_EQ(UNSET_VALUE, fd_); + EXPECT_EQ(UNSET_VALUE, offset_); + EXPECT_EQ(UNSET_VALUE, size_); +} + +} // namespace android_webview diff --git a/src/android_webview/native/aw_settings.cc b/src/android_webview/native/aw_settings.cc index 19c6251..8d7370e 100644 --- a/src/android_webview/native/aw_settings.cc +++ b/src/android_webview/native/aw_settings.cc @@ -377,6 +377,14 @@ void AwSettings::PopulateWebPreferencesLocked( web_prefs->use_wide_viewport = Java_AwSettings_getUseWideViewportLocked(env, obj); + web_prefs->force_zero_layout_height = + Java_AwSettings_getForceZeroLayoutHeightLocked(env, obj); + + const bool zero_layout_height_disables_viewport_quirk = + Java_AwSettings_getZeroLayoutHeightDisablesViewportQuirkLocked(env, obj); + web_prefs->viewport_enabled = !(zero_layout_height_disables_viewport_quirk && + web_prefs->force_zero_layout_height); + web_prefs->double_tap_to_zoom_enabled = Java_AwSettings_supportsDoubleTapZoomLocked(env, obj); diff --git a/src/android_webview/native/aw_web_contents_delegate.cc b/src/android_webview/native/aw_web_contents_delegate.cc index f9c42b1..f7aecfe 100644 --- a/src/android_webview/native/aw_web_contents_delegate.cc +++ b/src/android_webview/native/aw_web_contents_delegate.cc @@ -210,16 +210,19 @@ void AwWebContentsDelegate::RequestMediaAccessPermission( static void FilesSelectedInChooser( JNIEnv* env, jclass clazz, jint process_id, jint render_id, jint mode_flags, - jobjectArray file_paths) { + jobjectArray file_paths, jobjectArray display_names) { content::RenderViewHost* rvh = content::RenderViewHost::FromID(process_id, render_id); if (!rvh) return; std::vector file_path_str; + std::vector display_name_str; // Note file_paths maybe NULL, but this will just yield a zero-length vector. base::android::AppendJavaStringArrayToStringVector(env, file_paths, &file_path_str); + base::android::AppendJavaStringArrayToStringVector(env, display_names, + &display_name_str); std::vector files; files.reserve(file_path_str.size()); for (size_t i = 0; i < file_path_str.size(); ++i) { @@ -227,7 +230,10 @@ static void FilesSelectedInChooser( if (!url.is_valid()) continue; base::FilePath path(url.SchemeIsFile() ? url.path() : file_path_str[i]); - files.push_back(ui::SelectedFileInfo(path, base::FilePath())); + ui::SelectedFileInfo file_info(path, base::FilePath()); + if (!display_name_str[i].empty()) + file_info.display_name = display_name_str[i]; + files.push_back(file_info); } FileChooserParams::Mode mode; if (mode_flags & kFileChooserModeOpenFolder) { diff --git a/src/android_webview/native/webview_native.gyp b/src/android_webview/native/webview_native.gyp index f8c70d9..cdd6f1f 100644 --- a/src/android_webview/native/webview_native.gyp +++ b/src/android_webview/native/webview_native.gyp @@ -16,6 +16,7 @@ '../../components/components.gyp:autofill_content_browser', '../../components/components.gyp:web_contents_delegate_android', '../../content/content.gyp:content_common', + '../../media/media.gyp:player_android', '../../net/net.gyp:net', '../../skia/skia.gyp:skia', '../../ui/base/ui_base.gyp:ui_base', @@ -36,6 +37,8 @@ 'android_protocol_handler.h', 'android_webview_jni_registrar.cc', 'android_webview_jni_registrar.h', + 'aw_assets.cc', + 'aw_assets.h', 'aw_autofill_client.cc', 'aw_autofill_client.h', 'aw_browser_dependency_factory.cc', @@ -54,6 +57,8 @@ 'aw_form_database.h', 'aw_http_auth_handler.cc', 'aw_http_auth_handler.h', + 'aw_media_url_interceptor.cc', + 'aw_media_url_interceptor.h', 'aw_pdf_exporter.cc', 'aw_pdf_exporter.h', 'aw_picture.cc', @@ -117,6 +122,7 @@ 'type': 'none', 'sources': [ '../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', + '../java/src/org/chromium/android_webview/AwAssets.java', '../java/src/org/chromium/android_webview/AwAutofillClient.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', diff --git a/src/android_webview/renderer/aw_render_view_ext.cc b/src/android_webview/renderer/aw_render_view_ext.cc index 7dd91e2..212b683 100644 --- a/src/android_webview/renderer/aw_render_view_ext.cc +++ b/src/android_webview/renderer/aw_render_view_ext.cc @@ -160,7 +160,6 @@ bool AwRenderViewExt::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(AwViewMsg_ResetScrollAndScaleState, OnResetScrollAndScaleState) IPC_MESSAGE_HANDLER(AwViewMsg_SetInitialPageScale, OnSetInitialPageScale) - IPC_MESSAGE_HANDLER(AwViewMsg_SetFixedLayoutSize, OnSetFixedLayoutSize) IPC_MESSAGE_HANDLER(AwViewMsg_SetBackgroundColor, OnSetBackgroundColor) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -307,12 +306,6 @@ void AwRenderViewExt::OnSetInitialPageScale(double page_scale_factor) { page_scale_factor); } -void AwRenderViewExt::OnSetFixedLayoutSize(const gfx::Size& size) { - if (!render_view() || !render_view()->GetWebView()) - return; - render_view()->GetWebView()->setFixedLayoutSize(size); -} - void AwRenderViewExt::OnSetBackgroundColor(SkColor c) { if (!render_view() || !render_view()->GetWebView()) return; diff --git a/src/android_webview/renderer/aw_render_view_ext.h b/src/android_webview/renderer/aw_render_view_ext.h index e0d5402..089273b 100644 --- a/src/android_webview/renderer/aw_render_view_ext.h +++ b/src/android_webview/renderer/aw_render_view_ext.h @@ -49,8 +49,6 @@ class AwRenderViewExt : public content::RenderViewObserver { void OnSetInitialPageScale(double page_scale_factor); - void OnSetFixedLayoutSize(const gfx::Size& size); - void OnSetBackgroundColor(SkColor c); void UpdatePageScaleFactor(); diff --git a/src/android_webview/test/unittest/assets/asset_file.ogg b/src/android_webview/test/unittest/assets/asset_file.ogg new file mode 100644 index 0000000..1e9e1a1 --- /dev/null +++ b/src/android_webview/test/unittest/assets/asset_file.ogg @@ -0,0 +1,7 @@ +This file is used by the WebView unittests for loading media asset files, +see android_webview_unittests_apk and AwMediaUrlInterceptorTest. + +This is a text file, but we use the .ogg extension so that aapt will not +compress its contents. This is ok for the purpose of the unit tests since +they do not play the media, and they are only interested in the existance of +an uncompressed media file in the assets directory. diff --git a/src/ash/strings/ash_strings_ar.xtb b/src/ash/strings/ash_strings_ar.xtb index 1332f40..a3ed5e6 100644 --- a/src/ash/strings/ash_strings_ar.xtb +++ b/src/ash/strings/ash_strings_ar.xtb @@ -154,7 +154,7 @@ نسخ إلى تمّ توصيل شاحن منخفض الطاقة. لذا قد لا تكون عملية شحن البطارية جديرة بالثقة. قفل -التطبيقات +تطبيقات إخفاق في عملية التنشيط أخفق الاتصال بشبكة "": ‏تم إيقاف تشغيل Wi-Fi. diff --git a/src/ash/strings/ash_strings_fil.xtb b/src/ash/strings/ash_strings_fil.xtb index 9a7dd44..5909986 100644 --- a/src/ash/strings/ash_strings_fil.xtb +++ b/src/ash/strings/ash_strings_fil.xtb @@ -154,7 +154,7 @@ Pindutin ang Shift + Alt upang magpalit. Nagmi-mirror sa Naka-saksak sa isang low-power charger. Maaaring hindi maging tiyak ang pag-charge ng baterya. I-lock -Apps +Mga App Pagkabigo ng pag-activate Nabigong kumonekta sa network na '': Naka-off ang Wi-Fi. diff --git a/src/ash/strings/ash_strings_fr.xtb b/src/ash/strings/ash_strings_fr.xtb index 31c6a5b..206d154 100644 --- a/src/ash/strings/ash_strings_fr.xtb +++ b/src/ash/strings/ash_strings_fr.xtb @@ -154,7 +154,7 @@ Appuyez sur Maj + Alt pour en utiliser un autre. Mise en miroir pour L'appareil est branché à un chargeur de faible puissance. Il se peut que la charge ne soit pas fiable. Verrouiller -Google Apps +Applications Échec de l'activation Échec de la connexion au réseau "" : . Le Wi-Fi est désactivé. diff --git a/src/ash/strings/ash_strings_gu.xtb b/src/ash/strings/ash_strings_gu.xtb index 400ac4a..31db163 100644 --- a/src/ash/strings/ash_strings_gu.xtb +++ b/src/ash/strings/ash_strings_gu.xtb @@ -154,7 +154,7 @@ પર પ્રતિબિંબિત થઈ રહ્યું છે નિમ્ન-પાવર ચાર્જરમાં પ્લગ કરેલું છે. બૅટરી ચાર્જિંગ વિશ્વસનીય હશે નહીં. લૉક -એપ્લિકેશન્સ +એપ્સ સક્રિયતા નિષ્ફળ નેટવર્ક '' થી કનેક્ટ કરવામાં નિષ્ફળ: Wi-Fi બંધ છે. diff --git a/src/ash/strings/ash_strings_hr.xtb b/src/ash/strings/ash_strings_hr.xtb index 6f87dc5..0e21d33 100644 --- a/src/ash/strings/ash_strings_hr.xtb +++ b/src/ash/strings/ash_strings_hr.xtb @@ -154,7 +154,7 @@ Pritisnite Shift + Alt za promjenu. Zrcaljenje na zaslon Uređaj je priključen na punjač male snage. Punjenje baterije možda nije pouzdano. Zaključaj -Apps +Aplikacije Neuspjela aktivacija Neuspješno povezivanje s mrežom "": Wi-Fi je isključen. diff --git a/src/ash/strings/ash_strings_id.xtb b/src/ash/strings/ash_strings_id.xtb index 01709fc..f12b469 100644 --- a/src/ash/strings/ash_strings_id.xtb +++ b/src/ash/strings/ash_strings_id.xtb @@ -154,7 +154,7 @@ Tekan Shift + Alt untuk beralih. Mencerminkan ke Dipasang ke pengisi daya rendah. Pengisian daya baterai mungkin tidak dapat diandalkan. Kunci -Apps +Apl Kegagalan aktivasi Gagal menyambung ke jaringan '': Wi-Fi dinonaktifkan. diff --git a/src/ash/strings/ash_strings_it.xtb b/src/ash/strings/ash_strings_it.xtb index 15f2e04..20c13bd 100644 --- a/src/ash/strings/ash_strings_it.xtb +++ b/src/ash/strings/ash_strings_it.xtb @@ -154,7 +154,7 @@ Premi Maiusc+Alt per cambiare metodo. Mirroring su Collegato a un caricabatterie a basso consumo. La carica della batteria potrebbe non essere affidabile. Blocca -Google Apps +App Errore di attivazione Connessione alla rete "" non riuscita: Wi-Fi non attivo. diff --git a/src/ash/strings/ash_strings_iw.xtb b/src/ash/strings/ash_strings_iw.xtb index 7e8e6e5..1f9b0d4 100644 --- a/src/ash/strings/ash_strings_iw.xtb +++ b/src/ash/strings/ash_strings_iw.xtb @@ -154,7 +154,7 @@ משקף אל מחובר למטען בעל מתח נמוך. ייתכן שטעינת הסוללה לא תהיה אמינה. נעילה -Apps +אפליקציות כשל בהפעלה ההתחברות לרשת נכשלה '': ‏Wi-Fi כבוי. diff --git a/src/ash/strings/ash_strings_kn.xtb b/src/ash/strings/ash_strings_kn.xtb index 5879955..cd20d66 100644 --- a/src/ash/strings/ash_strings_kn.xtb +++ b/src/ash/strings/ash_strings_kn.xtb @@ -154,7 +154,7 @@ ಗೆ ಪ್ರತಿಬಿಂಬಿಸುತ್ತಿದೆ ಕಡಿಮೆ ವಿದ್ಯುತ್ ಚಾರ್ಜರ್‌ಗೆ ಪ್ಲಗ್ ಮಾಡಲಾಗಿದೆ. ಬ್ಯಾಟರಿ ಚಾರ್ಜಿಂಗ್ ವಿಶ್ವಾಸಾರ್ಹವಾಗಿಲ್ಲದಿರಬಹುದು. ಲಾಕ್ ಮಾಡಿ -Apps +ಆಪ್ಸ್‌‌ ಸಕ್ರಿಯಗೊಳಿಸುವಿಕೆ ವಿಫಲವಾಗಿದೆ '' ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು ವಿಫಲವಾಗಿದೆ: Wi-Fi ಆಫ್ ಮಾಡಲಾಗಿದೆ. diff --git a/src/ash/strings/ash_strings_ko.xtb b/src/ash/strings/ash_strings_ko.xtb index 84f8ed4..2b767fd 100644 --- a/src/ash/strings/ash_strings_ko.xtb +++ b/src/ash/strings/ash_strings_ko.xtb @@ -154,7 +154,7 @@ 에 미러링 저출력 충전기에 연결되었습니다. 배터리 충전 상태가 불안정합니다. 잠금 -응용프로그램 +앱 활성화 실패 '' 네트워크에 연결하지 못했습니다: Wi-Fi가 꺼져 있습니다. diff --git a/src/ash/strings/ash_strings_nl.xtb b/src/ash/strings/ash_strings_nl.xtb index 53e17da..c99a16f 100644 --- a/src/ash/strings/ash_strings_nl.xtb +++ b/src/ash/strings/ash_strings_nl.xtb @@ -154,7 +154,7 @@ Druk op Shift + Alt om te schakelen. Spiegelen naar Aangesloten op een laag-vermogen-lader. Opladen van de batterij mogelijk niet betrouwbaar. Vergrendelen -Google Apps +Apps Activering mislukt Kan geen verbinding maken met het netwerk '': Wifi is uitgeschakeld. diff --git a/src/ash/wm/toplevel_window_event_handler.cc b/src/ash/wm/toplevel_window_event_handler.cc index 5d9ce4b..a759e8b 100644 --- a/src/ash/wm/toplevel_window_event_handler.cc +++ b/src/ash/wm/toplevel_window_event_handler.cc @@ -494,8 +494,11 @@ void ToplevelWindowEventHandler::HandleMouseReleased( if (event->phase() != ui::EP_PRETARGET) return; - CompleteDrag(event->type() == ui::ET_MOUSE_RELEASED ? - DRAG_COMPLETE : DRAG_REVERT); + if (window_resizer_) { + CompleteDrag(event->type() == ui::ET_MOUSE_RELEASED ? + DRAG_COMPLETE : DRAG_REVERT); + } + // Completing the drag may result in hiding the window. If this happens // mark the event as handled so no other handlers/observers act upon the // event. They should see the event on a hidden window, to determine targets diff --git a/src/ash/wm/toplevel_window_event_handler_unittest.cc b/src/ash/wm/toplevel_window_event_handler_unittest.cc index 3aa25ba..74497f7 100644 --- a/src/ash/wm/toplevel_window_event_handler_unittest.cc +++ b/src/ash/wm/toplevel_window_event_handler_unittest.cc @@ -16,6 +16,7 @@ #include "ash/wm/workspace_controller.h" #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/message_loop/message_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/test/aura_test_base.h" @@ -705,6 +706,37 @@ TEST_F(ToplevelWindowEventHandlerTest, RunMoveLoopFailsDuringInProgressDrag) { EXPECT_EQ("10,11 100x100", window1->bounds().ToString()); } +namespace { + +void SendMouseReleaseAndReleaseCapture(aura::test::EventGenerator* generator, + aura::Window* window) { + generator->ReleaseLeftButton(); + window->ReleaseCapture(); +} + +} // namespace + +// Test that a drag is successful even if ET_MOUSE_CAPTURE_CHANGED is sent +// immediately after the mouse release. views::Widget has this behavior. +TEST_F(ToplevelWindowEventHandlerTest, CaptureLossAfterMouseRelease) { + scoped_ptr window(CreateWindow(HTNOWHERE)); + aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), + window.get()); + generator.PressLeftButton(); + window->SetCapture(); + + aura::client::WindowMoveClient* move_client = + aura::client::GetWindowMoveClient(window->GetRootWindow()); + base::MessageLoopForUI::current()->PostTask( + FROM_HERE, + base::Bind(&SendMouseReleaseAndReleaseCapture, + base::Unretained(&generator), + base::Unretained(window.get()))); + EXPECT_EQ(aura::client::MOVE_SUCCESSFUL, + move_client->RunMoveLoop(window.get(), gfx::Vector2d(), + aura::client::WINDOW_MOVE_SOURCE_MOUSE)); +} + // Showing the resize shadows when the mouse is over the window edges is tested // in resize_shadow_and_cursor_test.cc diff --git a/src/base/android/java/src/org/chromium/base/ContentUriUtils.java b/src/base/android/java/src/org/chromium/base/ContentUriUtils.java index 74c74f4..b806b47 100644 --- a/src/base/android/java/src/org/chromium/base/ContentUriUtils.java +++ b/src/base/android/java/src/org/chromium/base/ContentUriUtils.java @@ -6,6 +6,7 @@ package org.chromium.base; import android.content.ContentResolver; import android.content.Context; +import android.database.Cursor; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -13,7 +14,7 @@ import android.util.Log; /** * This class provides methods to access content URI schemes. */ -abstract class ContentUriUtils { +public abstract class ContentUriUtils { private static final String TAG = "ContentUriUtils"; // Prevent instantiation. @@ -71,4 +72,35 @@ abstract class ContentUriUtils { } return pfd; } + + /** + * Method to resolve the display name of a content URI. + * + * @param uri the content URI to be resolved. + * @param contentResolver the content resolver to query. + * @param columnField the column field to query. + * @returns the display name of the @code uri if present in the database + * or an empty string otherwise. + */ + public static String getDisplayName( + Uri uri, ContentResolver contentResolver, String columnField) { + if (contentResolver == null || uri == null) return ""; + Cursor cursor = null; + try { + cursor = contentResolver.query(uri, null, null, null, null); + + if (cursor != null && cursor.getCount() >= 1) { + cursor.moveToFirst(); + int index = cursor.getColumnIndex(columnField); + if (index > -1) return cursor.getString(index); + } + } catch (NullPointerException e) { + // Some android models don't handle the provider call correctly. + // see crbug.com/345393 + return ""; + } finally { + if (cursor != null) cursor.close(); + } + return ""; + } } diff --git a/src/base/android/jni_array.cc b/src/base/android/jni_array.cc index 6c7ac5b..3c06413 100644 --- a/src/base/android/jni_array.cc +++ b/src/base/android/jni_array.cc @@ -167,6 +167,19 @@ void JavaIntArrayToIntVector(JNIEnv* env, env->ReleaseIntArrayElements(int_array, ints, JNI_ABORT); } +void JavaLongArrayToLongVector(JNIEnv* env, + jlongArray long_array, + std::vector* out) { + DCHECK(out); + out->clear(); + jsize len = env->GetArrayLength(long_array); + jlong* longs = env->GetLongArrayElements(long_array, NULL); + for (jsize i = 0; i < len; ++i) { + out->push_back(static_cast(longs[i])); + } + env->ReleaseLongArrayElements(long_array, longs, JNI_ABORT); +} + void JavaFloatArrayToFloatVector(JNIEnv* env, jfloatArray float_array, std::vector* out) { diff --git a/src/base/android/jni_array.h b/src/base/android/jni_array.h index 9d9be67..66b9422 100644 --- a/src/base/android/jni_array.h +++ b/src/base/android/jni_array.h @@ -73,6 +73,12 @@ BASE_EXPORT void JavaIntArrayToIntVector( jintArray int_array, std::vector* out); +// Replaces the content of |out| with the Java longs in |long_array|. +BASE_EXPORT void JavaLongArrayToLongVector( + JNIEnv* env, + jlongArray long_array, + std::vector* out); + // Replaces the content of |out| with the Java floats in |float_array|. BASE_EXPORT void JavaFloatArrayToFloatVector( JNIEnv* env, diff --git a/src/base/win/iat_patch_function.cc b/src/base/win/iat_patch_function.cc index 21c3995..7655927 100644 --- a/src/base/win/iat_patch_function.cc +++ b/src/base/win/iat_patch_function.cc @@ -40,56 +40,6 @@ void* GetIATFunction(IMAGE_THUNK_DATA* iat_thunk) { iat_function.thunk = *iat_thunk; return iat_function.pointer; } -// Change the page protection (of code pages) to writable and copy -// the data at the specified location -// -// Arguments: -// old_code Target location to copy -// new_code Source -// length Number of bytes to copy -// -// Returns: Windows error code (winerror.h). NO_ERROR if successful -DWORD ModifyCode(void* old_code, void* new_code, int length) { - if ((NULL == old_code) || (NULL == new_code) || (0 == length)) { - NOTREACHED(); - return ERROR_INVALID_PARAMETER; - } - - // Change the page protection so that we can write. - MEMORY_BASIC_INFORMATION memory_info; - DWORD error = NO_ERROR; - DWORD old_page_protection = 0; - - if (!VirtualQuery(old_code, &memory_info, sizeof(memory_info))) { - error = GetLastError(); - return error; - } - - DWORD is_executable = (PAGE_EXECUTE | PAGE_EXECUTE_READ | - PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) & - memory_info.Protect; - - if (VirtualProtect(old_code, - length, - is_executable ? PAGE_EXECUTE_READWRITE : - PAGE_READWRITE, - &old_page_protection)) { - - // Write the data. - CopyMemory(old_code, new_code, length); - - // Restore the old page protection. - error = ERROR_SUCCESS; - VirtualProtect(old_code, - length, - old_page_protection, - &old_page_protection); - } else { - error = GetLastError(); - } - - return error; -} bool InterceptEnumCallback(const base::win::PEImage& image, const char* module, DWORD ordinal, const char* name, DWORD hint, @@ -216,6 +166,57 @@ DWORD RestoreImportedFunction(void* intercept_function, } // namespace +// Change the page protection (of code pages) to writable and copy +// the data at the specified location +// +// Arguments: +// old_code Target location to copy +// new_code Source +// length Number of bytes to copy +// +// Returns: Windows error code (winerror.h). NO_ERROR if successful +DWORD ModifyCode(void* old_code, void* new_code, int length) { + if ((NULL == old_code) || (NULL == new_code) || (0 == length)) { + NOTREACHED(); + return ERROR_INVALID_PARAMETER; + } + + // Change the page protection so that we can write. + MEMORY_BASIC_INFORMATION memory_info; + DWORD error = NO_ERROR; + DWORD old_page_protection = 0; + + if (!VirtualQuery(old_code, &memory_info, sizeof(memory_info))) { + error = GetLastError(); + return error; + } + + DWORD is_executable = (PAGE_EXECUTE | PAGE_EXECUTE_READ | + PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) & + memory_info.Protect; + + if (VirtualProtect(old_code, + length, + is_executable ? PAGE_EXECUTE_READWRITE : + PAGE_READWRITE, + &old_page_protection)) { + + // Write the data. + CopyMemory(old_code, new_code, length); + + // Restore the old page protection. + error = ERROR_SUCCESS; + VirtualProtect(old_code, + length, + old_page_protection, + &old_page_protection); + } else { + error = GetLastError(); + } + + return error; +} + IATPatchFunction::IATPatchFunction() : module_handle_(NULL), original_function_(NULL), diff --git a/src/base/win/iat_patch_function.h b/src/base/win/iat_patch_function.h index 5026e0e..b400841 100644 --- a/src/base/win/iat_patch_function.h +++ b/src/base/win/iat_patch_function.h @@ -59,6 +59,7 @@ class BASE_EXPORT IATPatchFunction { void* original_function() const; + private: HMODULE module_handle_; void* intercept_function_; @@ -68,6 +69,8 @@ class BASE_EXPORT IATPatchFunction { DISALLOW_COPY_AND_ASSIGN(IATPatchFunction); }; +BASE_EXPORT DWORD ModifyCode(void* old_code, void* new_code, int length); + } // namespace win } // namespace base diff --git a/src/chrome/VERSION b/src/chrome/VERSION index 240043c..91a647d 100644 --- a/src/chrome/VERSION +++ b/src/chrome/VERSION @@ -1,4 +1,4 @@ MAJOR=37 MINOR=0 BUILD=2062 -PATCH=76 +PATCH=94 diff --git a/src/chrome/android/java/res/drawable-hdpi/pageinfo_bad.png b/src/chrome/android/java/res/drawable-hdpi/pageinfo_bad.png index b472a544628bee5bfec30140d41f01dadcec7f83..e4345bb425659782a327ba1f07d76372e66ed3b6 100644 GIT binary patch literal 3291 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 ZJpgFVqa9+sRQ&(|002ovPDHLkV1lVEO11z1 literal 2389 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 Hu0mjfUS4{( diff --git a/src/chrome/android/java/res/drawable-hdpi/pageinfo_enterprise_managed.png b/src/chrome/android/java/res/drawable-hdpi/pageinfo_enterprise_managed.png index 9b7c9aa3dc953e4ac890d9c8e7e2ce6b5a6ce860..ca9f695e27836a45461b32e606a05a3990d52ac4 100644 GIT binary patch literal 3046 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 literal 839 zcmV-N1GxN&P)RIL_GJG5%$#$QsDuz`W>jeI zhu`4(otI0LQOXR3B+Sf$c1bYE%_)lVRyC}SjGcE-z7?_sMq4uEi;jWp4(5S+*(ew^ zbgfS{Ere_vvNi%ci@>q7&|;%Ra2y-*g#sWahp3kufhbnSteM>1Vmx4GYP@8 zm}ah+^SlTKF~-O=4PY3$4w|N>f@v6@7ip7tNvZ<$0(t=uk|<15RRX$LS-P3l+zTEv zqOtT%s)9N2CqEuM6^Yu9DRAd!<1q-tqoKv8zI}n&S~aE}gvO7jR*i25rO6oMMb>WF z2kW*SlEobUF=IR8K!du8pryE47IXN-h;aw851;t^S9jp`!)vmb!`EntV1oqvz&IKp ztPz=jBNpq&C%&QF1)JKB$YKtEe>zQ~85TIjRnnL<@oW%AZ(oGr{-dF&SEp&$&xJKe z!3?s9>$;0fj19qy`&VS~KQsOPE6mlZp=yx36KXI{>OZHc(b;e{hzW!IiEpvZ?T2A& z<)kd;M9wFF>jlq2zRmI@W;JK$SIS~e+ zuR0t!sLPdOuzl}YSb3@SCeHC_f^~8dnaX?YEutzL*l&YJwu$Mzi>zX)VYcq|I zUCbd%D2fic>41p}alqDQ8a~aSBW~Ur)HJo`*-szOi(s&==zJm=^O=+y><2_^!TBs0 z+}&Op0D|inyFgNUy1zH5-npaHFBm+3yfSj(MCH=5qVs`ZQk$Q1AxW4f)t+P?m={@- zOm!b9-y46>duH)V@@e46JWPbku R3)%nx002ovPDHLkV1jeqi)R1; diff --git a/src/chrome/android/java/res/drawable-hdpi/pageinfo_good.png b/src/chrome/android/java/res/drawable-hdpi/pageinfo_good.png index 232d62c2e968c60308bfde81ced0b940c8c7361e..435573ffd0637eb30c4321f04f9f9647dc5523ac 100644 GIT binary patch literal 3286 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 Ti@M=F00000NkvXXu0mjfj90NX diff --git a/src/chrome/android/java/res/drawable-hdpi/pageinfo_info.png b/src/chrome/android/java/res/drawable-hdpi/pageinfo_info.png index 6a49f5bdbc425b80caae3f9086d4dd57fc1c3bd3..708583d2a95026982c30a51a3815bdcff70afdb3 100644 GIT binary patch literal 3067 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 literal 1548 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 Jm5T4f{s%Y}U~~Wg literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-ldrtl-sw600dp-mdpi/edge_menu_bg.9.png b/src/chrome/android/java/res/drawable-ldrtl-sw600dp-mdpi/edge_menu_bg.9.png new file mode 100644 index 0000000000000000000000000000000000000000..c25099847830c342e5de8cb6f3795186224f5ef5 GIT binary patch literal 4033 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 P<^Y(6o_dX{b=3a=+Ai1- literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi/edge_menu_bg.9.png b/src/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi/edge_menu_bg.9.png new file mode 100644 index 0000000000000000000000000000000000000000..4424cb2096dd8357a816f9102d12ef4d53df4a85 GIT binary patch literal 6399 zcmdU!_ct5R|NkRmi&{mES~c3*d&LZ?E>x>xg;0AGwPV%Z)T|aYYAcEw5qp+O%~Y)h zp|y8xAMbO%?_a)u!RPbCz4x3uUiaL4?(1=$&vRq+pTfY@?9>1N0Id4}`s}(*zAm|x z~~7v({#&344pgQSH&|_jMXTwFz_aPE^}f zvitMd7ya;s>D5NuwB2?ft_7ff{ub2r#+W2TCf}HOYrWHqk!h%h2xOxtp))4wz}wn_ zV8>A4#5o4?{(b3#zPh6=u@D>dj7Yn_py$+8a0;Ki)*W&Hwf3Z(N{}Ec0hnf3*LzFq z3iSOT{jOA`q!dd&RY4`+Qctz>QOU}E^k7z|;Br1YeB@TEOl~|{e?D6PUlFs1(Pr0FLgMeBi2UOMd~VcOh3N z;4AgEc>sH4fcp85`?n*VE#CDk(hAYUZEQGulH@sw-Ty0pmiN}}dwZlJ@%_-&nUQia zt6C_(?oH`e+Jxeg;z!WoVOqLOtjz_H{%Wa1(c#Bnx5&r54%Xd>zb_2_rcs5**rOv< zLXDHfY^cM7C-K2-azYfhf^wXg?Y$6yzz9YCCS8gFHwZwBpY)Eanm;gb-IQLEdZ4Y< zzAB~KGfB$-a`lv(#w^wq|5$_1aOH?L$;LyVK;%~8Lb!7$kTIF!%_nM^P%#Ohh$Waa zMEW)9JP#l|nAAri^Mz3@ikx~)c+^w>07zi`Bc>d4MV5+w7X4wP?q=x-Kilqa(k-FUA#MbBYE>8GWkufR;&s}++>|4#knr(h}D zy|D6pEq%xV{~PueO7pPOPZU3SWXLZ_0>c@yfa6x+Ux05R(>2PRl(4R$KTzMBA1PQn zX7CT2SXAj6yIAoYI{=XgL{}=M`T!;AsE#ou$1YSe+4v3#1FusGUlFiOJ3E=Kh@&~- zL5lk_DS1@BRTdjd->s!6csw3yWHp6+C^4C3on`cxbw$pWUOM#T?PugmGUB-p-aXfv{dg6 zUnIR>j~ViAZQ?JDR$WfPr>V@kk#|_1-MRa|KJ>Y+BcHh-L=eN9I;dm=^I(IkTj+hc zlgEP)xbaR+KTTMWS??jIw&wIx#fQ!6e(HW&pPzwCT_=povs!XY^f1uChk@d-RO!t9 z%%#Dq)QS|R^!3aD0lhR_rcWk9EKdl*8~pIH_`C^d(5c>O7+P3kl&^!Y?}9|=YG)Uu zBcqYo$QWeUqHM2$Ko;UwgPo=iuqMvHcLcDRg2~-AXV0-b;fpuPwPgQ%-@Nb%4;;5H5&S8>OB%S7DrSY zZ0D;QDP-uh67Wxlh6Rn|ti8 z>XNBoO-zpNJKcoACx*W!=AT=(VC%88PAm3;G8MAu{(_oWIJ{D4>XTx($^fd+@59M` z8c3XRTn@_|3qoX5#87lygd2VrPG;;EMq%iPzutHYqr(Fy8P@;en?`oymneh+glfli zOBQnABX>u@BZV}ytUIg|qHG?c?)WB7j}$Q*v3P{<>->oqGwDkv>!-s{a0#p4JuW?S zzaY~WO=tISJi3tri|bD-NnK^f(pW@iR=-SnS>5=Kh}?GEE>TrdjZsZdWoq+os|XZ7 zwz>dbc%RPg<91e0ac6oU1yCi`U+N-|4#P4N=EtwjQ$U&FU&BYC znLXw)*1BJGZ|W`q^)wp(czs3eg)Wz+C8rhMl`b1C`{58?e_TJVDPR>_bKhJVB7_m| zmMN6bYWeOkx%GmnKz%gjv9KrH7M+!N`S|cb{GAU1VQ`u{$FK8tuvdBC4Tc$34wkc* zU5B^^_Xp2{WNl@AyzJV%FC))8Ww)H@sv@Son9Vdl^)c^k!5_A*C%N#rJeb}Y(iuv4 z#j)TTJ3nFY$)Kjq(!OqcrBAb2(*TbV9WkYI?sdNDyg6rESLHa9$!9Toh#XpsUDOkp zeYd^<4}5ttH+&SniTQl=`ON2!H>J<)+`pE6^$(PEf$#o^X>#JRI z?{~ZSbEp--RPj$=y0G~eq`<4VyV!rsy`4*|GVK=|SpHAwBJb$iPm@@a{HfWgm~TaL z4grq?7XF2d=Wva1iK>0LLLI~(z0a=uZubbAGII0d2gN*}pgqmLh~2mt)+nWyZ&X|A zm&bCx)O?vA3eBvx*lqSGo57r&zsRhx`=V&B9GDY`*^InMn7WP5%|L7fIs9wbcES96 zU3ZbORF&997Pxw9ekMMD)DlQYyvpGqjUzwZ5^D>%vY3VZ3!J|gr6{{$p*HNVaAAL8 zy|GjvM6Gu(w_L62V)7VgTZTE<_=K~>)vfZ1%dq!#>UGv&RWNM) zN&K9D?LqI(P<-b2QbhaR%WuT=(TcnvpEHada|R)+Qa$MHpSDaBbQa1zsuu3 z4%@{gvGWyeYDb|L`DfM#{VD%8^p5q?^Agm2P*mr8zJe~cD+|Q%{WB>gcn|5m`|Sx7U18612ZF|E|G^JGw-zkDvTg9! zZ~fwH`+@<#o0@{nVdNi$4YLkWIxa0V4TUT=vbef3Y)Y?KB zYWdAlkz#!+qTSN*ryMl3?HCPl5=HGT!?mol<+ z%FOG{4(B3K0@)v*?Ij`CY!v7DMfxThezOiOBkwpI_h0ny+e{8)$iPdS7-xJN(9NYrIk-B6()J@Z9Ba zJ%&$r_lFAig#qo>(E!d96A9^1(c5}*G{n!x%M>g=Rg<+!k{D(+$k2$H4Polb39*V8 z63Uni^p9`vn8|+{a&|jxeA{yl5w%4{`S#UCq0SDqnoFrM&k6O}Ks0-$rh=p!1<5waa5-quaveNijNX zOn!$jlo@<^Fs>IIcy)Q9mZ9DL>+AdIJItW&;7<%Uni7oX5W?q64RFcDl=P1Iz{~R! z>o~jS7^)=b!PXp_IJ9;uu!wsA922@kGN8@Be^WxibMj8ep7HD+!`fB9U;SK!yIPHT z61Jk&Pbo=r$!H8!l)kT*Mw-;%gDJ+Uv8Vkwq`A$bUv^y_^ik()J40diHLX*EbRoTb zx5LD~gclS71DUN)_-PNt%2ZS5Lln}Yd&)d%x4&{q^lqiL*RmHcMeOpP3am*J!O>c* zPnWqaUny>dSv8t*_Gmrt&??Js-bBgs&>b?AEE;jI`cu86MN>gL4u8U0O?ot>=vMOO zpKv|)Aw6g7sEebZ9U8hj)oD?%lSB0Yyi1Z_)jjA6aJQL#x0J4uQ5}YX9wmeb7rLc4wCq6^qx(RcH|7p|(%cZeIR9;zv3n zaK0zl^Ocj>X;apVAk$Qrsw@8|y$!bcsMPl%^lnBqsSZk`df^<{tLgTT!>#y@{slQ- z-fd-KYrn$?13lPvNsDdXyN%18m@5z;@rCHmx|hMdHY zx2=-yi1CmZFAs>i)wsMEkg)SXi8YzAHilwe#!F%jY@^a8t5|7~IE#z|T;e1uw^&3t)z;7(F@m#*FE*S`{PJh3Sh;tE+scU}o!EpLa~t2!6eY%<*4l&n^JH1k)pfU zsiFlpwB~2;2RJnKv<<8`hgiJXiF3wj1#NPK?Az<9;mDXjo|2 zQzG!t?GxGayuvY#Zy^uI4TGCm^aB$gy8Qy)d!lziFi}5Lyoa%(DV2d7W;&5fu9hA| zihde9m_U5_-?Jzmly-3yo@vpNS>Z{_NPo4JrDS?2I6kX>#UKZMApjVD2x6Ri{j~WGMWDyLvu{@SHD@Ef5`u>8kq%fBC!V_%iT#Z$2*1`Z$^o&BnnAK z2T#R#-29K!xyORaIF4T^a8Z>`d>~3K9Fo&pv_P4YV;!R9xPJa&mZxuilj}#~7_A2f zrGY0x?7)!2WwF!X1@%6GR=Z~Bb|Ejyfw*n1HOwZiEj07bkq*>AU4C%g+{Sp*X>D^6 zY{O}rb*j^Zopq#74gt%kEvgn>__=oY#jEriyAcl2ZZRRkdpg9y#vCH~M?K=9j^v7H z#CrUmo0)oTmf+4%>1FQjfAR+d>vM?&FWe#-4gaj+-ZRjUvq~;?8=uZ;LRRbFE8=Eq*he_K+L3K)Vfz)BlheEchjkW>Qk@ zz9#DGgrDsdEx&v{<-iBOWKeyOYT)TXH9q`lT3hISACAnIPx%*O6_=UAtjngI1$k~4 z3*IFTMcv@OoZ|bv<;)KI7^CcKR;l0>bh94|tb#RNqbb7e^6J@D{U63u$tz6Z_YgMn{s(BgM_UbmIhXwc9 zlC+A2PNiM%9da&eXfXlw%j=y=d+^7QXd!CBJ_Ge(501dz zByTy*4Ay>ZrNk8vxkN9jhl?8ueR^2y6FSu`LbiqYidUwN76h}NJQIbrv5ZwGseZS6 z%TOHVYvUEY`*J6CN$u-RI44SoKF^Ffeww!MjC6=LQ)p(s05T^=3*;jXn% zC0blqgf0(?KEj!K9OzQu&Ja4}F~FpjO&IZWLpJVwVny_aV{g z7`bIuOLr`A8q4J7eTV1f-+ac{L=?2Z_y*5NrQ@~o*gE+R`5mf&@mUEQ)ZrE}VFfqS z@<$z_S-%Awfr@lk>Do2B7$}U`ke-z`fAM5`z4K2p;b4iFC-x~e76l~KeyVSb>zLVY?3b@#kHI~s?3{A^!FlK=!sNlEwFD~FcfPF<*~)HRfLKOUI$Vf z=5-BdCYiHSu{0(SnC#?M>arBy-}Lq^2!Y-kYT6DI0F!K*;YVPJ>_;T~D$NPc!_%k$$n6G|aMkOnZpv+;kiCI9>#|8ELO+|CQU5-? z^;&yB2Mrq66lN*G6N!{@l3p(R9148NDn^FO+`SWnYx+rE&Z0H!i<6qAm;DA@NMc@? zUptB`&r{>{Y#6LiR?gj1r?**Ay*f;j05koT0`PH7U#79%vI#?CUxiD}0*>tU?z&MWn@h|fH&d4G~Y zNfdjx@_rb~uMtsaXV+$?=-SMb|JTegM2cKyv??(q)#8#o_-6xVxEIuQTFPO*861~SH`!I2ZvvMnVBbChbW zGw~C&);}#0v-!^$r4w^^+4r!5lNLd4eHJ4+8)%r#Z9?EFq+uR+**Mn$(QGO?nlQ4{ r4c?{5`~4-(VvT%c4@KO+q;R?K{=IY^#&G?y0npWc3jLyK`SyPR@3@qU literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-ldrtl-sw600dp-xxhdpi/edge_menu_bg.9.png b/src/chrome/android/java/res/drawable-ldrtl-sw600dp-xxhdpi/edge_menu_bg.9.png new file mode 100644 index 0000000000000000000000000000000000000000..e7c030de21f7256f209c70a7f5f4cb3614829c15 GIT binary patch literal 9638 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 a`u_omfTzW?b!#aA0000X+uL$Nkc;* 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 N002ovPDHLkV1mpyq+|d9 literal 686 zcmV;f0#W^mP)ro#ZRDDD^?q6lFf|IK7=X5bQ1%c4L|;2cjo!+Gc!qK=kTPB+(s4< z5i&npwQV5;L?VpcV1`w&+(agpNQ0ZqfSVc!1t*bC8+NpSjw0X{0mkyS9hguYv0K(!ofz;}=g0n;?VLi{w0NSIJf|B^Ds z7%)r_0tDxwf;CkcfB^c49-zqt!ZEmzlxEHavRqw+W}`00c0iSJ!F6~rzkYm!TCFO_ zc49>quvg7yli0p{gmTB;QF*T>JLCU_+8Gxbp63ytDvu~XzIh<;389Ya`4b;dGB3$8eZJL08j3m(y0B#uD!ZaE1)ypVnz1;^*zc;=`Lj_78kxleYvXC zQakhQ>N?BGdxlR^?mKc`D?E5`Tp5F4XTPbl;5`!%xMy#lPgBl6yQRr0FK6YLHv6f{ zgnnG*I_nX7X9VvJQf8XQ9}@Kt-$Am?8`sQpI@pGOD_A0WK+fb$B-Ek7p(>ekflZ{XBQ=SeW=V{n{JWWxo2de|0vO UA=!t6#Q*>R07*qoM6N<$f-O-v6951J diff --git a/src/chrome/android/java/res/drawable-mdpi/pageinfo_good.png b/src/chrome/android/java/res/drawable-mdpi/pageinfo_good.png index 9a7cec781e857d958330c1c2bd3c39c74b486381..bfe73579d42d50b862fe119133e31f36c18d43d9 100644 GIT binary patch literal 3095 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 literal 1170 zcmV;D1a13?P)vmsfVS^>ZS+VY_RVxkWa1SAZjZPnGH;7qr}E2lq}s{l5&Ow?-r zY`sy8jW!(BDpV>!5=hZXuqvWo1<^Xk+Fp-6?G`)ty|d}5!*5>t$>url)*F6oe6^#| zgy9iLQZS|r6B8!_5U+h7pxW2>Ja`XmwF=OWQ~~52Y+ALSjjNvH?&fwxgex~@xbWN8oWFLMtO_>lGvFf-10?EC ztuY=0L9qd#AhxYL$YT$@j)?T-z3|YzyLfQjE~+!@IrGcgR7W8jE(1jswgO9x0uLmS zg$E{9?&r~o1Kj%i8sE-*%GtRu0ob;T;0sv4avBj?0v+PmiMRUE4=w5B+&N4lOh0je&G$_6!^I<1GDuRD2rA7|VS-l} z#C0}Ga|NtvZpVA!ySZb1P-7L;n)=?ae|*7C|0)~SOww9_b_<4TC73G01X!k^hIa6=dJqG6C<^f6aehfoa2|R+%|JZl z9=zA_UWdM155&ccC}md8MuA?d@cFIB8Og`{kso|{7O$0vs11EqjEwWr?$0@TYA@X` zq=lY6LC>TNRHKVd&!8<}BNj+Gv*`2+(wn=do39fu zn_&Qkn_h!34oMQ{Bg{>N#f=Sv zdj0d&*}dGn4)Zsmy%^uoCuV_xEQgUMeV|Fout2lka|ch|hkZkZ(c8T-4tWh+ffi7C zB?61YDrl$*CLQ<#)B>>1ajIMJLQz1Wr4ORZVKbI5+u;J+{>_9024LgIB*%lRH~ zw%6s2&LU5@7OAHeDisBa=*MXSNmg2t7`uj`^ua-unc&W!r7e-?w^d@^*Xn zqs95#52qEz(j{EXO4b2IkEdXaK(07aC+vOOS7NJv%vj8 k9mx29o-S|)xD0gu1?foOJdt}XRR91007*qoM6N<$f|lSGWdHyG diff --git a/src/chrome/android/java/res/drawable-mdpi/pageinfo_info.png b/src/chrome/android/java/res/drawable-mdpi/pageinfo_info.png index 57572b7039020e995242fa85c5441ec86cfa7233..eacd1d0d5f5a93388e9fd747bf71f668eee8e6ff 100644 GIT binary patch literal 2929 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 b2{Ic1+f6fC!Y7`I00000NkvXXu0mjf6SAdA literal 1130 zcmV-w1eN=VP)%POpdh>=tx7HX3s2!aY0Rth#2YN166QJa8;3R+l1EEKg8 z(x`tyEEYi!3|Pg8Ym*f$G@H$`yZ6mG$9Z$k?95wR2fjBmhk56l@0{<=b0UIskG;Ox zb=^m8*IjJecGG(gH~@nD0TEpaq=aoJQtc%Jx0q;)D7i$tR!1Zsv!aEBA>O`eCACidOi%{DFBxuu17K5dvl`Yl@;`-dc**n z_bSW?q*5o!s3f*u1dNcufidfbsc-#N0ME?Ho}5HQlSnjI)-)~PG_f)ig_cOyoM(-Z zaGD_+V~Ow#c#r*~gGT|}-!^SK?PBR7s}cd}FbY>99}aF~IJ^VlkdnG?32nCw-%MZ} zMr_JVy7oUF0#;k^T?#noavxH52UL3`qH9+#V`F`q_CNl718;wL4dZ?Tky#ZPm@D;? zEr!NJhsl>kMX2^1l*q>8k6Zv#Ksee{LzJFIFqkt6n->9CT~&WU!POrB9l`>d-G$~T z?o4}5u2e$dOjcNQU0lUxa%RB!4mbbUK^`}^cM!telt?eeVAy=zLrF2VinYfLHMgBC zB#W+_(F$IE>r;qOgen3bz%?7DqE4PkBdYeai?2X=9dycsE`7l{52BEwt~~|sPse$= zC_8qfl(n`=%cym=TM27(Aqqx>Hheg|jn6-L6w;T!r^Z2aY@bqqY$I?Ou*pkO|t@)r=z-kh#)Y{ zAoE#}dgr=TJ7amcn2mHUZWL9LQ1%8<2(uC-1cNM;jEu;!#>kX1opd8B07Z)1Bgudf z5=4m#IWkeM4x8aPk%*}?H*!VB09^ITivlQ#m=r=_wQBz1=Dw9uT1;SM*1rfgGF2p& z$cU^YT%EJ>IAm2IVzoOjdO)NuV|ANik75ppvjmg?)ub_>RTv?*fJAS|X5d;NYzGrmAi}H;{G}t~m`~ z44{1isy(XLhq1BN{{(s^_nE(I) diff --git a/src/chrome/android/java/res/drawable-mdpi/pageinfo_warning_minor.png b/src/chrome/android/java/res/drawable-mdpi/pageinfo_warning_minor.png index 2c6318b5fde9c20b6e8c20ff8a76f7fd7a375dd2..a0efe75ee9d8eb7e02f95dc1337825bd255a149b 100644 GIT binary patch literal 3106 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 literal 1240 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 literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-sw600dp-mdpi/edge_menu_bg.9.png b/src/chrome/android/java/res/drawable-sw600dp-mdpi/edge_menu_bg.9.png new file mode 100644 index 0000000000000000000000000000000000000000..ddc7409035b20176868948aa1899c93d35830dee GIT binary patch literal 4041 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 literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-sw600dp-xhdpi/edge_menu_bg.9.png b/src/chrome/android/java/res/drawable-sw600dp-xhdpi/edge_menu_bg.9.png new file mode 100644 index 0000000000000000000000000000000000000000..4a3f5148f756d373d59700ec7a3c665658652803 GIT binary patch literal 6339 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 Bd42!@ literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-sw600dp-xxhdpi/edge_menu_bg.9.png b/src/chrome/android/java/res/drawable-sw600dp-xxhdpi/edge_menu_bg.9.png new file mode 100644 index 0000000000000000000000000000000000000000..da8bc44b36fafd9f1a7e06fbc4323f0366689363 GIT binary patch literal 9541 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 literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_bad.png b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_bad.png index 00d8f60f331328fc0ffa51a54f81ffa77ff1f341..04a8b8db118f96abb062897798740a32c7b74b95 100644 GIT binary patch literal 3605 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 b3UU7fDzzsGD^$Me00000NkvXXu0mjfmp1g| literal 3675 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 diff --git a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_enterprise_managed.png b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_enterprise_managed.png index c5fda4e3c97ab6313f45044ce46acbdde7681d85..bd64cae74433fe9baba83cae4b30c3d7f4b6d7ee 100644 GIT binary patch literal 3113 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 bjH3Pl=O5+jb=Z!E00000NkvXXu0mjfh9~}p diff --git a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_good.png b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_good.png index 4d3c7e22d2bfc0d0fed50eb3a11f7913304b0b0b..4981f841d8afb83c1fe0c70c4633d68e1b2b9c74 100644 GIT binary patch literal 3513 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 literal 2765 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 TiMZns00000NkvXXu0mjfGUzYq diff --git a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_info.png b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_info.png index e61cc26489b1e2c862628b57020130a0fef27f44..8396a96a555676621ece82fdfac33a61b168546e 100644 GIT binary patch literal 3132 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 T8OUex00000NkvXXu0mjft{Zg% diff --git a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_warning_minor.png b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_warning_minor.png index f364e978cfd6c790bf984325a4158b87437b7389..e03e9f209713b577521844bb314d99bfb3fc5163 100644 GIT binary patch literal 3585 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 Hu0mjft?=)_ literal 2071 zcmV+y2m+qHrF9ZoNYYCR1tAbZsD=k55SJ(T6W}jE;syG| z3sRqWK|v&>N*hN4lC)LQTx_Lolh8P^1H_KKyWY8-!}&hV=xDUsO?KBQ-k$L<=j@r8 zGv9B1-}%mEVkxCS>ENN4JX?sL3EO^6SYkIU^Z^z&W>WN5mP%fdN%BS_s<$@4tewhha&u#pqlog@juFhm#x=ff!c#@lb5n72roLZNV`r`TKa zeIK^t5SgwZ#H8XFK@gz2R=H5C)%H2A>;AM@>?swBMN%er!v;_M(lr5CLO?<7(Te@V z@jZWvlp!)*n%H*Y5QX8C<9hDXOa`n-SCi6Q_Buk?o@EKB?&bsHpt<;h3MO?wDMx`1 zdGHkv|AhK(K?+KxRFPob~B-!x2y+X9>VH!(&=MzC5gMoLLYsjzF;PK=K~nbp<}(59%+*Vl^!2liujb`~=;vk-!m5*;&g=pls8 z=2Q~9cc)~iJ##kKwn|xJa|&fHIRqL6X3g!{|Ro#Qz*XySPJ@@34; zeTe1dWq!uMz#v9PNAQx*$@(Ox-dyz>xF)@MT$8Xbba=*3}64XE&Nc&BK z;o%+Hu%0YblQP<{W2jWhC=?6OGkKb45vWXc`dkGk{&t*Z%6uOk#bQwhlp$)9+iuq` z)?Kv$DY@_H&^(-}!?<$g3RYIja9v-+gQFF)Z3dO8j?b-@D-;k+dm7s{A!?J_ZpS9H zuMmUZ=9Vp=$p%lx_3PKP!44q{#~Mgsab0%)#*OQ2Nv7`L;2^iziA|0IH`qr1VV7eU z%I;TCx^pkX^*l1Z!MZ9VW@Bk-32~Bu+fs^EjN`EF6|-tTC}eI2Si&}h7;JE}HnVf& zUcB0z7(0tyqwisLbu-SNOK@|+NoUXElMM=hhEa#h7BUsk=w3RD%>hF=wM(~e7A%m=)STt=qO?a`M@f9G~HAYU=w)>1BVp;E+g(YGn-*PfTOSqZg?HOiEFn zq>z~U>H>cCdOvIq`}PCdCfeN(dsdU7ogxrHJ~9rhxN$#2h9g-N#&DfGc)m0ZB#Mn^ zB!nf)eW|4vF6iQxASJmBjrwVwQBCH4*CUQ%tku?VXzwXFq73dk2_Ykr zsYFD9*IvGbFbL@dKCpd4qa{L8<9-j2xfhU<;a$!MLxUe+{PXXoiWp@egOs4s01yK& zJ#!6P`d3*cDdhv$hn8K=ED5s60u$j(z%bDcNMAynAP6fsGWlj+6(*A8h!Ci3kxGYe zA`F>O=PuVdm<$_Js|6^Hp4D&sh6w~jCW-T8l006WyoP?CREi%&r49yG)A`e!VN}xK zLn_`-cdR=&_|!=z!AJ;osu)Oyz7P1`^Ye(JfQE^OGq57fO`#*wjuaQdkn~Artkm)OCwwx`ovqL5lVH9Bdzz5j%*mP4>43YXe z-v+)j`LR|hB$d`%Av3lx8mLA79>pyJUB~2EA4q99f8F}+_H6~<=JopAdgrfcLrba?F_^s;814U>;*&vJh)P7KC zq>Kp=Qu6EoxBl}vqe6pz(wwlthl@zvtyxe&o0}w!)5w1#6l_|xC_;oeGbi|$pA z|K0Ygr@ zh4W`lLf8Vr5}f;f0eyY_=EZPvzTYFIia*p!nE4HdFpeDM|Kd47uvyqKa5 zgAG;d^+^$IwClPI+jd&o&I-ez^$%W(-@bt3I-Dyd*O3rG@IC^!4fXIpcxk~ow}k^? zahP83|4czJ&r+YnCrQgZoQ{W-+EPdW2=VDjWk*W9rxf<1yHh$L#w8(T{DxU$bT5bl zaS?GGzn&z?1$23mQoc`IERyQWUwL6zkHSZVuuI)ZCb)qgerUGC_d)FVMDE!^&>9;tz{SWyN3+oP7#7qDH002ovPDHLkV1nVS B>gNCe diff --git a/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_bad.png b/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_bad.png new file mode 100644 index 0000000000000000000000000000000000000000..8a5eb2048ccd513ff5c1d64f7d9ba15de822de58 GIT binary patch literal 3991 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 literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_info.png b/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_info.png new file mode 100644 index 0000000000000000000000000000000000000000..f28543f375959451ec106b77d216624d4396defa GIT binary patch literal 3342 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 literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_warning_minor.png b/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_warning_minor.png new file mode 100644 index 0000000000000000000000000000000000000000..0a7fff16edccafa609ccd4a799e2733a31d23c25 GIT binary patch literal 3931 zcmV-h52WykP)X+uL$Nkc;* zP;zf(X>4Tx07wm;mUmQB*%pV-y*Itk5+Wca^cs2zAksTX6$DXM^`x7XQc?|s+0 z08spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO_(THK{JlMynW#v{v-a*T zfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH1j_W4DKdsJG8Ul;qO2n0 z#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#itsL#`S=Q!g`M=rU9)45( zJ;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J<>9PP?;rs31pu_(obw)r zY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q7e9d`Nfk3?MdhZarb|T3 z%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|xfmo0(WD10T)!}~_HYW!e zew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^Xswa2bB{85{^$B13tWnB z;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^BfHQCd-XH*kfJhJnmIE$G z0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK<41h;K3WmW;Fah3yX$XSw z5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%HgQ}rJP(Ab`bQ-z{U4#0d z2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG;Yzp`J`T6S7vUT504#-H z!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0k#Xb$28W?xm>3qu8RLgp zjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT=5u1%I#8zOBU|X=4u>;s) z>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l?}87(bMRt(A-)QK9Dg3) zj~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N5P8I0VkxnX*g?EW941ba z6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|XrzUnLKcKTwn?CKOLf97RIe zPB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhvt&^*fYnAJldnHel*Ozyf zUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZVwz%!VuRu}#Ze`^l7W)9 z5>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP=)Lp_WhG@>R;lZ?BJkMlIuMhw8ApiF&yDYW2hFJ?fJhni{?u z85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$RAwc!i#egKuI;BS(LSWz zt39n_sIypSqfWEV6J3%nTQ@-4i zi$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^u!)^Xl1YupO;gy^-c(?^ z&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zii=7tT7GEswEK@D(EFW1Z zSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcHnq9En7Q0Tn&-M=XBKs!$ zF$X<|c!#|X_tWYh)GZit z(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z{kZ!p4@(b`M~lalr<3Oz z&kJ6Nm#vN_+kA5{dW4@^Vjg_`q%qU1ULk& z3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFjair&;wpi!{CU}&@N=Eg#~ zLQ&zpEzVmGY{hI9Z0+4-0xS$$Xe-OToc?Y*V;rTcf_ zb_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ=k7SRuGN`h>O0Q~1)u-yD z>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEidtwC+YVcg-Y!_VuY>bk#Y ze_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{;Ppd$6RYV^Go!iq1UMl% z@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2-|2wUogK~{EkB$8eDsX= znVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gcj=lwb=lWgyFW&aLedUh- zof`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*%^u_SYjF;2ng}*8Ow)d6M ztDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@1equ5g71C1Y43|LteQy)}H!CItH`oSW!p9=jVf=E;}#>9xP_-KtpgC=P40csO% zwPa0wV6hcqwb5iF*$v6&_Wp0(yLUCabN41Q6WKX%li4}v%$f7MXJ$8d!)O#0Ex*wB zxksmUL|PtcG&rhCftF4$iFALDM&%8))n!J;ID@jDh`TXyA3wjq?IHfpa3O+1C;`#05J$K)T)9MAO-=3T2+t~;>s|sQO zN@wV~s;A~oqIt7t(EC%T(CAU4$m<B+NabgS_WUA|UNjZJsC&Lh#_+RVbG z=7XU`M*XdOZ~Qpg^wkCvjFYheYRirididxsC+7WXBYcU?otaPN#akT1LAIzc_`p}R z2(2Jg4ie4E%(U`s3k2xO^#*GG=c#!?G3MPI^D3B?PeZ+4%QhGa(YmiU39Tfddk~gY z1Wu^4lMWs~NtIRA)X@>NAlMt(*;%w^xsN_wwSqDR4KjT(#)facvzu{k3tM8-awo?u ztL>!~RDSqaTsX)Y;9yg{XP*TD%MF{mC=mvzV0Lu>xPIeTI$3khagMNsPeky}CrX3? z!kv%EPiM|XnvQ?lee7d79>ArcFhHYoa;zyf-FslQoi^+~_OYD$yR{Pr$U7wZJ!Gr# zK`>dd``E`ycARAGg#pUU$gt+t-Q8`qoi^+~_OYD$yR{Pr$n6AW`zb(-JHYjm^z^)3 z`lM(%%g( znRv?0#k&ZX8*v+x6)U>yu`D_38-BY@r_R=yQ5MXbL-`*}=N!@5@LVd$S?H)$I2@*J zCFNEJ+UOeyG9Um|)zrp31jD0M^bG`&4ydiYok|ZJd4mP|ppz}q0qs3dNr9KfKbXEI z=z~tSNCougqrZ)%6#u~)bg+>rQUPr%DWh;tPu%>WgN;m)1_)mW)*El_EP)MdWr-9( zU0q$Yy)^nDo|Qao;Uhz&06JQAnjSYlahxw~;UhzY18RBEN)?sIlg<@B@D(k>0qw3h zNFBjY(s{xMzM@4apg-oTLM2gVA=8Jrb3D?^s z?r-PYlw}|0$_3EVe_Q%6C3mj8VsZg=mJ|P^$`3fEWZAYE?lB5Q6|ittvzq literal 0 HcmV?d00001 diff --git a/src/chrome/android/java/res/layout/website_settings.xml b/src/chrome/android/java/res/layout/website_settings.xml index 074844b..cb614ca 100644 --- a/src/chrome/android/java/res/layout/website_settings.xml +++ b/src/chrome/android/java/res/layout/website_settings.xml @@ -1,30 +1,38 @@ - - - - - - - + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" > + + + + + + + + + + + \ No newline at end of file diff --git a/src/chrome/android/java/res/values-sw600dp/dimens.xml b/src/chrome/android/java/res/values-sw600dp/dimens.xml new file mode 100644 index 0000000..d8fed33 --- /dev/null +++ b/src/chrome/android/java/res/values-sw600dp/dimens.xml @@ -0,0 +1,11 @@ + + + + + + + -6dp + \ No newline at end of file diff --git a/src/chrome/android/java/res/values/colors.xml b/src/chrome/android/java/res/values/colors.xml index 06730b2..66bd267 100644 --- a/src/chrome/android/java/res/values/colors.xml +++ b/src/chrome/android/java/res/values/colors.xml @@ -28,4 +28,7 @@ #ffffff #777777 #33999999 + + + #5595fe diff --git a/src/chrome/android/java/res/values/dimens.xml b/src/chrome/android/java/res/values/dimens.xml index e1b6b0a..72172f2 100644 --- a/src/chrome/android/java/res/values/dimens.xml +++ b/src/chrome/android/java/res/values/dimens.xml @@ -6,7 +6,8 @@ - 20dp + 24dp + 16dp 65dp @@ -16,6 +17,7 @@ 258dp + 0dp 15dp diff --git a/src/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java b/src/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java index c4660fc..fef7090 100644 --- a/src/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java +++ b/src/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java @@ -56,7 +56,7 @@ class CertificateViewer implements OnItemSelectedListener { mViews = new ArrayList(); mTitles = new ArrayList(); mPadding = (int) context.getResources().getDimension( - R.dimen.certificate_viewer_padding) / 2; + R.dimen.certificate_viewer_padding_wide) / 2; } // Show information about an array of DER-encoded data representing a X509 certificate chain. diff --git a/src/chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java b/src/chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java index 7e43f06..d2f9e06 100644 --- a/src/chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java +++ b/src/chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java @@ -250,13 +250,17 @@ class TtsPlatformImpl { mVoices = new ArrayList(); for (int i = 0; i < locales.length; ++i) { if (!locales[i].getVariant().isEmpty()) continue; - if (mTextToSpeech.isLanguageAvailable(locales[i]) > 0) { - String name = locales[i].getDisplayLanguage(); - if (!locales[i].getCountry().isEmpty()) { - name += " " + locales[i].getDisplayCountry(); + try { + if (mTextToSpeech.isLanguageAvailable(locales[i]) > 0) { + String name = locales[i].getDisplayLanguage(); + if (!locales[i].getCountry().isEmpty()) { + name += " " + locales[i].getDisplayCountry(); + } + TtsVoice voice = new TtsVoice(name, locales[i].toString()); + mVoices.add(voice); } - TtsVoice voice = new TtsVoice(name, locales[i].toString()); - mVoices.add(voice); + } catch (java.util.MissingResourceException e) { + // Just skip the locale if it's invalid. } } diff --git a/src/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java b/src/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java index 887ea4a..51b32a8 100644 --- a/src/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java +++ b/src/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java @@ -10,12 +10,11 @@ import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.provider.Browser; -import android.text.Html; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; +import android.view.ViewGroup; import android.view.Window; import android.widget.ImageView; import android.widget.LinearLayout; @@ -35,12 +34,14 @@ import java.net.URISyntaxException; public class WebsiteSettingsPopup implements OnClickListener { private static final String HELP_URL = "http://www.google.com/support/chrome/bin/answer.py?answer=95617"; + private static final int DESCRIPTION_TEXT_SIZE_SP = 12; private final Context mContext; private final Dialog mDialog; private final LinearLayout mContainer; private final WebContents mWebContents; - private final int mPadding; + private final int mPaddingWide, mPaddingThin; private TextView mCertificateViewer, mMoreInfoLink; + private ViewGroup mCertificateLayout, mDescriptionLayout; private String mLinkUrl; private WebsiteSettingsPopup(Context context, WebContents webContents) { @@ -49,8 +50,13 @@ public class WebsiteSettingsPopup implements OnClickListener { mContainer = new LinearLayout(mContext); mContainer.setOrientation(LinearLayout.VERTICAL); - mPadding = (int) context.getResources().getDimension(R.dimen.certificate_viewer_padding); - mContainer.setPadding(mPadding, 0, mPadding, 0); + mContainer.setBackgroundColor(Color.WHITE); + mPaddingWide = (int) context.getResources().getDimension( + R.dimen.certificate_viewer_padding_wide); + mPaddingThin = (int) context.getResources().getDimension( + R.dimen.certificate_viewer_padding_thin); + mContainer.setPadding(mPaddingWide, mPaddingWide + mPaddingThin, mPaddingWide, + mPaddingWide); mDialog = new Dialog(mContext); mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); @@ -76,9 +82,33 @@ public class WebsiteSettingsPopup implements OnClickListener { }); } - /** Adds a section, which contains an icon, a headline, and a description. */ + /** + * Adds certificate section, which contains an icon, a headline, a + * description and a label for certificate info link. + */ + @CalledByNative + private void addCertificateSection(int enumeratedIconId, String headline, String description, + String label) { + View section = addSection(enumeratedIconId, headline, description); + assert mCertificateLayout == null; + mCertificateLayout = (ViewGroup) section.findViewById(R.id.website_settings_text_layout); + if (label != null && !label.isEmpty()) { + setCertificateViewer(label); + } + } + + /** + * Adds Description section, which contains an icon, a headline, and a + * description. Most likely headline for description is empty + */ @CalledByNative - private void addSection(int enumeratedIconId, String headline, String description) { + private void addDescriptionSection(int enumeratedIconId, String headline, String description) { + View section = addSection(enumeratedIconId, headline, description); + assert mDescriptionLayout == null; + mDescriptionLayout = (ViewGroup) section.findViewById(R.id.website_settings_text_layout); + } + + private View addSection(int enumeratedIconId, String headline, String description) { View section = LayoutInflater.from(mContext).inflate(R.layout.website_settings, null); ImageView i = (ImageView) section.findViewById(R.id.website_settings_icon); int drawableId = ResourceId.mapToDrawableId(enumeratedIconId); @@ -90,29 +120,23 @@ public class WebsiteSettingsPopup implements OnClickListener { TextView d = (TextView) section.findViewById(R.id.website_settings_description); d.setText(description); + d.setTextSize(DESCRIPTION_TEXT_SIZE_SP); if (TextUtils.isEmpty(description)) d.setVisibility(View.GONE); mContainer.addView(section); + return section; } - /** Adds a horizontal dividing line to separate sections. */ - @CalledByNative - private void addDivider() { - View divider = new View(mContext); - final int dividerHeight = (int) (2 * mContext.getResources().getDisplayMetrics().density); - divider.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, dividerHeight)); - divider.setBackgroundColor(Color.GRAY); - mContainer.addView(divider); - } - - @CalledByNative private void setCertificateViewer(String label) { assert mCertificateViewer == null; - mCertificateViewer = new TextView(mContext); - mCertificateViewer.setText(Html.fromHtml("" + label + "")); + mCertificateViewer = new TextView(mContext); + mCertificateViewer.setText(label); + mCertificateViewer.setTextColor( + mContext.getResources().getColor(R.color.website_settings_popup_text_link)); + mCertificateViewer.setTextSize(DESCRIPTION_TEXT_SIZE_SP); mCertificateViewer.setOnClickListener(this); - mCertificateViewer.setPadding(0, 0, 0, mPadding); - mContainer.addView(mCertificateViewer); + mCertificateViewer.setPadding(0, mPaddingWide, 0, mPaddingWide); + mCertificateLayout.addView(mCertificateViewer); } @CalledByNative @@ -124,10 +148,13 @@ public class WebsiteSettingsPopup implements OnClickListener { private void addUrl(String label, String url) { mMoreInfoLink = new TextView(mContext); mLinkUrl = url; - mMoreInfoLink.setText(Html.fromHtml("" + label + "")); - mMoreInfoLink.setPadding(0, mPadding, 0, mPadding); + mMoreInfoLink.setText(label); + mMoreInfoLink.setTextColor( + mContext.getResources().getColor(R.color.website_settings_popup_text_link)); + mMoreInfoLink.setTextSize(DESCRIPTION_TEXT_SIZE_SP); + mMoreInfoLink.setPadding(0, mPaddingWide + mPaddingThin, 0, mPaddingWide); mMoreInfoLink.setOnClickListener(this); - mContainer.addView(mMoreInfoLink); + mDescriptionLayout.addView(mMoreInfoLink); } /** Displays the WebsiteSettingsPopup. */ diff --git a/src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java b/src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java index 6f7f573..15afde5 100644 --- a/src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java +++ b/src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java @@ -24,6 +24,7 @@ import android.widget.ListPopupWindow; import android.widget.PopupWindow; import android.widget.PopupWindow.OnDismissListener; +import org.chromium.base.SysUtils; import org.chromium.chrome.R; import java.util.ArrayList; @@ -45,6 +46,7 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { private final int mItemRowHeight; private final int mItemDividerHeight; private final int mVerticalFadeDistance; + private final int mAdditionalVerticalOffset; private ListPopupWindow mPopup; private AppMenuAdapter mAdapter; private AppMenuHandler mHandler; @@ -71,6 +73,8 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { mItemDividerHeight = itemDividerHeight; assert mItemDividerHeight >= 0; + mAdditionalVerticalOffset = + res.getDimensionPixelSize(R.dimen.menu_software_vertical_offset); mVerticalFadeDistance = res.getDimensionPixelSize(R.dimen.menu_vertical_fade_distance); } @@ -111,6 +115,9 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { mPopup.setAnimationStyle(R.style.OverflowMenuAnim); } + // Turn off window animations for low end devices. + if (SysUtils.isLowEndDevice()) mPopup.setAnimationStyle(0); + Rect bgPadding = new Rect(); mPopup.getBackground().getPadding(bgPadding); @@ -154,14 +161,17 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { mPopup.getListView().setFadingEdgeLength(mVerticalFadeDistance); } - mPopup.getListView().addOnLayoutChangeListener(new View.OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - mPopup.getListView().removeOnLayoutChangeListener(this); - runMenuItemEnterAnimations(); - } - }); + // Don't animate the menu items for low end devices. + if (!SysUtils.isLowEndDevice()) { + mPopup.getListView().addOnLayoutChangeListener(new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + mPopup.getListView().removeOnLayoutChangeListener(this); + runMenuItemEnterAnimations(); + } + }); + } } private void setPopupOffset(ListPopupWindow popup, int screenRotation, Rect appRect) { @@ -196,7 +206,7 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { } else { // The menu is displayed over and below the anchored view, so shift the menu up by the // height of the anchor view. - popup.setVerticalOffset(-anchorHeight); + popup.setVerticalOffset(mAdditionalVerticalOffset - anchorHeight); } } diff --git a/src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuButtonHelper.java b/src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuButtonHelper.java index f89dca7..8006249 100644 --- a/src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuButtonHelper.java +++ b/src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuButtonHelper.java @@ -69,6 +69,14 @@ public class AppMenuButtonHelper extends SimpleOnGestureListener implements OnTo } /** + * @return Whether app menu is active. That is, AppMenu is showing or menu button is consuming + * touch events to prepare AppMenu showing. + */ + public boolean isAppMenuActive() { + return mMenuButton.isPressed() || mMenuHandler.isAppMenuShowing(); + } + + /** * Handle the key press event on a menu button. * @return Whether the app menu was shown as a result of this action. */ @@ -95,10 +103,7 @@ public class AppMenuButtonHelper extends SimpleOnGestureListener implements OnTo if (mSeenFirstScrollEvent) return false; mSeenFirstScrollEvent = true; - // If the scrolling direction is roughly down on the first onScroll detection, - // we consider it as dragging start, so shows the app menu. Otherwise, we - // don't show menu so that toolbar horizontal swiping can happen. - return -distanceY >= Math.abs(distanceX) && showAppMenu(true); + return showAppMenu(true); } @Override diff --git a/src/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java b/src/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java new file mode 100644 index 0000000..c9a3bde --- /dev/null +++ b/src/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java @@ -0,0 +1,182 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; +import android.test.suitebuilder.annotation.MediumTest; +import android.view.View; +import android.view.ViewGroup; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.shell.ChromeShellActivity; +import org.chromium.chrome.shell.ChromeShellTestBase; +import org.chromium.chrome.shell.R; +import org.chromium.content.browser.test.util.CallbackHelper; + +import java.lang.reflect.Method; +import java.util.concurrent.TimeoutException; + +/** + * Tests for the SmartClipProvider. + */ +public class SmartClipProviderTest extends ChromeShellTestBase implements Handler.Callback { + // This is a key for meta-data in the package manifest. It should NOT + // change, as OEMs will use it when they look for the SmartClipProvider + // interface. + private static final String SMART_CLIP_PROVIDER_KEY = + "org.chromium.content.browser.SMART_CLIP_PROVIDER"; + + private static class MyCallbackHelper extends CallbackHelper { + public String getTitle() { + return mTitle; + } + + public String getUrl() { + return mUrl; + } + + public String getText() { + return mText; + } + + public String getHtml() { + return mHtml; + } + + public Rect getRect() { + return mRect; + } + + public void notifyCalled(String title, String url, String text, String html, Rect rect) { + mTitle = title; + mUrl = url; + mText = text; + mHtml = html; + mRect = rect; + super.notifyCalled(); + } + + private String mTitle; + private String mUrl; + private String mText; + private String mHtml; + private Rect mRect; + } + + private ChromeShellActivity mActivity; + private MyCallbackHelper mCallbackHelper; + private HandlerThread mHandlerThread; + private Handler mHandler; + private Class mSmartClipProviderClass; + private Method mSetSmartClipResultHandlerMethod; + private Method mExtractSmartClipDataMethod; + + @Override + public void setUp() throws Exception { + super.setUp(); + mActivity = launchChromeShellWithBlankPage(); + mCallbackHelper = new MyCallbackHelper(); + mHandlerThread = new HandlerThread("ContentViewTest thread"); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper(), this); + + mSmartClipProviderClass = getSmartClipProviderClass(); + assertNotNull(mSmartClipProviderClass); + mSetSmartClipResultHandlerMethod = mSmartClipProviderClass.getDeclaredMethod( + "setSmartClipResultHandler", new Class[] { Handler.class }); + mExtractSmartClipDataMethod = mSmartClipProviderClass.getDeclaredMethod( + "extractSmartClipData", + new Class[] { Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE }); + } + + @Override + public void tearDown() throws Exception { + try { + mHandlerThread.quitSafely(); + } finally { + super.tearDown(); + } + } + + // Implements Handler.Callback + @Override + public boolean handleMessage(Message msg) { + Bundle bundle = msg.getData(); + assertNotNull(bundle); + String url = bundle.getString("url"); + String title = bundle.getString("title"); + String text = bundle.getString("text"); + String html = bundle.getString("html"); + Rect rect = bundle.getParcelable("rect"); + // We don't care about other values for now. + mCallbackHelper.notifyCalled(title, url, text, html, rect); + return true; + } + + // Create SmartClipProvider interface from package meta-data. + private Class getSmartClipProviderClass() throws Exception { + ApplicationInfo ai = mActivity.getPackageManager().getApplicationInfo( + mActivity.getPackageName(), PackageManager.GET_META_DATA); + Bundle bundle = ai.metaData; + String className = bundle.getString(SMART_CLIP_PROVIDER_KEY); + assertNotNull(className); + return Class.forName(className); + } + + // Returns the first smart clip provider under the root view using DFS. + private Object findSmartClipProvider(View v) { + if (mSmartClipProviderClass.isInstance(v)) { + return v; + } else if (v instanceof ViewGroup) { + ViewGroup viewGroup = (ViewGroup) v; + int count = viewGroup.getChildCount(); + for (int i = 0; i < count; ++i) { + View c = viewGroup.getChildAt(i); + Object found = findSmartClipProvider(c); + if (found != null) + return found; + } + } + return null; + } + + @MediumTest + @Feature({"SmartClip"}) + public void testSmartClipDataCallback() throws InterruptedException, TimeoutException { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + // This emulates what OEM will be doing when they want to call + // functions on SmartClipProvider through view hierarchy. + + // Implementation of SmartClipProvider such as ContentView or + // JellyBeanContentView can be found somewhere under content_container. + Object scp = findSmartClipProvider( + getActivity().findViewById(R.id.content_container)); + assertNotNull(scp); + try { + mSetSmartClipResultHandlerMethod.invoke(scp, mHandler); + mExtractSmartClipDataMethod.invoke(scp, 10, 20, 100, 70); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + } + }); + mCallbackHelper.waitForCallback(0, 1); // call count: 0 --> 1 + assertEquals("about:blank", mCallbackHelper.getTitle()); + assertEquals("about:blank", mCallbackHelper.getUrl()); + assertNotNull(mCallbackHelper.getText()); + assertNotNull(mCallbackHelper.getHtml()); + assertNotNull(mCallbackHelper.getRect()); + } +} diff --git a/src/chrome/android/shell/java/AndroidManifest.xml b/src/chrome/android/shell/java/AndroidManifest.xml index 476deb9..3499dd3 100644 --- a/src/chrome/android/shell/java/AndroidManifest.xml +++ b/src/chrome/android/shell/java/AndroidManifest.xml @@ -198,5 +198,8 @@ + + diff --git a/src/chrome/app/resources/generated_resources_ar.xtb b/src/chrome/app/resources/generated_resources_ar.xtb index 671c166..ba863fb 100644 --- a/src/chrome/app/resources/generated_resources_ar.xtb +++ b/src/chrome/app/resources/generated_resources_ar.xtb @@ -2885,7 +2885,7 @@ ‏لاستخدام هذه الإضافة، اكتب ""، ثم TAB، ثم الأمر أو البحث. يبدو أنك تدير مستخدمًا من خلال هذا الاسم فعلاً.هل كنت تريد الاستيراد إلى هذا الجهاز؟ يريد استخدام الميكروفون. -التطبيقات +تطبيقات تم التحقق من هوية موقع الويب هذا بواسطة وهو قابل للتدقيق بشكل عام. إزالة هذا المستخدم ‏يمكن إضافة هذه الصفحة إلى تطبيقات Launcher diff --git a/src/chrome/app/resources/generated_resources_fil.xtb b/src/chrome/app/resources/generated_resources_fil.xtb index 071dbf0..41110fa 100644 --- a/src/chrome/app/resources/generated_resources_fil.xtb +++ b/src/chrome/app/resources/generated_resources_fil.xtb @@ -2917,7 +2917,7 @@ Tiyaking hindi ka maglalantad ng anumang sensitibong impormasyon. Upang gamitin ang extension na ito, i-type ang "", pagkatapos ay ang TAB, pagkatapos ay ang iyong command o paghahanap. Mukhang pinamamahalaan mo na ang isang user sa pangalang iyan.Gusto mo bang i-import si sa device na ito? Gustong gamitin ng ang iyong microphone. -Apps +Mga App Ang pagkakakilanlan ng website na ito ay na-verify ni at na-o-audit ng publiko. Alisin ang user na ito Maaaring idagdag ang page na ito sa App Launcher diff --git a/src/chrome/app/resources/generated_resources_fr.xtb b/src/chrome/app/resources/generated_resources_fr.xtb index 7db02c4..11715bf 100644 --- a/src/chrome/app/resources/generated_resources_fr.xtb +++ b/src/chrome/app/resources/generated_resources_fr.xtb @@ -2920,7 +2920,7 @@ Assurez-vous de ne pas dévoiler d'informations sensibles. Pour utiliser cette extension, saisissez "", TAB, puis votre commande ou votre recherche. Il semble que vous gérez déjà un utilisateur portant ce nom.Voulez-vous importer sur cet appareil ? veut utiliser votre micro. -Google Apps +Applications L'identité de ce site Web a été validée par , et elle est vérifiable publiquement. Supprimer cet utilisateur Cette page peut être ajoutée au lanceur d'applications. diff --git a/src/chrome/app/resources/generated_resources_gu.xtb b/src/chrome/app/resources/generated_resources_gu.xtb index 933e8eb..2d9dc8b 100644 --- a/src/chrome/app/resources/generated_resources_gu.xtb +++ b/src/chrome/app/resources/generated_resources_gu.xtb @@ -2921,7 +2921,7 @@ આ એક્સ્ટેંશનનો ઉપયોગ કરવા, "" ટાઇપ કરો, તે પછી TAB, તે પછી તમારો આદેશ અથવા શોધ. એવું લાગે છે કે તમે પહેલાંથી જ તે નામના વપરાશકર્તાનું સંચાલન કરી રહ્યાં છો.શું તમે આ ઉપકરણ પર આયાત કરવા માંગો છો? તમારા માઇક્રોફોનનો ઉપયોગ કરવા માગે છે. -એપ્લિકેશન્સ +એપ્સ દ્વારા આ વેબસાઇટની ઓળખ ચકાસવામાં આવી છે અને તે સાર્વજનિક રૂપે ઓડિટેબલ છે. આ વપરાશકર્તાને દૂર કરો આ પૃષ્ઠ એપ લૉન્ચરમાં ઉમેરી શકાય છે diff --git a/src/chrome/app/resources/generated_resources_hr.xtb b/src/chrome/app/resources/generated_resources_hr.xtb index 8279b6c..ac58918 100644 --- a/src/chrome/app/resources/generated_resources_hr.xtb +++ b/src/chrome/app/resources/generated_resources_hr.xtb @@ -2884,7 +2884,7 @@ Ne otkrivajte nikakve osjetljive podatke. Da biste upotrijebili to proširenje, upišite "", zatim pritisnite TAB, a zatim svoju naredbu ili pretraživanje. Izgleda da već upravljate korisnikom pod tim imenom.Jeste li htjeli uvesti korisnika na ovaj uređaj? Host želi upotrijebiti vaš mikrofon. -Apps +Aplikacije Identitet te web-lokacije potvrdio je izdavač i može se javno nadzirati. Ukloni tog korisnika Tu stranicu možete dodati u Pokretač aplikacija diff --git a/src/chrome/app/resources/generated_resources_id.xtb b/src/chrome/app/resources/generated_resources_id.xtb index 5495d64..60b68a4 100644 --- a/src/chrome/app/resources/generated_resources_id.xtb +++ b/src/chrome/app/resources/generated_resources_id.xtb @@ -2894,7 +2894,7 @@ Pastikan Anda tidak mengekspos informasi penting apa pun. Untuk menggunakan ekstensi ini, ketik "", lalu TAB, kemudian perintah atau penelusuran Anda. Tampaknya Anda telah mengelola pengguna dengan nama tersebut.Apakah Anda ingin mengimpor ke perangkat ini? ingin menggunakan mikrofon Anda. -Apps +Apl Identitas situs web ini telah diverifikasi oleh dan dapat diaudit secara publik. Hapus pengguna ini Laman ini dapat ditambahkan ke Peluncur Aplikasi @@ -3459,7 +3459,7 @@ dan tidak biasa. Bisa jadi penyerang berpura-pura menjadi , ata Aplikasi/ekstensi dapat: Menghapus item... Aktifkan Pemberitahuan Tersinkron eksperimental. -$1 byte +$1 bita Terjadi kesalahan tidak dikenal saat mencoba menyambung ke "". Google Wallet tidak mendukung versi Chrome ini atau tidak mengenali kunci API Google Anda. Kesalahan Masuk @@ -4812,7 +4812,7 @@ Tekan sembarang tombol untuk melanjutkan penjelajahan. Bookmark Pilih bahasa Anda: Hapus cookies serta data situs dan plugin lainnya saat Anda menutup browser -Jumlah byte yang terbaca di seluruh jaringan +Jumlah bita yang terbaca di seluruh jaringan Coba ulang unduhan Buka di &jendela penyamaran Ubur-ubur diff --git a/src/chrome/app/resources/generated_resources_it.xtb b/src/chrome/app/resources/generated_resources_it.xtb index 2f82781..1676247 100644 --- a/src/chrome/app/resources/generated_resources_it.xtb +++ b/src/chrome/app/resources/generated_resources_it.xtb @@ -2875,7 +2875,7 @@ Assicurati di non mostrare informazioni riservate. Per utilizzare questa estensione, digita "", quindi TAB, poi il tuo comando o la tua ricerca. Sembra che tu gestisca già un utente con il nome indicato.Volevi importarlo in questo dispositivo? vuole utilizzare il microfono. -Google Apps +App L'identità di questo sito web è stata verificata da e può essere controllata pubblicamente. Rimuovi questo utente Questa pagina può essere aggiunta ad Avvio applicazioni diff --git a/src/chrome/app/resources/generated_resources_iw.xtb b/src/chrome/app/resources/generated_resources_iw.xtb index 36c1f74..342b5f8 100644 --- a/src/chrome/app/resources/generated_resources_iw.xtb +++ b/src/chrome/app/resources/generated_resources_iw.xtb @@ -2882,7 +2882,7 @@ JavaScript ויישומי פלאגין. ‏כדי להשתמש בתוסף זה, הקלד "", לאחר מכן הקש TAB ולאחר מכן הקלד את הפקודה או מונח החיפוש. נראה שאתה כבר מנהל משתמש עם השם הזה.האם רצית לייבא את אל המכשיר הזה? מעוניין להשתמש במיקרופון שלך. -Apps +אפליקציות הזהות של האתר הזה אומתה על ידי , והוא זמין לביקורת ציבורית. הסר את המשתמש הזה ניתן להוסיף דף זה למפעיל היישומים diff --git a/src/chrome/app/resources/generated_resources_kn.xtb b/src/chrome/app/resources/generated_resources_kn.xtb index f7158b2..26ad58c 100644 --- a/src/chrome/app/resources/generated_resources_kn.xtb +++ b/src/chrome/app/resources/generated_resources_kn.xtb @@ -2900,7 +2900,7 @@ ಈ ವಿಸ್ತರಣೆಯನ್ನು ಬಳಸಲು, "" ಅನ್ನು ಟೈಪ್ ಮಾಡಿ, ನಂತರ TAB, ನಂತರ ನಿಮ್ಮ ಆದೇಶ ಅಥವಾ ಹುಡುಕಾಟ‌ವನ್ನು ಟೈಪ್ ಮಾಡಿ. ಆ ಹೆಸರಿನ ಮೂಲಕ ನೀವು ಈಗಾಗಲೇ ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸುತ್ತಿರುವಂತೆ ತೋರುತ್ತಿದೆ.ನೀವು ಈ ಸಾಧನಕ್ಕೆ ಆಮದು ಮಾಡಲು ಬಯಸುವಿರಾ? ನಿಮ್ಮ ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ಬಳಸಬೇಕೆಂದು ಬಯಸುತ್ತದೆ. -Apps +ಆಪ್ಸ್‌‌ ಈ ವೆಬ್‌ಸೈಟ್‌ ಗುರುತನ್ನು ಮೂಲಕ ಪರಿಶೀಲಿಸಲಾಗಿದೆ ಮತ್ತು ಇದನ್ನು ಸಾರ್ವಜನಿಕವಾಗಿ ಪರಿಶೋಧಿಸಬಹುದಾಗಿದೆ. ಈ ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಿ ಈ ಪುಟವನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಲಾಂಚರ್‌ಗೆ ಸೇರಿಸಬಹುದಾಗಿದೆ diff --git a/src/chrome/app/resources/generated_resources_ko.xtb b/src/chrome/app/resources/generated_resources_ko.xtb index 74ef97c..dd302ff 100644 --- a/src/chrome/app/resources/generated_resources_ko.xtb +++ b/src/chrome/app/resources/generated_resources_ko.xtb @@ -2916,7 +2916,7 @@ http://support.google.com/chromebook/?p=tpm 이 확장 프로그램을 사용하려면 ''(을)를 입력하고 TAB을 누른 다음 명령어 또는 검색어를 입력하세요. 이미 해당 이름으로 사용자를 관리 중인 것 같습니다.을(를) 이 기기로 가져오시겠습니까? 에서 사용자의 마이크를 사용하려고 합니다. -응용프로그램 +앱 이 웹사이트의 ID는 에 의해 확인되었고 공개 감사가 가능합니다. 이 사용자 삭제 이 페이지를 앱 런처에 추가할 수 있습니다. diff --git a/src/chrome/app/resources/generated_resources_nl.xtb b/src/chrome/app/resources/generated_resources_nl.xtb index e3c87ac..9753736 100644 --- a/src/chrome/app/resources/generated_resources_nl.xtb +++ b/src/chrome/app/resources/generated_resources_nl.xtb @@ -2927,7 +2927,7 @@ Zorg ervoor dat je geen gevoelige informatie weergeeft. Als je deze extensie wilt gebruiken, typ je '', druk je op Tab en geef je je opdracht of zoekopdracht op. Het lijkt erop dat je al een gebruiker met die naam beheert.Wil je importeren naar dit apparaat? wil gebruikmaken van je microfoon. -Google Apps +Apps De identiteit van deze website is geverifieerd door en is openbaar controleerbaar. Deze gebruiker verwijderen Deze pagina kan worden toegevoegd aan de App Launcher diff --git a/src/chrome/app/resources/generated_resources_sr.xtb b/src/chrome/app/resources/generated_resources_sr.xtb index 1567066..18df83e 100644 --- a/src/chrome/app/resources/generated_resources_sr.xtb +++ b/src/chrome/app/resources/generated_resources_sr.xtb @@ -1798,7 +1798,7 @@ Пријави проблем Експеримент са TLS/SSL упозорењем Ово може да потраје један минут... -Учитавање... +Учитава се... Укупно: Промени &Подешавања језика... diff --git a/src/chrome/app/resources/generated_resources_ta.xtb b/src/chrome/app/resources/generated_resources_ta.xtb index 3fa98b7..5dd5147 100644 --- a/src/chrome/app/resources/generated_resources_ta.xtb +++ b/src/chrome/app/resources/generated_resources_ta.xtb @@ -485,7 +485,7 @@ சுயவிவரத்தில் நீட்டிப்புக் கோப்பகத்தை நகர்த்த முடியவில்லை. புளூடூத்தை இயக்கு எதிர்கால வருகைகளுக்கு இந்த அமைப்புகளை அழி -மொழிபெயர்ப்பிற்கான மொழி: +மொழிபெயர்ப்பிற்கான மொழி: சோதனை முறையிலான குறுகியகாலப் பயன்பாடுகளை இயக்கு. பிரதிநிதியைத் தேர்ந்தெடுக்க Space ஐ அழுத்துக தாவல்களை மூடுக @@ -3201,7 +3201,7 @@ Chromium ஐப் பிழைத்திருத்துவதற்குப் பயன்படும் கூடுதல் விசைப்பலகைக் குறுக்குவழிகளை இயக்கும். நீட்டிக்கப்பட்ட விசைப் பயன்பாடு இயல்பாக மீண்டும் ஏற்று -தொடக்க உள்ளீட்டு மொழி சீனம் +தொடக்க உள்ளீட்டு மொழி சீனம் <b>""</b> உடன் பொருந்தும் உருப்படிகள் எதுவுமில்லை நீட்டிப்பை இயக்கு பயனர் முகவர் @@ -4317,7 +4317,7 @@ உரை உள்ளீட்டுக்கு, ஒரு மொழியைத் தேர்ந்தெடுத்து கிடைக்கும் உள்ளீட்டு முறைகளைக் காண்க. &வலஞ்சுழியாகச் சுற்று ஆம், உறுதியாக உள்ளேன் -உங்கள் மொழி என்ன? +உங்கள் மொழி என்ன? (கண்காணிக்கப்படும் பயனர்) மாற்று... உங்கள் Chromebook இல் உள்நுழைய, இணையத்துடன் இணையவும். diff --git a/src/chrome/app/resources/generated_resources_zh-TW.xtb b/src/chrome/app/resources/generated_resources_zh-TW.xtb index 892737a..5d06410 100644 --- a/src/chrome/app/resources/generated_resources_zh-TW.xtb +++ b/src/chrome/app/resources/generated_resources_zh-TW.xtb @@ -2700,7 +2700,7 @@ 允許 取消分頁固定 電池可使用時間低於 。 -已儲存的內容設定及搜尋引擎不會遭到清除,而這可能反映您的瀏覽習慣。 +已儲存的|內容設定|和#搜尋引擎#資料不會被清除,而且可能會反映您的瀏覽習慣。 無法載入瀏覽器動作的圖示「」。 新增帳單詳細資訊... 我需要進一步資訊 @@ -5237,4 +5237,4 @@ Colemak 美式配置 確認安裝 回報錯誤的警告 - \ No newline at end of file + diff --git a/src/chrome/browser/android/most_visited_sites.cc b/src/chrome/browser/android/most_visited_sites.cc index 16aed52..4cae0f3 100644 --- a/src/chrome/browser/android/most_visited_sites.cc +++ b/src/chrome/browser/android/most_visited_sites.cc @@ -167,7 +167,8 @@ void LogHistogramEvent(const std::string& histogram, int position, num_sites, num_sites + 1, base::Histogram::kUmaTargetedHistogramFlag); - counter->Add(position); + if (counter) + counter->Add(position); } } // namespace diff --git a/src/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/src/chrome/browser/chromeos/app_mode/kiosk_app_data.cc index 955a91d..51c9571 100644 --- a/src/chrome/browser/chromeos/app_mode/kiosk_app_data.cc +++ b/src/chrome/browser/chromeos/app_mode/kiosk_app_data.cc @@ -336,7 +336,7 @@ void KioskAppData::SetStatus(Status status) { case STATUS_ERROR: delegate_->OnKioskAppDataLoadFailure(app_id_); break; - }; + } } net::URLRequestContextGetter* KioskAppData::GetRequestContextGetter() { @@ -442,6 +442,7 @@ void KioskAppData::StartFetch() { GetRequestContextGetter(), GURL(), app_id_)); + webstore_fetcher_->set_max_auto_retries(3); webstore_fetcher_->Start(); } diff --git a/src/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/src/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc index 3dff8f1..50df660 100644 --- a/src/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc +++ b/src/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc @@ -356,6 +356,13 @@ void KioskAppManager::UpdateAppDataFromProfile( app_data->LoadFromInstalledApp(profile, app); } +void KioskAppManager::RetryFailedAppDataFetch() { + for (size_t i = 0; i < apps_.size(); ++i) { + if (apps_[i]->status() == KioskAppData::STATUS_ERROR) + apps_[i]->Load(); + } +} + void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) { observers_.AddObserver(observer); } @@ -469,6 +476,8 @@ void KioskAppManager::UpdateAppData() { prefs->Set(apps_[i]->app_id(), new base::DictionaryValue); external_cache_->UpdateExtensionsList(prefs.Pass()); + RetryFailedAppDataFetch(); + FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_, OnKioskAppsSettingsChanged()); } diff --git a/src/chrome/browser/chromeos/app_mode/kiosk_app_manager.h b/src/chrome/browser/chromeos/app_mode/kiosk_app_manager.h index 7a9fe67..a26939e 100644 --- a/src/chrome/browser/chromeos/app_mode/kiosk_app_manager.h +++ b/src/chrome/browser/chromeos/app_mode/kiosk_app_manager.h @@ -150,6 +150,8 @@ class KioskAppManager : public KioskAppDataDelegate, Profile* profile, const extensions::Extension* app); + void RetryFailedAppDataFetch(); + void AddObserver(KioskAppManagerObserver* observer); void RemoveObserver(KioskAppManagerObserver* observer); diff --git a/src/chrome/browser/chromeos/input_method/input_method_engine.cc b/src/chrome/browser/chromeos/input_method/input_method_engine.cc index 0179772..10c0aac 100644 --- a/src/chrome/browser/chromeos/input_method/input_method_engine.cc +++ b/src/chrome/browser/chromeos/input_method/input_method_engine.cc @@ -29,6 +29,7 @@ #include "ui/base/ime/chromeos/ime_keymap.h" #include "ui/events/event.h" #include "ui/events/event_processor.h" +#include "ui/events/keycodes/dom4/keycode_converter.h" #include "ui/keyboard/keyboard_controller.h" #include "ui/keyboard/keyboard_util.h" @@ -76,8 +77,44 @@ std::string GetKeyFromEvent(const ui::KeyEvent& event) { if (code == "Escape") return "Esc"; if (code == "Backspace" || code == "Tab" || - code == "Enter" || code == "CapsLock") + code == "Enter" || code == "CapsLock" || + code == "Power") return code; + // Cases for media keys. + switch (event.key_code()) { + case ui::VKEY_BROWSER_BACK: + case ui::VKEY_F1: + return "HistoryBack"; + case ui::VKEY_BROWSER_FORWARD: + case ui::VKEY_F2: + return "HistoryForward"; + case ui::VKEY_BROWSER_REFRESH: + case ui::VKEY_F3: + return "BrowserRefresh"; + case ui::VKEY_MEDIA_LAUNCH_APP2: + case ui::VKEY_F4: + return "ChromeOSFullscreen"; + case ui::VKEY_MEDIA_LAUNCH_APP1: + case ui::VKEY_F5: + return "ChromeOSSwitchWindow"; + case ui::VKEY_BRIGHTNESS_DOWN: + case ui::VKEY_F6: + return "BrightnessDown"; + case ui::VKEY_BRIGHTNESS_UP: + case ui::VKEY_F7: + return "BrightnessUp"; + case ui::VKEY_VOLUME_MUTE: + case ui::VKEY_F8: + return "AudioVolumeMute"; + case ui::VKEY_VOLUME_DOWN: + case ui::VKEY_F9: + return "AudioVolumeDown"; + case ui::VKEY_VOLUME_UP: + case ui::VKEY_F10: + return "AudioVolumeUp"; + default: + break; + } uint16 ch = 0; // Ctrl+? cases, gets key value for Ctrl is not down. if (event.flags() & ui::EF_CONTROL_DOWN) { @@ -100,7 +137,11 @@ void GetExtensionKeyboardEventFromKeyEvent( DCHECK(ext_event); ext_event->type = (event.type() == ui::ET_KEY_RELEASED) ? "keyup" : "keydown"; - ext_event->code = event.code(); + std::string dom_code = event.code(); + if (dom_code == + ui::KeycodeConverter::GetInstance()->InvalidKeyboardEventCode()) + dom_code = ui::KeyboardCodeToDomKeycode(event.key_code()); + ext_event->code = dom_code; ext_event->key_code = static_cast(event.key_code()); ext_event->alt_key = event.IsAltDown(); ext_event->ctrl_key = event.IsControlDown(); diff --git a/src/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc b/src/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc index 494371f..a169cdb 100644 --- a/src/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc +++ b/src/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc @@ -5,6 +5,7 @@ #include "ash/ime/input_method_menu_item.h" #include "ash/ime/input_method_menu_manager.h" #include "base/bind_helpers.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_test_message_listener.h" @@ -389,6 +390,53 @@ IN_PROC_BROWSER_TEST_P(InputMethodEngineBrowserTest, EXPECT_TRUE(keyevent_listener.was_satisfied()); callback.WaitUntilCalled(); } + // Media keys cases. + const struct { + ui::KeyboardCode keycode; + const char* code; + const char* key; + } kMediaKeyCases[] = { + { ui::VKEY_BROWSER_BACK, "BrowserBack", "HistoryBack" }, + { ui::VKEY_BROWSER_FORWARD, "BrowserForward", "HistoryForward" }, + { ui::VKEY_BROWSER_REFRESH, "BrowserRefresh", "BrowserRefresh" }, + { ui::VKEY_MEDIA_LAUNCH_APP2, "ChromeOSFullscreen", "ChromeOSFullscreen" }, + { ui::VKEY_MEDIA_LAUNCH_APP1, + "ChromeOSSwitchWindow", "ChromeOSSwitchWindow" }, + { ui::VKEY_BRIGHTNESS_DOWN, "BrightnessDown", "BrightnessDown" }, + { ui::VKEY_BRIGHTNESS_UP, "BrightnessUp", "BrightnessUp" }, + { ui::VKEY_VOLUME_MUTE, "VolumeMute", "AudioVolumeMute" }, + { ui::VKEY_VOLUME_DOWN, "VolumeDown", "AudioVolumeDown" }, + { ui::VKEY_VOLUME_UP, "VolumeUp", "AudioVolumeUp" }, + { ui::VKEY_F1, "F1", "HistoryBack" }, + { ui::VKEY_F2, "F2", "HistoryForward" }, + { ui::VKEY_F3, "F3", "BrowserRefresh" }, + { ui::VKEY_F4, "F4", "ChromeOSFullscreen" }, + { ui::VKEY_F5, "F5", "ChromeOSSwitchWindow" }, + { ui::VKEY_F6, "F6", "BrightnessDown" }, + { ui::VKEY_F7, "F7", "BrightnessUp" }, + { ui::VKEY_F8, "F8", "AudioVolumeMute" }, + { ui::VKEY_F9, "F9", "AudioVolumeDown" }, + { ui::VKEY_F10, "F10", "AudioVolumeUp" }, + }; + for (size_t i = 0; i < arraysize(kMediaKeyCases); ++i) { + SCOPED_TRACE(std::string("KeyDown, ") + kMediaKeyCases[i].code); + KeyEventDoneCallback callback(false); + const std::string expected_value = + base::StringPrintf("onKeyEvent::keydown:%s:%s:false:false:false:false", + kMediaKeyCases[i].key, kMediaKeyCases[i].code); + ExtensionTestMessageListener keyevent_listener(expected_value, false); + + ui::KeyEvent key_event(ui::ET_KEY_PRESSED, + kMediaKeyCases[i].keycode, + kMediaKeyCases[i].code, + ui::EF_NONE); + engine_handler->ProcessKeyEvent(key_event, + base::Bind(&KeyEventDoneCallback::Run, + base::Unretained(&callback))); + ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied()); + EXPECT_TRUE(keyevent_listener.was_satisfied()); + callback.WaitUntilCalled(); + } // TODO(nona): Add browser tests for other API as well. { SCOPED_TRACE("commitText test"); diff --git a/src/chrome/browser/chromeos/login/ui/user_adding_screen.cc b/src/chrome/browser/chromeos/login/ui/user_adding_screen.cc index 172417d..06b7435 100644 --- a/src/chrome/browser/chromeos/login/ui/user_adding_screen.cc +++ b/src/chrome/browser/chromeos/login/ui/user_adding_screen.cc @@ -11,6 +11,7 @@ #include "base/observer_list.h" #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" +#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" @@ -56,6 +57,12 @@ void UserAddingScreenImpl::Cancel() { // Make sure that system tray is enabled after this flow. ash::Shell::GetInstance()->GetPrimarySystemTray()->SetEnabled(true); display_host_->Finalize(); + + // Reset wallpaper if cancel adding user from multiple user sign in page. + if (UserManager::Get()->IsUserLoggedIn()) { + WallpaperManager::Get()->SetUserWallpaperDelayed( + UserManager::Get()->GetActiveUser()->email()); + } } bool UserAddingScreenImpl::IsRunning() { diff --git a/src/chrome/browser/extensions/api/system_cpu/cpu_info_provider_linux.cc b/src/chrome/browser/extensions/api/system_cpu/cpu_info_provider_linux.cc index 2422262..6c7b795 100644 --- a/src/chrome/browser/extensions/api/system_cpu/cpu_info_provider_linux.cc +++ b/src/chrome/browser/extensions/api/system_cpu/cpu_info_provider_linux.cc @@ -37,19 +37,33 @@ bool CpuInfoProvider::QueryCpuTimePerProcessor( if (line.compare(0, 3, "cpu") != 0) continue; + // The number of entries in /proc/stat may mismatch the size of infos + // because the number of online processors may change after the value has + // been decided in CpuInfoProvider::QueryInfo(). + // + // TODO(jchuang): fix the fail case by using the number of configured + // processors instead of online processors. + if (i == infos->size()) { + LOG(ERROR) << "Got more entries in /proc/stat than online CPUs"; + return false; + } + uint64 user = 0, nice = 0, sys = 0, idle = 0; int vals = sscanf(line.c_str(), "%*s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, &user, &nice, &sys, &idle); DCHECK_EQ(4, vals); - DCHECK(i < infos->size()); infos->at(i)->usage.kernel = static_cast(sys); infos->at(i)->usage.user = static_cast(user + nice); infos->at(i)->usage.idle = static_cast(idle); infos->at(i)->usage.total = static_cast(sys + user + nice + idle); ++i; } - DCHECK_EQ(infos->size(), i); + if (i < infos->size()) { + LOG(ERROR) << "Got fewer entries in /proc/stat than online CPUs"; + return false; + } + return true; } diff --git a/src/chrome/browser/extensions/webstore_data_fetcher.cc b/src/chrome/browser/extensions/webstore_data_fetcher.cc index 89d523b..d71fe01 100644 --- a/src/chrome/browser/extensions/webstore_data_fetcher.cc +++ b/src/chrome/browser/extensions/webstore_data_fetcher.cc @@ -29,7 +29,8 @@ WebstoreDataFetcher::WebstoreDataFetcher( : delegate_(delegate), request_context_(request_context), referrer_url_(referrer_url), - id_(webstore_item_id) { + id_(webstore_item_id), + max_auto_retries_(0) { } WebstoreDataFetcher::~WebstoreDataFetcher() {} @@ -43,6 +44,11 @@ void WebstoreDataFetcher::Start() { webstore_data_url_fetcher_->SetReferrer(referrer_url_.spec()); webstore_data_url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DISABLE_CACHE); + if (max_auto_retries_ > 0) { + webstore_data_url_fetcher_->SetMaxRetriesOn5xx(max_auto_retries_); + webstore_data_url_fetcher_->SetAutomaticallyRetryOnNetworkChanges( + max_auto_retries_); + } webstore_data_url_fetcher_->Start(); } diff --git a/src/chrome/browser/extensions/webstore_data_fetcher.h b/src/chrome/browser/extensions/webstore_data_fetcher.h index fb8aafd..b11ac97 100644 --- a/src/chrome/browser/extensions/webstore_data_fetcher.h +++ b/src/chrome/browser/extensions/webstore_data_fetcher.h @@ -38,6 +38,10 @@ class WebstoreDataFetcher : public base::SupportsWeakPtr, void Start(); + void set_max_auto_retries(int max_retries) { + max_auto_retries_ = max_retries; + } + private: void OnJsonParseSuccess(scoped_ptr parsed_json); void OnJsonParseFailure(const std::string& error); @@ -53,6 +57,10 @@ class WebstoreDataFetcher : public base::SupportsWeakPtr, // For fetching webstore JSON data. scoped_ptr webstore_data_url_fetcher_; + // Maximum auto retry times on server 5xx error or ERR_NETWORK_CHANGED. + // Default is 0 which means to use the URLFetcher default behavior. + int max_auto_retries_; + DISALLOW_COPY_AND_ASSIGN(WebstoreDataFetcher); }; diff --git a/src/chrome/browser/history/in_memory_url_index.cc b/src/chrome/browser/history/in_memory_url_index.cc index 38eb30c..e705b46 100644 --- a/src/chrome/browser/history/in_memory_url_index.cc +++ b/src/chrome/browser/history/in_memory_url_index.cc @@ -233,6 +233,25 @@ void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) { row != details->rows.end(); ++row) needs_to_be_cached_ |= private_data_->DeleteURL(row->url()); } + // If we made changes, destroy the previous cache. Otherwise, if we go + // through an unclean shutdown (and therefore fail to write a new cache file), + // when Chrome restarts and we restore from the previous cache, we'll end up + // searching over URLs that may be deleted. This would be wrong, and + // surprising to the user who bothered to delete some URLs from his/her + // history. In this situation, deleting the cache is a better solution than + // writing a new cache (after deleting the URLs from the in-memory structure) + // because deleting the cache forces it to be rebuilt from history upon + // startup. If we instead write a new, updated cache then at the time of next + // startup (after an unclean shutdown) we will not rebuild the in-memory data + // structures from history but rather use the cache. This solution is + // mediocre because this cache may not have the most-recently-visited URLs + // in it (URLs visited after user deleted some URLs from history), which + // would be odd and confusing. It's better to force a rebuild. + base::FilePath path; + if (needs_to_be_cached_ && GetCacheFilePath(&path)) { + content::BrowserThread::PostBlockingPoolTask( + FROM_HERE, base::Bind(DeleteCacheFile, path)); + } } // Restoring from Cache -------------------------------------------------------- diff --git a/src/chrome/browser/history/in_memory_url_index.h b/src/chrome/browser/history/in_memory_url_index.h index 697ccad..5537712 100644 --- a/src/chrome/browser/history/in_memory_url_index.h +++ b/src/chrome/browser/history/in_memory_url_index.h @@ -290,8 +290,6 @@ class InMemoryURLIndex : public content::NotificationObserver, // to be cached. Set to false when the index has been cached. Used as a // temporary safety check to insure that the cache is saved before the // index has been destructed. - // TODO(mrossetti): Eliminate once the transition to SQLite has been done. - // http://crbug.com/83659 bool needs_to_be_cached_; DISALLOW_COPY_AND_ASSIGN(InMemoryURLIndex); diff --git a/src/chrome/browser/profiles/profile_info_cache.cc b/src/chrome/browser/profiles/profile_info_cache.cc index a6f8d9a..3a49fc0 100644 --- a/src/chrome/browser/profiles/profile_info_cache.cc +++ b/src/chrome/browser/profiles/profile_info_cache.cc @@ -793,6 +793,11 @@ void ProfileInfoCache::RegisterPrefs(PrefRegistrySimple* registry) { void ProfileInfoCache::DownloadHighResAvatar( size_t icon_index, const base::FilePath& profile_path) { + // Downloading is only supported on desktop. +#if defined(OS_ANDROID) || defined(OS_IOS) || defined(OS_CHROMEOS) + return; +#endif + // TODO(noms): We should check whether the file already exists on disk // before trying to re-download it. For now, since this is behind a flag and // the resources are still changing, re-download it every time the profile diff --git a/src/chrome/browser/profiles/profile_info_cache_unittest.cc b/src/chrome/browser/profiles/profile_info_cache_unittest.cc index 92638ae..11a682e 100644 --- a/src/chrome/browser/profiles/profile_info_cache_unittest.cc +++ b/src/chrome/browser/profiles/profile_info_cache_unittest.cc @@ -504,6 +504,8 @@ TEST_F(ProfileInfoCacheTest, AddStubProfile) { ASSERT_FALSE(names[i].empty()); } +// High res avatar downloading is only supported on desktop. +#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) TEST_F(ProfileInfoCacheTest, DownloadHighResAvatarTest) { EXPECT_EQ(0U, GetCache()->GetNumberOfProfiles()); base::FilePath path_1 = GetProfilePath("path_1"); @@ -551,3 +553,4 @@ TEST_F(ProfileInfoCacheTest, DownloadHighResAvatarTest) { EXPECT_TRUE(base::DeleteFile(icon_path, true)); EXPECT_FALSE(base::PathExists(icon_path)); } +#endif diff --git a/src/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher.js b/src/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher.js index 6aa21cf..1a67836 100644 --- a/src/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher.js +++ b/src/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher.js @@ -582,9 +582,12 @@ cvox.ChromeVoxEventWatcher.mouseClickEventWatcher = function(evt) { * @return {boolean} True if the default action should be performed. */ cvox.ChromeVoxEventWatcher.mouseOverEventWatcher = function(evt) { - var hasTouch = 'ontouchstart' in window; + // Chrome simulates the meta key for mouse events generated from + // touch exploration. + var isTouchEvent = (evt.metaKey); + var mouseoverDelayMs = cvox.ChromeVoxEventWatcher.mouseoverDelayMs; - if (hasTouch) { + if (isTouchEvent) { mouseoverDelayMs = 0; } else if (!cvox.ChromeVoxEventWatcher.focusFollowsMouse) { return true; diff --git a/src/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.css b/src/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.css index ba150cd..401eab3 100644 --- a/src/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.css +++ b/src/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.css @@ -68,7 +68,7 @@ } #hid-detection #hid-keyboard-pincode { - -webkit-padding-start: 40px; + -webkit-padding-start: 60px; padding-bottom: 15px; padding-top: 15px; } diff --git a/src/chrome/browser/resources/hotword_helper/manifest.json b/src/chrome/browser/resources/hotword_helper/manifest.json index eb21576..889cf30 100644 --- a/src/chrome/browser/resources/hotword_helper/manifest.json +++ b/src/chrome/browser/resources/hotword_helper/manifest.json @@ -3,7 +3,7 @@ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDagiQy1VGkO2CHJSjVh7eU5GtuBuOlg2/cTZt7203AcevqpcDd+65S2/yd9KAELYcU6pK8nHVGYBMI6s0u+0RgXfIJ0eFOlTlgfAQWHvg8ovHtJlFJd1COrOkbntD9+s9Jobr3ldmow87aZF1bVHUY4khVP56cZe6adlVw2wK31QIDAQAB", "name": "hotword helper", - "version": "0.0.1.0", + "version": "0.0.2.0", "manifest_version": 2, "background": { diff --git a/src/chrome/browser/supervised_user/supervised_user_service.cc b/src/chrome/browser/supervised_user/supervised_user_service.cc index d20661e..dfc1e16 100644 --- a/src/chrome/browser/supervised_user/supervised_user_service.cc +++ b/src/chrome/browser/supervised_user/supervised_user_service.cc @@ -593,7 +593,7 @@ void SupervisedUserService::SetActive(bool active) { settings_service, SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext( profile_), - pref_service->GetString(prefs::kProfileName), + GetSupervisedUserName(), pref_service->GetString(prefs::kSupervisedUserId))); } @@ -748,3 +748,16 @@ void SupervisedUserService::OnBrowserSetLastActive(Browser* browser) { is_profile_active_ = profile_became_active; } + +std::string SupervisedUserService::GetSupervisedUserName() const { +#if defined(OS_CHROMEOS) + // The active user can be NULL in unit tests. + if (chromeos::UserManager::Get()->GetActiveUser()) { + return UTF16ToUTF8(chromeos::UserManager::Get()->GetUserDisplayName( + chromeos::UserManager::Get()->GetActiveUser()->GetUserID())); + } + return std::string(); +#else + return profile_->GetPrefs()->GetString(prefs::kProfileName); +#endif +} diff --git a/src/chrome/browser/supervised_user/supervised_user_service.h b/src/chrome/browser/supervised_user/supervised_user_service.h index ae20046..e2165b9 100644 --- a/src/chrome/browser/supervised_user/supervised_user_service.h +++ b/src/chrome/browser/supervised_user/supervised_user_service.h @@ -251,6 +251,9 @@ class SupervisedUserService : public KeyedService, // corresponding preference is changed. void UpdateManualURLs(); + // Returns the human readable name of the supervised user. + std::string GetSupervisedUserName() const; + // Owns us via the KeyedService mechanism. Profile* profile_; diff --git a/src/chrome/browser/ui/android/website_settings_popup_android.cc b/src/chrome/browser/ui/android/website_settings_popup_android.cc index 1c0aabb..c5a35f7 100644 --- a/src/chrome/browser/ui/android/website_settings_popup_android.cc +++ b/src/chrome/browser/ui/android/website_settings_popup_android.cc @@ -125,17 +125,15 @@ void WebsiteSettingsPopupAndroid::SetIdentityInfo( ScopedJavaLocalRef description = ConvertUTF8ToJavaString( env, identity_info.identity_status_description); - Java_WebsiteSettingsPopup_addSection(env, popup_jobject_.obj(), icon_id, - ConvertUTF8ToJavaString(env, headline).obj(), description.obj()); - base::string16 certificate_label = - l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON); - if (!certificate_label.empty()) { - Java_WebsiteSettingsPopup_setCertificateViewer(env, popup_jobject_.obj(), - ConvertUTF16ToJavaString(env, certificate_label).obj()); - } - - Java_WebsiteSettingsPopup_addDivider(env, popup_jobject_.obj()); + l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON); + Java_WebsiteSettingsPopup_addCertificateSection( + env, + popup_jobject_.obj(), + icon_id, + ConvertUTF8ToJavaString(env, headline).obj(), + description.obj(), + ConvertUTF16ToJavaString(env, certificate_label).obj()); } { @@ -145,10 +143,8 @@ void WebsiteSettingsPopupAndroid::SetIdentityInfo( ScopedJavaLocalRef description = ConvertUTF8ToJavaString( env, identity_info.connection_status_description); - Java_WebsiteSettingsPopup_addSection(env, popup_jobject_.obj(), icon_id, - NULL, description.obj()); - - Java_WebsiteSettingsPopup_addDivider(env, popup_jobject_.obj()); + Java_WebsiteSettingsPopup_addDescriptionSection( + env, popup_jobject_.obj(), icon_id, NULL, description.obj()); } Java_WebsiteSettingsPopup_addMoreInfoLink(env, popup_jobject_.obj(), diff --git a/src/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/src/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc index f8f08d6..5047f64 100644 --- a/src/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/src/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc @@ -466,7 +466,6 @@ void ManagePasswordsBubbleView::ShowBubble(content::WebContents* web_contents, browser_view->GetBoundsInScreen()); } manage_passwords_bubble_->GetWidget()->Show(); - manage_passwords_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE); } // static @@ -493,7 +492,7 @@ ManagePasswordsBubbleView::ManagePasswordsBubbleView( anchor_view_(anchor_view), never_save_passwords_(false) { // Compensate for built-in vertical padding in the anchor view's image. - set_anchor_view_insets(gfx::Insets(2, 0, 2, 0)); + set_anchor_view_insets(gfx::Insets(5, 0, 5, 0)); set_notify_enter_exit_on_child(true); if (anchor_view) anchor_view->SetActive(true); diff --git a/src/chrome/browser/ui/views/tabs/tab.cc b/src/chrome/browser/ui/views/tabs/tab.cc index ae9cf1b..4f0833b 100644 --- a/src/chrome/browser/ui/views/tabs/tab.cc +++ b/src/chrome/browser/ui/views/tabs/tab.cc @@ -730,6 +730,11 @@ void Tab::Layout() { kViewSpacing - title_left; } gfx::Rect rect(title_left, lb.y(), std::max(title_width, 0), lb.height()); + const int title_height = title_->GetPreferredSize().height(); + if (title_height > rect.height()) { + rect.set_y(lb.y() - (title_height - rect.height()) / 2); + rect.set_height(title_height); + } rect.set_x(GetMirroredXForRect(rect)); title_->SetBoundsRect(rect); } diff --git a/src/chrome/browser/ui/views/tabs/window_finder_ash.cc b/src/chrome/browser/ui/views/tabs/window_finder_ash.cc index cdd9e68..0498888 100644 --- a/src/chrome/browser/ui/views/tabs/window_finder_ash.cc +++ b/src/chrome/browser/ui/views/tabs/window_finder_ash.cc @@ -22,7 +22,8 @@ aura::Window* GetLocalProcessWindowAtPointImpl( return NULL; if (window->id() == ash::kShellWindowId_PhantomWindow || - window->id() == ash::kShellWindowId_OverlayContainer) + window->id() == ash::kShellWindowId_OverlayContainer || + window->id() == ash::kShellWindowId_MouseCursorContainer) return NULL; if (window->layer()->type() == ui::LAYER_TEXTURED) diff --git a/src/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc b/src/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc index a1eab10..5babef6 100644 --- a/src/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc +++ b/src/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc @@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/metrics/histogram.h" @@ -15,6 +16,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" #include "chrome/common/pref_names.h" +#include "chromeos/chromeos_switches.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" @@ -112,7 +114,8 @@ void HIDDetectionScreenHandler::Show() { show_on_init_ = true; return; } - core_oobe_actor_->InitDemoModeDetection(); + if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableDemoMode)) + core_oobe_actor_->InitDemoModeDetection(); input_service_proxy_.AddObserver(this); first_time_screen_show_ = true; GetDevicesFirstTime(); diff --git a/src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc b/src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc index 50295aa..4ab1f18 100644 --- a/src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc +++ b/src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc @@ -37,14 +37,18 @@ const int kMaxAppIconSize = 160; } // namespace -KioskAppMenuHandler::KioskAppMenuHandler() +KioskAppMenuHandler::KioskAppMenuHandler( + const scoped_refptr& network_state_informer) : weak_ptr_factory_(this), - is_webui_initialized_(false) { + is_webui_initialized_(false), + network_state_informer_(network_state_informer) { KioskAppManager::Get()->AddObserver(this); + network_state_informer_->AddObserver(this); } KioskAppMenuHandler::~KioskAppMenuHandler() { KioskAppManager::Get()->RemoveObserver(this); + network_state_informer_->RemoveObserver(this); } void KioskAppMenuHandler::GetLocalizedStrings( @@ -133,6 +137,7 @@ void KioskAppMenuHandler::HandleInitializeKioskApps( const base::ListValue* args) { is_webui_initialized_ = true; SendKioskApps(); + UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE); } void KioskAppMenuHandler::HandleKioskAppsLoaded( @@ -165,4 +170,9 @@ void KioskAppMenuHandler::OnKioskAppDataChanged(const std::string& app_id) { SendKioskApps(); } +void KioskAppMenuHandler::UpdateState(ErrorScreenActor::ErrorReason reason) { + if (network_state_informer_->state() == NetworkStateInformer::ONLINE) + KioskAppManager::Get()->RetryFailedAppDataFetch(); +} + } // namespace chromeos diff --git a/src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h b/src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h index 2cd58ac..b1e887e 100644 --- a/src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h +++ b/src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h @@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h" +#include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h" #include "content/public/browser/web_ui_message_handler.h" namespace chromeos { @@ -19,10 +20,13 @@ namespace chromeos { // KioskAppMenuHandler supplies kiosk apps data to apps menu on sign-in // screen when app mode is enabled and handles "launchKioskApp" request // from the apps menu. -class KioskAppMenuHandler : public content::WebUIMessageHandler, - public KioskAppManagerObserver { +class KioskAppMenuHandler + : public content::WebUIMessageHandler, + public KioskAppManagerObserver, + public NetworkStateInformer::NetworkStateInformerObserver { public: - KioskAppMenuHandler(); + explicit KioskAppMenuHandler( + const scoped_refptr& network_state_informer); virtual ~KioskAppMenuHandler(); void GetLocalizedStrings(base::DictionaryValue* localized_strings); @@ -46,11 +50,16 @@ class KioskAppMenuHandler : public content::WebUIMessageHandler, virtual void OnKioskAppsSettingsChanged() OVERRIDE; virtual void OnKioskAppDataChanged(const std::string& app_id) OVERRIDE; + // NetworkStateInformer::NetworkStateInformerObserver overrides: + virtual void UpdateState(ErrorScreenActor::ErrorReason reason) OVERRIDE; + base::WeakPtrFactory weak_ptr_factory_; // True when WebUI is initialized. Otherwise don't allow calling JS functions. bool is_webui_initialized_; + scoped_refptr network_state_informer_; + DISALLOW_COPY_AND_ASSIGN(KioskAppMenuHandler); }; diff --git a/src/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/src/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index 67dfa9a..8d55960 100644 --- a/src/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/src/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc @@ -278,7 +278,7 @@ OobeUI::OobeUI(content::WebUI* web_ui, const GURL& url) app_launch_splash_screen_actor_ = app_launch_splash_screen_handler; // Initialize KioskAppMenuHandler. Note that it is NOT a screen handler. - kiosk_app_menu_handler_ = new KioskAppMenuHandler; + kiosk_app_menu_handler_ = new KioskAppMenuHandler(network_state_informer_); web_ui->AddMessageHandler(kiosk_app_menu_handler_); base::DictionaryValue localized_strings; diff --git a/src/chrome/third_party/chromevox/chromeVoxChromeBackgroundScript.js b/src/chrome/third_party/chromevox/chromeVoxChromeBackgroundScript.js index 9ee7347..9665b1f 100644 --- a/src/chrome/third_party/chromevox/chromeVoxChromeBackgroundScript.js +++ b/src/chrome/third_party/chromevox/chromeVoxChromeBackgroundScript.js @@ -1589,7 +1589,7 @@ cvox.ChromeVoxEventWatcher.setLastFocusedNode_=function(a){cvox.ChromeVoxEventWa cvox.ChromeVoxEventWatcher.mutationHandler=function(a){if(cvox.ChromeVoxEventSuspender.areEventsSuspended())return!0;cvox.ChromeVox.navigationManager.updateIndicatorIfChanged();cvox.LiveRegions.processMutations(a,function(a,c){var d=new window.Event("LiveRegion");d.navDescriptions=c;d.assertive=a;cvox.ChromeVoxEventWatcher.addEvent(d,!0);return!0})}; cvox.ChromeVoxEventWatcher.mouseClickEventWatcher=function(a){if(a.fromCvox)return!0;if(cvox.ChromeVox.host.mustRedispatchClickEvent())return cvox.ChromeVoxUserCommands.wasMouseClicked=!0,a.stopPropagation(),a.preventDefault(),cvox.Focuser.setFocus(cvox.ChromeVox.navigationManager.getCurrentNode()),cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg("element_clicked"),cvox.ChromeVoxEventWatcher.queueMode_(),cvox.AbstractTts.PERSONALITY_ANNOTATION),a=cvox.ChromeVox.navigationManager.getCurrentNode(), cvox.DomUtil.clickElem(a,!1,!0),!1;cvox.ChromeVoxEventWatcher.addEvent(a);return cvox.ChromeVoxUserCommands.wasMouseClicked=!0}; -cvox.ChromeVoxEventWatcher.mouseOverEventWatcher=function(a){var b="ontouchstart"in window,c=cvox.ChromeVoxEventWatcher.mouseoverDelayMs;if(b)c=0;else if(!cvox.ChromeVoxEventWatcher.focusFollowsMouse)return!0;if(cvox.DomUtil.isDescendantOfNode(cvox.ChromeVoxEventWatcher.announcedMouseOverNode,a.target)||a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode)return!0;cvox.ChromeVoxEventWatcher.pendingMouseOverNode=a.target;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId), +cvox.ChromeVoxEventWatcher.mouseOverEventWatcher=function(a){var b=a.metaKey,c=cvox.ChromeVoxEventWatcher.mouseoverDelayMs;if(b)c=0;else if(!cvox.ChromeVoxEventWatcher.focusFollowsMouse)return!0;if(cvox.DomUtil.isDescendantOfNode(cvox.ChromeVoxEventWatcher.announcedMouseOverNode,a.target)||a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode)return!0;cvox.ChromeVoxEventWatcher.pendingMouseOverNode=a.target;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId), cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null);if(a.target.tagName&&"BODY"==a.target.tagName)return cvox.ChromeVoxEventWatcher.pendingMouseOverNode=null,cvox.ChromeVoxEventWatcher.announcedMouseOverNode=null,!0;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=window.setTimeout(function(){cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null;if(a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode){cvox.ChromeVoxEventWatcher.shouldFlushNextUtterance=!0;cvox.ChromeVox.navigationManager.stopReading(!0); var b=a.target;cvox.Focuser.setFocus(b);cvox.ApiImplementation.syncToNode(b,!0,cvox.ChromeVoxEventWatcher.queueMode_());cvox.ChromeVoxEventWatcher.announcedMouseOverNode=b}},c);return!0}; cvox.ChromeVoxEventWatcher.mouseOutEventWatcher=function(a){a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode&&(cvox.ChromeVoxEventWatcher.pendingMouseOverNode=null,cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId),cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null));return!0}; diff --git a/src/chrome/third_party/chromevox/chromeVoxChromeOptionsScript.js b/src/chrome/third_party/chromevox/chromeVoxChromeOptionsScript.js index 759b5c9..4637e9e 100644 --- a/src/chrome/third_party/chromevox/chromeVoxChromeOptionsScript.js +++ b/src/chrome/third_party/chromevox/chromeVoxChromeOptionsScript.js @@ -1525,7 +1525,7 @@ cvox.ChromeVoxEventWatcher.setLastFocusedNode_=function(a){cvox.ChromeVoxEventWa cvox.ChromeVoxEventWatcher.mutationHandler=function(a){if(cvox.ChromeVoxEventSuspender.areEventsSuspended())return!0;cvox.ChromeVox.navigationManager.updateIndicatorIfChanged();cvox.LiveRegions.processMutations(a,function(a,c){var d=new window.Event("LiveRegion");d.navDescriptions=c;d.assertive=a;cvox.ChromeVoxEventWatcher.addEvent(d,!0);return!0})}; cvox.ChromeVoxEventWatcher.mouseClickEventWatcher=function(a){if(a.fromCvox)return!0;if(cvox.ChromeVox.host.mustRedispatchClickEvent())return cvox.ChromeVoxUserCommands.wasMouseClicked=!0,a.stopPropagation(),a.preventDefault(),cvox.Focuser.setFocus(cvox.ChromeVox.navigationManager.getCurrentNode()),cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg("element_clicked"),cvox.ChromeVoxEventWatcher.queueMode_(),cvox.AbstractTts.PERSONALITY_ANNOTATION),a=cvox.ChromeVox.navigationManager.getCurrentNode(), cvox.DomUtil.clickElem(a,!1,!0),!1;cvox.ChromeVoxEventWatcher.addEvent(a);return cvox.ChromeVoxUserCommands.wasMouseClicked=!0}; -cvox.ChromeVoxEventWatcher.mouseOverEventWatcher=function(a){var b="ontouchstart"in window,c=cvox.ChromeVoxEventWatcher.mouseoverDelayMs;if(b)c=0;else if(!cvox.ChromeVoxEventWatcher.focusFollowsMouse)return!0;if(cvox.DomUtil.isDescendantOfNode(cvox.ChromeVoxEventWatcher.announcedMouseOverNode,a.target)||a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode)return!0;cvox.ChromeVoxEventWatcher.pendingMouseOverNode=a.target;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId), +cvox.ChromeVoxEventWatcher.mouseOverEventWatcher=function(a){var b=a.metaKey,c=cvox.ChromeVoxEventWatcher.mouseoverDelayMs;if(b)c=0;else if(!cvox.ChromeVoxEventWatcher.focusFollowsMouse)return!0;if(cvox.DomUtil.isDescendantOfNode(cvox.ChromeVoxEventWatcher.announcedMouseOverNode,a.target)||a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode)return!0;cvox.ChromeVoxEventWatcher.pendingMouseOverNode=a.target;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId), cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null);if(a.target.tagName&&"BODY"==a.target.tagName)return cvox.ChromeVoxEventWatcher.pendingMouseOverNode=null,cvox.ChromeVoxEventWatcher.announcedMouseOverNode=null,!0;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=window.setTimeout(function(){cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null;if(a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode){cvox.ChromeVoxEventWatcher.shouldFlushNextUtterance=!0;cvox.ChromeVox.navigationManager.stopReading(!0); var b=a.target;cvox.Focuser.setFocus(b);cvox.ApiImplementation.syncToNode(b,!0,cvox.ChromeVoxEventWatcher.queueMode_());cvox.ChromeVoxEventWatcher.announcedMouseOverNode=b}},c);return!0}; cvox.ChromeVoxEventWatcher.mouseOutEventWatcher=function(a){a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode&&(cvox.ChromeVoxEventWatcher.pendingMouseOverNode=null,cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId),cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null));return!0}; diff --git a/src/chrome/third_party/chromevox/chromeVoxChromePageScript.js b/src/chrome/third_party/chromevox/chromeVoxChromePageScript.js index af97838..32ba9af 100644 --- a/src/chrome/third_party/chromevox/chromeVoxChromePageScript.js +++ b/src/chrome/third_party/chromevox/chromeVoxChromePageScript.js @@ -1474,7 +1474,7 @@ cvox.ChromeVoxEventWatcher.setLastFocusedNode_=function(a){cvox.ChromeVoxEventWa cvox.ChromeVoxEventWatcher.mutationHandler=function(a){if(cvox.ChromeVoxEventSuspender.areEventsSuspended())return!0;cvox.ChromeVox.navigationManager.updateIndicatorIfChanged();cvox.LiveRegions.processMutations(a,function(a,c){var d=new window.Event("LiveRegion");d.navDescriptions=c;d.assertive=a;cvox.ChromeVoxEventWatcher.addEvent(d,!0);return!0})}; cvox.ChromeVoxEventWatcher.mouseClickEventWatcher=function(a){if(a.fromCvox)return!0;if(cvox.ChromeVox.host.mustRedispatchClickEvent())return cvox.ChromeVoxUserCommands.wasMouseClicked=!0,a.stopPropagation(),a.preventDefault(),cvox.Focuser.setFocus(cvox.ChromeVox.navigationManager.getCurrentNode()),cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg("element_clicked"),cvox.ChromeVoxEventWatcher.queueMode_(),cvox.AbstractTts.PERSONALITY_ANNOTATION),a=cvox.ChromeVox.navigationManager.getCurrentNode(), cvox.DomUtil.clickElem(a,!1,!0),!1;cvox.ChromeVoxEventWatcher.addEvent(a);return cvox.ChromeVoxUserCommands.wasMouseClicked=!0}; -cvox.ChromeVoxEventWatcher.mouseOverEventWatcher=function(a){var b="ontouchstart"in window,c=cvox.ChromeVoxEventWatcher.mouseoverDelayMs;if(b)c=0;else if(!cvox.ChromeVoxEventWatcher.focusFollowsMouse)return!0;if(cvox.DomUtil.isDescendantOfNode(cvox.ChromeVoxEventWatcher.announcedMouseOverNode,a.target)||a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode)return!0;cvox.ChromeVoxEventWatcher.pendingMouseOverNode=a.target;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId), +cvox.ChromeVoxEventWatcher.mouseOverEventWatcher=function(a){var b=a.metaKey,c=cvox.ChromeVoxEventWatcher.mouseoverDelayMs;if(b)c=0;else if(!cvox.ChromeVoxEventWatcher.focusFollowsMouse)return!0;if(cvox.DomUtil.isDescendantOfNode(cvox.ChromeVoxEventWatcher.announcedMouseOverNode,a.target)||a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode)return!0;cvox.ChromeVoxEventWatcher.pendingMouseOverNode=a.target;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId), cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null);if(a.target.tagName&&"BODY"==a.target.tagName)return cvox.ChromeVoxEventWatcher.pendingMouseOverNode=null,cvox.ChromeVoxEventWatcher.announcedMouseOverNode=null,!0;cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=window.setTimeout(function(){cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null;if(a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode){cvox.ChromeVoxEventWatcher.shouldFlushNextUtterance=!0;cvox.ChromeVox.navigationManager.stopReading(!0); var b=a.target;cvox.Focuser.setFocus(b);cvox.ApiImplementation.syncToNode(b,!0,cvox.ChromeVoxEventWatcher.queueMode_());cvox.ChromeVoxEventWatcher.announcedMouseOverNode=b}},c);return!0}; cvox.ChromeVoxEventWatcher.mouseOutEventWatcher=function(a){a.target==cvox.ChromeVoxEventWatcher.pendingMouseOverNode&&(cvox.ChromeVoxEventWatcher.pendingMouseOverNode=null,cvox.ChromeVoxEventWatcher.mouseOverTimeoutId&&(window.clearTimeout(cvox.ChromeVoxEventWatcher.mouseOverTimeoutId),cvox.ChromeVoxEventWatcher.mouseOverTimeoutId=null));return!0}; diff --git a/src/chrome_elf/blacklist/blacklist.cc b/src/chrome_elf/blacklist/blacklist.cc index efb9c97..4026a0a 100644 --- a/src/chrome_elf/blacklist/blacklist.cc +++ b/src/chrome_elf/blacklist/blacklist.cc @@ -34,11 +34,19 @@ const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = { // See crbug.com/379218. L"activedetect64.dll", // Lenovo One Key Theater. L"bitguard.dll", // Unknown (suspected malware). + L"cespy.dll", // CovenantEyes. L"chrmxtn.dll", // Unknown (keystroke logger). + L"cplushook.dll", // Unknown (suspected malware). L"datamngr.dll", // Unknown (suspected adware). L"hk.dll", // Unknown (keystroke logger). + L"libapi2hook.dll", // V-Bates. + L"libinject.dll", // V-Bates. + L"libinject2.dll", // V-Bates. + L"libredir2.dll", // V-Bates. L"libsvn_tsvn32.dll", // TortoiseSVN. + L"libwinhook.dll", // V-Bates. L"lmrn.dll", // Unknown. + L"minisp.dll", // Unknown (suspected malware). L"scdetour.dll", // Quick Heal Antivirus. // See crbug.com/382561. L"systemk.dll", // Unknown (suspected adware). diff --git a/src/components/policy/resources/policy_templates_fa.xtb b/src/components/policy/resources/policy_templates_fa.xtb index 0429514..60897eb 100644 --- a/src/components/policy/resources/policy_templates_fa.xtb +++ b/src/components/policy/resources/policy_templates_fa.xtb @@ -826,7 +826,7 @@ اگر این خط‌مشی را تنظیم کرده باشید، کاربران نمی‌توانند آن را تغییر دهند یا لغو نمایند. چنانچه این خط‌مشی بدون تنظیم رها شده باشد، نشانگر موشواره بزرگ از ابتدا از کار افتاده است اما می‌تواند در هر زمان توسط کاربر به کار انداخته شود. -فعال کردن بازخورد صوتی +فعال کردن بازخورد گفتاری این خط‌مشی از نسخه ۳۵ کنار گذاشته شده است. اطلاعات حافظه به هر حال، بدون در نظر گرفتن مقدار گزینه، به صفحه گزارش داده خواهد شد، اما اندازه‌های گزارش شده diff --git a/src/components/policy/resources/policy_templates_id.xtb b/src/components/policy/resources/policy_templates_id.xtb index b703054..63d62ce 100644 --- a/src/components/policy/resources/policy_templates_id.xtb +++ b/src/components/policy/resources/policy_templates_id.xtb @@ -545,7 +545,7 @@ Ekstensi URL yang akan diberi akses ke perangkat perekam video tanpa peringatan Laporkan lokasi perangkat -Setel ukuran cache disk dalam byte +Setel ukuran cache disk dalam bita Mengaktifkan pengoptimalan WPAD pada dan mencegah pengguna mengubah setelan ini. Menyetel kebijakan ini menjadi aktif akan menyebabkan Chrome menunggu dalam interval yang lebih pendek bagi server WPAD berbasis DNS. @@ -1353,7 +1353,7 @@ Jika kebijakan ini tidak disetel, keyboard di layar akan dinonaktifkan pada awalnya namun dapat diaktifkan oleh pengguna kapan saja. Aturan heuristis juga dapat digunakan untuk menentukan waktu untuk menampilkan keyboard. Izinkan host Native Messaging tingkat pengguna (dipasang tanpa izin admin). Izinkan semua situs menjalankan plugin secara otomatis -Setel ukuran cache disk media dalam byte +Setel ukuran cache disk media dalam bita Menentukan apakah pencari plugin harus dinonaktifkan Nama hosting perpesanan asli yang dilarang (atau * untuk semua) Menyetel jenis lup yang diaktifkan. diff --git a/src/components/strings/components_strings_sr.xtb b/src/components/strings/components_strings_sr.xtb index 8ababa4..e456729 100644 --- a/src/components/strings/components_strings_sr.xtb +++ b/src/components/strings/components_strings_sr.xtb @@ -64,7 +64,7 @@ Онемогућен је Ниво Вредност је изван опсега . -Учитавање... +Учитава се... Департман Неисправан потпис Погрешан тип смерница diff --git a/src/content/browser/android/content_view_core_impl.cc b/src/content/browser/android/content_view_core_impl.cc index fc0af4c..1021550 100644 --- a/src/content/browser/android/content_view_core_impl.cc +++ b/src/content/browser/android/content_view_core_impl.cc @@ -944,7 +944,10 @@ jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env, jfloat touch_major_0, jfloat touch_major_1, jfloat raw_pos_x, - jfloat raw_pos_y) { + jfloat raw_pos_y, + jint android_tool_type_0, + jint android_tool_type_1, + jint android_button_state) { RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); // Avoid synthesizing a touch event if it cannot be forwarded. if (!rwhv) @@ -967,7 +970,10 @@ jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env, touch_major_0, touch_major_1, raw_pos_x, - raw_pos_y); + raw_pos_y, + android_tool_type_0, + android_tool_type_1, + android_button_state); return rwhv->OnTouchEvent(event); } @@ -1523,6 +1529,14 @@ void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj, SetAccessibilityEnabledInternal(enabled); } +void ContentViewCoreImpl::ShowSelectionHandlesAutomatically() const { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef obj(java_ref_.get(env)); + if (obj.is_null()) + return; + Java_ContentViewCore_showSelectionHandlesAutomatically(env, obj.obj()); +} + void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) { accessibility_enabled_ = enabled; RenderWidgetHostViewAndroid* host_view = GetRenderWidgetHostViewAndroid(); @@ -1598,14 +1612,18 @@ void ContentViewCoreImpl::RequestTextSurroundingSelection( } void ContentViewCoreImpl::OnSmartClipDataExtracted( - const base::string16& result) { + const base::string16& text, + const base::string16& html, + const gfx::Rect& clip_rect) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef obj = java_ref_.get(env); if (obj.is_null()) return; - ScopedJavaLocalRef jresult = ConvertUTF16ToJavaString(env, result); + ScopedJavaLocalRef jtext = ConvertUTF16ToJavaString(env, text); + ScopedJavaLocalRef jhtml = ConvertUTF16ToJavaString(env, html); + ScopedJavaLocalRef clip_rect_object(CreateJavaRect(env, clip_rect)); Java_ContentViewCore_onSmartClipDataExtracted( - env, obj.obj(), jresult.obj()); + env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj()); } void ContentViewCoreImpl::WebContentsDestroyed() { diff --git a/src/content/browser/android/content_view_core_impl.h b/src/content/browser/android/content_view_core_impl.h index 3bb1291..462f3dc 100644 --- a/src/content/browser/android/content_view_core_impl.h +++ b/src/content/browser/android/content_view_core_impl.h @@ -114,7 +114,10 @@ class ContentViewCoreImpl : public ContentViewCore, jfloat touch_major_0, jfloat touch_major_1, jfloat raw_pos_x, - jfloat raw_pos_y); + jfloat raw_pos_y, + jint android_tool_type_0, + jint android_tool_type_1, + jint android_button_state); jboolean SendMouseMoveEvent(JNIEnv* env, jobject obj, jlong time_ms, @@ -235,7 +238,9 @@ class ContentViewCoreImpl : public ContentViewCore, // Public methods that call to Java via JNI // -------------------------------------------------------------------------- - void OnSmartClipDataExtracted(const base::string16& result); + void OnSmartClipDataExtracted(const base::string16& text, + const base::string16& html, + const gfx::Rect& clip_rect); // Creates a popup menu with |items|. // |multiple| defines if it should support multi-select. @@ -302,6 +307,8 @@ class ContentViewCoreImpl : public ContentViewCore, void SetAccessibilityEnabledInternal(bool enabled); + void ShowSelectionHandlesAutomatically() const; + // -------------------------------------------------------------------------- // Methods called from native code // -------------------------------------------------------------------------- diff --git a/src/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/src/content/browser/android/in_process/synchronous_compositor_factory_impl.cc index c19173c..e5a0a68 100644 --- a/src/content/browser/android/in_process/synchronous_compositor_factory_impl.cc +++ b/src/content/browser/android/in_process/synchronous_compositor_factory_impl.cc @@ -228,6 +228,11 @@ void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() { base::AutoLock lock(num_hardware_compositor_lock_); DCHECK_GT(num_hardware_compositors_, 0u); num_hardware_compositors_--; + if (num_hardware_compositors_ == 0) { + // Nullify the video_context_provider_ now so that it is not null only if + // there is at least 1 hardware compositor + video_context_provider_ = NULL; + } } bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() { @@ -241,8 +246,8 @@ SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() { context_provider; // This check only guarantees the main thread context is created after // a compositor did successfully initialize hardware draw in the past. - // In particular this does not guarantee that the main thread context - // will fail creation when all compositors release hardware draw. + // When all compositors have released hardware draw, main thread context + // creation is guaranteed to fail. if (CanCreateMainThreadContext() && !video_context_provider_) { DCHECK(service_); DCHECK(share_context_.get()); diff --git a/src/content/browser/media/android/browser_media_player_manager.cc b/src/content/browser/media/android/browser_media_player_manager.cc index 5df9016..d0c0a69 100644 --- a/src/content/browser/media/android/browser_media_player_manager.cc +++ b/src/content/browser/media/android/browser_media_player_manager.cc @@ -26,6 +26,7 @@ #include "content/public/common/content_switches.h" #include "media/base/android/media_player_bridge.h" #include "media/base/android/media_source_player.h" +#include "media/base/android/media_url_interceptor.h" #include "media/base/media_switches.h" using media::MediaPlayerAndroid; @@ -40,6 +41,7 @@ namespace content { const int kMediaPlayerThreshold = 1; static BrowserMediaPlayerManager::Factory g_factory = NULL; +static media::MediaUrlInterceptor* media_url_interceptor_ = NULL; // static void BrowserMediaPlayerManager::RegisterFactory(Factory factory) { @@ -47,6 +49,12 @@ void BrowserMediaPlayerManager::RegisterFactory(Factory factory) { } // static +void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor( + media::MediaUrlInterceptor* media_url_interceptor) { + media_url_interceptor_ = media_url_interceptor; +} + +// static BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create( RenderFrameHost* rfh) { if (g_factory) @@ -77,7 +85,8 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer( weak_ptr_factory_.GetWeakPtr()), base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesReleased, weak_ptr_factory_.GetWeakPtr()), - media_player_params.frame_url); + media_player_params.frame_url, + media_player_params.allow_credentials); BrowserMediaPlayerManager* browser_media_player_manager = static_cast(manager); ContentViewCoreImpl* content_view_core_impl = @@ -297,6 +306,11 @@ BrowserMediaPlayerManager::GetMediaResourceGetter() { return media_resource_getter_.get(); } +media::MediaUrlInterceptor* +BrowserMediaPlayerManager::GetMediaUrlInterceptor() { + return media_url_interceptor_; +} + MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() { return GetPlayer(fullscreen_player_id_); } @@ -395,6 +409,24 @@ void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) { video_view_->OpenVideo(); return; } else if (!ContentVideoView::GetInstance()) { + if (!GetPlayer(player_id)) { + // If a player doesn't exist, it must be waiting for CORS check. + // As a result, just request the tab to enter fullscreen mode without + // creating the surface view. This is only needed for M37. + Send(new MediaPlayerMsg_DidEnterFullscreen(RoutingID(), player_id)); + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableOverlayFullscreenVideoSubtitle)) { + return; + } + if (RenderWidgetHostViewAndroid* view_android = + static_cast( + web_contents_->GetRenderWidgetHostView())) { + view_android->SetOverlayVideoMode(true); + } + if (WebContentsDelegate* delegate = web_contents_->GetDelegate()) + delegate->ToggleFullscreenModeForTab(web_contents_, true); + } + // In Android WebView, two ContentViewCores could both try to enter // fullscreen video, we just ignore the second one. video_view_.reset(new ContentVideoView(this)); diff --git a/src/content/browser/media/android/browser_media_player_manager.h b/src/content/browser/media/android/browser_media_player_manager.h index 4c53388..5f3fae5 100644 --- a/src/content/browser/media/android/browser_media_player_manager.h +++ b/src/content/browser/media/android/browser_media_player_manager.h @@ -16,6 +16,7 @@ #include "ipc/ipc_message.h" #include "media/base/android/media_player_android.h" #include "media/base/android/media_player_manager.h" +#include "media/base/android/media_url_interceptor.h" #include "ui/gfx/rect_f.h" #include "url/gurl.h" @@ -44,6 +45,10 @@ class CONTENT_EXPORT BrowserMediaPlayerManager typedef BrowserMediaPlayerManager* (*Factory)(RenderFrameHost*); static void RegisterFactory(Factory factory); + // Permits embedders to handle custom urls. + static void RegisterMediaUrlInterceptor( + media::MediaUrlInterceptor* media_url_interceptor); + // Returns a new instance using the registered factory if available. static BrowserMediaPlayerManager* Create(RenderFrameHost* rfh); @@ -84,6 +89,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager virtual void OnVideoSizeChanged( int player_id, int width, int height) OVERRIDE; virtual media::MediaResourceGetter* GetMediaResourceGetter() OVERRIDE; + virtual media::MediaUrlInterceptor* GetMediaUrlInterceptor() OVERRIDE; virtual media::MediaPlayerAndroid* GetFullscreenPlayer() OVERRIDE; virtual media::MediaPlayerAndroid* GetPlayer(int player_id) OVERRIDE; virtual void RequestFullScreen(int player_id) OVERRIDE; diff --git a/src/content/browser/media/android/media_resource_getter_impl.cc b/src/content/browser/media/android/media_resource_getter_impl.cc index bcf293d..dac0059 100644 --- a/src/content/browser/media/android/media_resource_getter_impl.cc +++ b/src/content/browser/media/android/media_resource_getter_impl.cc @@ -18,6 +18,8 @@ #include "content/public/common/content_client.h" #include "content/public/common/url_constants.h" #include "jni/MediaResourceGetter_jni.h" +#include "media/base/android/media_url_interceptor.h" +#include "net/base/auth.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_store.h" #include "net/url_request/url_request_context.h" @@ -75,7 +77,21 @@ static void RequestPlaformPathFromFileSystemURL( ReturnResultOnUIThread(callback, std::string()); } -// Get the metadata from a media URL. When finished, a task is posted to the UI +// Posts a task to the UI thread to run the callback function. +static void PostMediaMetadataCallbackTask( + const media::MediaResourceGetter::ExtractMediaMetadataCB& callback, + JNIEnv* env, ScopedJavaLocalRef& j_metadata) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(callback, base::TimeDelta::FromMilliseconds( + Java_MediaMetadata_getDurationInMilliseconds( + env, j_metadata.obj())), + Java_MediaMetadata_getWidth(env, j_metadata.obj()), + Java_MediaMetadata_getHeight(env, j_metadata.obj()), + Java_MediaMetadata_isSuccess(env, j_metadata.obj()))); +} + +// Gets the metadata from a media URL. When finished, a task is posted to the UI // thread to run the callback function. static void GetMediaMetadata( const std::string& url, const std::string& cookies, @@ -94,14 +110,22 @@ static void GetMediaMetadata( j_url_string.obj(), j_cookies.obj(), j_user_agent.obj()); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(callback, base::TimeDelta::FromMilliseconds( - Java_MediaMetadata_getDurationInMilliseconds( - env, j_metadata.obj())), - Java_MediaMetadata_getWidth(env, j_metadata.obj()), - Java_MediaMetadata_getHeight(env, j_metadata.obj()), - Java_MediaMetadata_isSuccess(env, j_metadata.obj()))); + + PostMediaMetadataCallbackTask(callback, env, j_metadata); +} + +// Gets the metadata from a file descriptor. When finished, a task is posted to +// the UI thread to run the callback function. +static void GetMediaMetadataFromFd( + const int fd, const int64 offset, const int64 size, + const media::MediaResourceGetter::ExtractMediaMetadataCB& callback) { + JNIEnv* env = base::android::AttachCurrentThread(); + + ScopedJavaLocalRef j_metadata = + Java_MediaResourceGetter_extractMediaMetadataFromFd( + env, fd, offset, size); + + PostMediaMetadataCallbackTask(callback, env, j_metadata); } // The task object that retrieves cookie on the IO thread. @@ -276,6 +300,16 @@ void MediaResourceGetterImpl::ExtractMediaMetadata( base::Bind(&GetMediaMetadata, url, cookies, user_agent, callback)); } +void MediaResourceGetterImpl::ExtractMediaMetadata( + const int fd, const int64 offset, const int64 size, + const ExtractMediaMetadataCB& callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool(); + pool->PostWorkerTask( + FROM_HERE, + base::Bind(&GetMediaMetadataFromFd, fd, offset, size, callback)); +} + // static bool MediaResourceGetterImpl::RegisterMediaResourceGetter(JNIEnv* env) { return RegisterNativesImpl(env); diff --git a/src/content/browser/media/android/media_resource_getter_impl.h b/src/content/browser/media/android/media_resource_getter_impl.h index c1ed4b9..252ada8 100644 --- a/src/content/browser/media/android/media_resource_getter_impl.h +++ b/src/content/browser/media/android/media_resource_getter_impl.h @@ -12,6 +12,8 @@ #include "base/memory/weak_ptr.h" #include "base/synchronization/waitable_event.h" #include "media/base/android/media_resource_getter.h" +#include "media/base/android/media_url_interceptor.h" +#include "net/base/auth.h" #include "net/cookies/canonical_cookie.h" namespace fileapi { @@ -51,6 +53,11 @@ class MediaResourceGetterImpl : public media::MediaResourceGetter { const std::string& url, const std::string& cookies, const std::string& user_agent, const ExtractMediaMetadataCB& callback) OVERRIDE; + virtual void ExtractMediaMetadata( + const int fd, + const int64 offset, + const int64 size, + const ExtractMediaMetadataCB& callback) OVERRIDE; static bool RegisterMediaResourceGetter(JNIEnv* env); diff --git a/src/content/browser/renderer_host/input/gesture_text_selector.cc b/src/content/browser/renderer_host/input/gesture_text_selector.cc new file mode 100644 index 0000000..59f28cf --- /dev/null +++ b/src/content/browser/renderer_host/input/gesture_text_selector.cc @@ -0,0 +1,74 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/gesture_text_selector.h" + +#include "ui/events/event_constants.h" +#include "ui/events/gesture_detection/gesture_event_data.h" +#include "ui/events/gesture_detection/motion_event.h" + +namespace content { + +GestureTextSelector::GestureTextSelector(GestureTextSelectorClient* client) + : client_(client), + text_selection_triggered_(false), + anchor_x_(0.0f), + anchor_y_(0.0f) { +} + +GestureTextSelector::~GestureTextSelector() { +} + +bool GestureTextSelector::OnTouchEvent(const ui::MotionEvent& event) { + if (event.GetAction() == ui::MotionEvent::ACTION_DOWN) { + // Only trigger selection on ACTION_DOWN to prevent partial touch or gesture + // sequences from being forwarded. + text_selection_triggered_ = ShouldStartTextSelection(event); + } + return text_selection_triggered_; +} + +bool GestureTextSelector::OnGestureEvent(const ui::GestureEventData& gesture) { + if (!text_selection_triggered_) + return false; + + switch (gesture.type()) { + case ui::ET_GESTURE_TAP: { + client_->LongPress(gesture.time, gesture.x, gesture.y); + break; + } + case ui::ET_GESTURE_SCROLL_BEGIN: { + client_->Unselect(); + anchor_x_ = gesture.x; + anchor_y_ = gesture.y; + break; + } + case ui::ET_GESTURE_SCROLL_UPDATE: { + // TODO(changwan): check if we can show handles on ET_GESTURE_SCROLL_END + // instead. Currently it is not possible as ShowSelectionHandles should + // be called before we change the selection. + client_->ShowSelectionHandlesAutomatically(); + client_->SelectRange(anchor_x_, anchor_y_, gesture.x, gesture.y); + break; + } + default: + // Suppress all other gestures when we are selecting text. + break; + } + return true; +} + +// static +bool GestureTextSelector::ShouldStartTextSelection( + const ui::MotionEvent& event) { + DCHECK_GT(event.GetPointerCount(), 0u); + // Currently we are supporting stylus-only cases. + const bool is_stylus = + event.GetToolType(0) == ui::MotionEvent::TOOL_TYPE_STYLUS; + const bool is_only_secondary_button_pressed = + event.GetButtonState() == ui::MotionEvent::BUTTON_SECONDARY; + return is_stylus && is_only_secondary_button_pressed; +} + +} // namespace content diff --git a/src/content/browser/renderer_host/input/gesture_text_selector.h b/src/content/browser/renderer_host/input/gesture_text_selector.h new file mode 100644 index 0000000..092c30d --- /dev/null +++ b/src/content/browser/renderer_host/input/gesture_text_selector.h @@ -0,0 +1,65 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_TEXT_SELECTOR_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_TEXT_SELECTOR_H_ + +#include "base/gtest_prod_util.h" +#include "base/macros.h" +#include "base/time/time.h" +#include "content/common/content_export.h" + +namespace ui { +struct GestureEventData; +class MotionEvent; +} + +namespace content { +class GestureTextSelectorTest; + +// Interface with which GestureTextSelector can select, unselect, show +// selection handles, or long press. +class CONTENT_EXPORT GestureTextSelectorClient { + public: + virtual ~GestureTextSelectorClient() {} + + virtual void ShowSelectionHandlesAutomatically() = 0; + virtual void SelectRange(float x1, float y1, float x2, float y2) = 0; + virtual void Unselect() = 0; + virtual void LongPress(base::TimeTicks time, float x, float y) = 0; +}; + +// A class to handle gesture-based text selection, such as when clicking first +// button on stylus input. It also generates a synthetic long press gesture on +// tap so that a word can be selected or the contextual menu can be shown. +class CONTENT_EXPORT GestureTextSelector { + public: + explicit GestureTextSelector(GestureTextSelectorClient* client); + virtual ~GestureTextSelector(); + + // This should be called after gesture detection but before associated + // gestures are dispatched. Returns whether it will consume |event|. + bool OnTouchEvent(const ui::MotionEvent& event); + + // Returns whether it will consume the event. + bool OnGestureEvent(const ui::GestureEventData& gesture); + + private: + friend class GestureTextSelectorTest; + FRIEND_TEST_ALL_PREFIXES(GestureTextSelectorTest, + ShouldStartTextSelection); + + static bool ShouldStartTextSelection(const ui::MotionEvent& event); + + GestureTextSelectorClient* client_; + bool text_selection_triggered_; + float anchor_x_; + float anchor_y_; + + DISALLOW_COPY_AND_ASSIGN(GestureTextSelector); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_TEXT_SELECTOR_H_ diff --git a/src/content/browser/renderer_host/input/gesture_text_selector_unittest.cc b/src/content/browser/renderer_host/input/gesture_text_selector_unittest.cc new file mode 100644 index 0000000..c5be224 --- /dev/null +++ b/src/content/browser/renderer_host/input/gesture_text_selector_unittest.cc @@ -0,0 +1,221 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include + +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "content/browser/renderer_host/input/gesture_text_selector.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/event_constants.h" +#include "ui/events/gesture_detection/gesture_event_data.h" +#include "ui/events/gesture_detection/motion_event.h" +#include "ui/events/test/mock_motion_event.h" +#include "ui/gfx/geometry/rect_f.h" + +using ui::GestureEventData; +using ui::GestureEventDetails; +using ui::MotionEvent; +using ui::test::MockMotionEvent; + +namespace content { + +class GestureTextSelectorTest : public testing::Test, + public GestureTextSelectorClient { + public: + GestureTextSelectorTest() {} + virtual ~GestureTextSelectorTest() {} + + // Test implementation. + virtual void SetUp() OVERRIDE { + selector_.reset(new GestureTextSelector(this)); + event_log_.clear(); + } + + virtual void TearDown() OVERRIDE { + selector_.reset(); + event_log_.clear(); + } + + // GestureTextSelectorClient implementation. + virtual void ShowSelectionHandlesAutomatically() OVERRIDE { + event_log_.push_back("Show"); + } + + virtual void SelectRange(float x1, float y1, float x2, float y2) OVERRIDE { + event_log_.push_back("SelectRange"); + } + + virtual void Unselect() OVERRIDE { + event_log_.push_back("Unselect"); + } + + virtual void LongPress(base::TimeTicks time, float x, float y) OVERRIDE { + event_log_.push_back("LongPress"); + } + + protected: + scoped_ptr selector_; + std::vector event_log_; +}; + +TEST_F(GestureTextSelectorTest, ShouldStartTextSelection) { + base::TimeTicks event_time = base::TimeTicks::Now(); + { // Touched with a finger. + MockMotionEvent e(MotionEvent::ACTION_DOWN, event_time, 50.0f, 50.0f); + e.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER); + e.SetButtonState(0); + EXPECT_FALSE(selector_->ShouldStartTextSelection(e)); + } + + { // Touched with a stylus, but no button pressed. + MockMotionEvent e(MotionEvent::ACTION_DOWN, event_time, 50.0f, 50.0f); + e.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + e.SetButtonState(0); + EXPECT_FALSE(selector_->ShouldStartTextSelection(e)); + } + + { // Touched with a stylus, with first button (BUTTON_SECONDARY) pressed. + MockMotionEvent e(MotionEvent::ACTION_DOWN, event_time, 50.0f, 50.0f); + e.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + e.SetButtonState(MotionEvent::BUTTON_SECONDARY); + EXPECT_TRUE(selector_->ShouldStartTextSelection(e)); + } + + { // Touched with a stylus, with two buttons pressed. + MockMotionEvent e(MotionEvent::ACTION_DOWN, event_time, 50.0f, 50.0f); + e.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + e.SetButtonState( + MotionEvent::BUTTON_SECONDARY | MotionEvent::BUTTON_TERTIARY); + EXPECT_FALSE(selector_->ShouldStartTextSelection(e)); + } +} + +TEST_F(GestureTextSelectorTest, FingerTouch) { + base::TimeTicks event_time = base::TimeTicks::Now(); + const float x = 50.0f; + const float y = 30.0f; + // 1. Touched with a finger: ignored + MockMotionEvent finger(MotionEvent::ACTION_DOWN, event_time, x, y); + finger.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER); + EXPECT_FALSE(selector_->OnTouchEvent(finger)); + // We do not consume finger events. + EXPECT_TRUE(event_log_.empty()); +} + +TEST_F(GestureTextSelectorTest, PenDragging) { + base::TimeTicks event_time = base::TimeTicks::Now(); + const float x1 = 50.0f; + const float y1 = 30.0f; + const float x2 = 100.0f; + const float y2 = 90.0f; + // 1. ACTION_DOWN with stylus + button + event_time += base::TimeDelta::FromMilliseconds(10); + MockMotionEvent action_down(MotionEvent::ACTION_DOWN, event_time, x1, y1); + action_down.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + action_down.SetButtonState(MotionEvent::BUTTON_SECONDARY); + EXPECT_TRUE(selector_->OnTouchEvent(action_down)); + EXPECT_TRUE(event_log_.empty()); + + // 2. ACTION_MOVE + event_time += base::TimeDelta::FromMilliseconds(10); + MockMotionEvent action_move(MotionEvent::ACTION_MOVE, event_time, x2, y2); + action_move.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + action_move.SetButtonState(MotionEvent::BUTTON_SECONDARY); + EXPECT_TRUE(selector_->OnTouchEvent(action_move)); + EXPECT_TRUE(event_log_.empty()); + + // 3. DOUBLE TAP + // Suppress most gesture events when in text selection mode. + event_time += base::TimeDelta::FromMilliseconds(10); + const GestureEventData double_tap( + GestureEventDetails(ui::ET_GESTURE_DOUBLE_TAP, 0, 0), 0, event_time, + x2, y2, x2, y2, 1, gfx::RectF(0, 0, 0, 0)); + EXPECT_TRUE(selector_->OnGestureEvent(double_tap)); + EXPECT_TRUE(event_log_.empty()); + + // 4. ET_GESTURE_SCROLL_BEGIN + event_time += base::TimeDelta::FromMilliseconds(10); + const GestureEventData scroll_begin( + GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0), 0, event_time, + x1, y1, x1, y1, 1, gfx::RectF(0, 0, 0, 0)); + EXPECT_TRUE(selector_->OnGestureEvent(scroll_begin)); + EXPECT_EQ(1u, event_log_.size()); // Unselect + + // 5. ET_GESTURE_SCROLL_UPDATE + event_time += base::TimeDelta::FromMilliseconds(10); + const GestureEventData scroll_update( + GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 0, 0), 0, event_time, + x2, y2, x2, y2, 1, gfx::RectF(0, 0, 0, 0)); + EXPECT_TRUE(selector_->OnGestureEvent(scroll_update)); + EXPECT_EQ(3u, event_log_.size()); // Unselect, Show, SelectRange + EXPECT_STREQ("SelectRange", event_log_.back().c_str()); + + // 6. ACTION_UP + event_time += base::TimeDelta::FromMilliseconds(10); + MockMotionEvent action_up(MotionEvent::ACTION_UP, event_time, x2, y2); + action_up.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + action_up.SetButtonState(0); + EXPECT_TRUE(selector_->OnTouchEvent(action_up)); + EXPECT_EQ(3u, event_log_.size()); // NO CHANGE + + // 7. ET_GESTURE_SCROLL_END + event_time += base::TimeDelta::FromMilliseconds(10); + const GestureEventData scroll_end( + GestureEventDetails(ui::ET_GESTURE_SCROLL_END, 0, 0), 0, event_time, + x2, y2, x2, y2, 1, gfx::RectF(0, 0, 0, 0)); + EXPECT_TRUE(selector_->OnGestureEvent(scroll_end)); + EXPECT_EQ(3u, event_log_.size()); // NO CHANGE +} + +TEST_F(GestureTextSelectorTest, TapToSelectWord) { + base::TimeTicks event_time = base::TimeTicks::Now(); + const float x1 = 50.0f; + const float y1 = 30.0f; + const float x2 = 51.0f; + const float y2 = 31.0f; + // 1. ACTION_DOWN with stylus + button + event_time += base::TimeDelta::FromMilliseconds(10); + MockMotionEvent action_down(MotionEvent::ACTION_DOWN, event_time, x1, y1); + action_down.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + action_down.SetButtonState(MotionEvent::BUTTON_SECONDARY); + EXPECT_TRUE(selector_->OnTouchEvent(action_down)); + EXPECT_TRUE(event_log_.empty()); + + // 5. TAP_DOWN + event_time += base::TimeDelta::FromMilliseconds(10); + const GestureEventData tap_down( + GestureEventDetails(ui::ET_GESTURE_TAP_DOWN, 0, 0), 0, event_time, + x2, y2, x2, y2, 1, gfx::RectF(0, 0, 0, 0)); + EXPECT_TRUE(selector_->OnGestureEvent(tap_down)); + EXPECT_TRUE(event_log_.empty()); + + // 2. ACTION_MOVE + event_time += base::TimeDelta::FromMilliseconds(10); + MockMotionEvent action_move(MotionEvent::ACTION_MOVE, event_time, x2, y2); + action_move.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + action_move.SetButtonState(MotionEvent::BUTTON_SECONDARY); + EXPECT_TRUE(selector_->OnTouchEvent(action_move)); + EXPECT_TRUE(event_log_.empty()); + + // 3. ACTION_UP + event_time += base::TimeDelta::FromMilliseconds(10); + MockMotionEvent action_up(MotionEvent::ACTION_UP, event_time, x2, y2); + action_up.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS); + action_up.SetButtonState(0); + EXPECT_TRUE(selector_->OnTouchEvent(action_up)); + EXPECT_TRUE(event_log_.empty()); + + // 4. TAP + event_time += base::TimeDelta::FromMilliseconds(10); + const GestureEventData tap( + GestureEventDetails(ui::ET_GESTURE_TAP, 0, 0), 0, event_time, + x1, y1, x1, y1, 1, gfx::RectF(0, 0, 0, 0)); + EXPECT_TRUE(selector_->OnGestureEvent(tap)); + EXPECT_EQ(1u, event_log_.size()); // LongPress + EXPECT_STREQ("LongPress", event_log_.back().c_str()); +} + +} // namespace content diff --git a/src/content/browser/renderer_host/input/motion_event_android.cc b/src/content/browser/renderer_host/input/motion_event_android.cc index 7409955..7316a40 100644 --- a/src/content/browser/renderer_host/input/motion_event_android.cc +++ b/src/content/browser/renderer_host/input/motion_event_android.cc @@ -54,6 +54,38 @@ MotionEventAndroid::Action FromAndroidAction(int android_action) { return MotionEventAndroid::ACTION_CANCEL; } +MotionEventAndroid::ToolType FromAndroidToolType(int android_tool_type) { + switch (android_tool_type) { + case TOOL_TYPE_UNKNOWN: + return MotionEventAndroid::TOOL_TYPE_UNKNOWN; + case TOOL_TYPE_FINGER: + return MotionEventAndroid::TOOL_TYPE_FINGER; + case TOOL_TYPE_STYLUS: + return MotionEventAndroid::TOOL_TYPE_STYLUS; + case TOOL_TYPE_MOUSE: + return MotionEventAndroid::TOOL_TYPE_MOUSE; + default: + NOTREACHED() << "Invalid Android MotionEvent tool type: " + << android_tool_type; + }; + return MotionEventAndroid::TOOL_TYPE_UNKNOWN; +} + +int FromAndroidButtonState(int button_state) { + int result = 0; + if ((button_state & BUTTON_BACK) != 0) + result |= MotionEventAndroid::BUTTON_BACK; + if ((button_state & BUTTON_FORWARD) != 0) + result |= MotionEventAndroid::BUTTON_FORWARD; + if ((button_state & BUTTON_PRIMARY) != 0) + result |= MotionEventAndroid::BUTTON_PRIMARY; + if ((button_state & BUTTON_SECONDARY) != 0) + result |= MotionEventAndroid::BUTTON_SECONDARY; + if ((button_state & BUTTON_TERTIARY) != 0) + result |= MotionEventAndroid::BUTTON_TERTIARY; + return result; +} + int64 ToAndroidTime(base::TimeTicks time) { return (time - base::TimeTicks()).InMilliseconds(); } @@ -81,12 +113,16 @@ MotionEventAndroid::MotionEventAndroid(float pix_to_dip, jfloat touch_major_0_pixels, jfloat touch_major_1_pixels, jfloat raw_pos_x_pixels, - jfloat raw_pos_y_pixels) + jfloat raw_pos_y_pixels, + jint android_tool_type_0, + jint android_tool_type_1, + jint android_button_state) : cached_time_(FromAndroidTime(time_ms)), cached_action_(FromAndroidAction(android_action)), cached_pointer_count_(pointer_count), cached_history_size_(history_size), cached_action_index_(action_index), + cached_button_state_(FromAndroidButtonState(android_button_state)), pix_to_dip_(pix_to_dip), should_recycle_(false) { DCHECK_GT(pointer_count, 0); @@ -104,6 +140,8 @@ MotionEventAndroid::MotionEventAndroid(float pix_to_dip, cached_raw_position_offset_ = ToDips(gfx::PointF(raw_pos_x_pixels, raw_pos_y_pixels)) - cached_positions_[0]; + cached_tool_types_[0] = FromAndroidToolType(android_tool_type_0); + cached_tool_types_[1] = FromAndroidToolType(android_tool_type_1); } MotionEventAndroid::MotionEventAndroid(float pix_to_dip, @@ -115,6 +153,8 @@ MotionEventAndroid::MotionEventAndroid(float pix_to_dip, cached_pointer_count_(Java_MotionEvent_getPointerCount(env, event)), cached_history_size_(Java_MotionEvent_getHistorySize(env, event)), cached_action_index_(Java_MotionEvent_getActionIndex(env, event)), + cached_button_state_( + FromAndroidButtonState(Java_MotionEvent_getButtonState(env, event))), pix_to_dip_(pix_to_dip), should_recycle_(true) { event_.Reset(env, event); @@ -128,9 +168,12 @@ MotionEventAndroid::MotionEventAndroid(float pix_to_dip, cached_pointer_ids_[i] = Java_MotionEvent_getPointerId(env, event, i); cached_touch_majors_[i] = ToDips(Java_MotionEvent_getTouchMajorF_I(env, event, i)); + cached_tool_types_[i] = + FromAndroidToolType(Java_MotionEvent_getToolType(env, event, i)); } else { cached_pointer_ids_[i] = 0; cached_touch_majors_[i] = 0.f; + cached_tool_types_[i] = MotionEvent::TOOL_TYPE_UNKNOWN; } } @@ -148,6 +191,7 @@ MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid& other) cached_history_size_(other.cached_history_size_), cached_action_index_(other.cached_action_index_), cached_raw_position_offset_(other.cached_raw_position_offset_), + cached_button_state_(other.cached_button_state_), pix_to_dip_(other.pix_to_dip_), should_recycle_(true) { DCHECK(event_.obj()); @@ -155,6 +199,7 @@ MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid& other) cached_positions_[i] = other.cached_positions_[i]; cached_pointer_ids_[i] = other.cached_pointer_ids_[i]; cached_touch_majors_[i] = other.cached_touch_majors_[i]; + cached_tool_types_[i] = other.cached_tool_types_[i]; } } @@ -258,6 +303,19 @@ float MotionEventAndroid::GetHistoricalY(size_t pointer_index, AttachCurrentThread(), event_.obj(), pointer_index, historical_index)); } +ui::MotionEvent::ToolType MotionEventAndroid::GetToolType( + size_t pointer_index) const { + DCHECK_LT(pointer_index, cached_pointer_count_); + if (pointer_index < MAX_POINTERS_TO_CACHE) + return cached_tool_types_[pointer_index]; + return FromAndroidToolType(Java_MotionEvent_getToolType( + AttachCurrentThread(), event_.obj(), pointer_index)); +} + +int MotionEventAndroid::GetButtonState() const { + return cached_button_state_; +} + scoped_ptr MotionEventAndroid::Clone() const { return scoped_ptr(new MotionEventAndroid(*this)); } diff --git a/src/content/browser/renderer_host/input/motion_event_android.h b/src/content/browser/renderer_host/input/motion_event_android.h index 0362b04..aa3e082 100644 --- a/src/content/browser/renderer_host/input/motion_event_android.h +++ b/src/content/browser/renderer_host/input/motion_event_android.h @@ -39,7 +39,10 @@ class MotionEventAndroid : public ui::MotionEvent { jfloat touch_major_0_pixels, jfloat touch_major_1_pixels, jfloat raw_pos_x_pixels, - jfloat raw_pos_y_pixels); + jfloat raw_pos_y_pixels, + jint android_tool_type_0, + jint android_tool_type_1, + jint android_button_state); virtual ~MotionEventAndroid(); // ui::MotionEvent methods. @@ -64,6 +67,8 @@ class MotionEventAndroid : public ui::MotionEvent { size_t historical_index) const OVERRIDE; virtual float GetHistoricalY(size_t pointer_index, size_t historical_index) const OVERRIDE; + virtual ToolType GetToolType(size_t pointer_index) const OVERRIDE; + virtual int GetButtonState() const OVERRIDE; virtual scoped_ptr Clone() const OVERRIDE; virtual scoped_ptr Cancel() const OVERRIDE; @@ -110,6 +115,8 @@ class MotionEventAndroid : public ui::MotionEvent { int cached_pointer_ids_[MAX_POINTERS_TO_CACHE]; float cached_touch_majors_[MAX_POINTERS_TO_CACHE]; gfx::Vector2dF cached_raw_position_offset_; + ToolType cached_tool_types_[MAX_POINTERS_TO_CACHE]; + int cached_button_state_; // Used to convert pixel coordinates from the Java-backed MotionEvent to // DIP coordinates cached/returned by the MotionEventAndroid. diff --git a/src/content/browser/renderer_host/input/motion_event_web.cc b/src/content/browser/renderer_host/input/motion_event_web.cc index d1ff8a3..0d812b2 100644 --- a/src/content/browser/renderer_host/input/motion_event_web.cc +++ b/src/content/browser/renderer_host/input/motion_event_web.cc @@ -143,6 +143,17 @@ float MotionEventWeb::GetHistoricalY(size_t pointer_index, return 0.f; } +ui::MotionEvent::ToolType MotionEventWeb::GetToolType( + size_t pointer_index) const { + NOTIMPLEMENTED(); + return TOOL_TYPE_UNKNOWN; +} + +int MotionEventWeb::GetButtonState() const { + NOTIMPLEMENTED(); + return 0; +} + scoped_ptr MotionEventWeb::Clone() const { return scoped_ptr(new MotionEventWeb(event_)); } diff --git a/src/content/browser/renderer_host/input/motion_event_web.h b/src/content/browser/renderer_host/input/motion_event_web.h index f4ae258..06a2141 100644 --- a/src/content/browser/renderer_host/input/motion_event_web.h +++ b/src/content/browser/renderer_host/input/motion_event_web.h @@ -41,6 +41,8 @@ class MotionEventWeb : public ui::MotionEvent { virtual float GetHistoricalY( size_t pointer_index, size_t historical_index) const OVERRIDE; + virtual ToolType GetToolType(size_t pointer_index) const OVERRIDE; + virtual int GetButtonState() const OVERRIDE; virtual scoped_ptr Clone() const OVERRIDE; virtual scoped_ptr Cancel() const OVERRIDE; diff --git a/src/content/browser/renderer_host/render_widget_host_impl.cc b/src/content/browser/renderer_host/render_widget_host_impl.cc index d281bdf..eb638b0 100644 --- a/src/content/browser/renderer_host/render_widget_host_impl.cc +++ b/src/content/browser/renderer_host/render_widget_host_impl.cc @@ -1200,6 +1200,18 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status, // Reset some fields in preparation for recovering from a crash. ResetSizeAndRepaintPendingFlags(); current_size_.SetSize(0, 0); + // After the renderer crashes, the view is destroyed and so the + // RenderWidgetHost cannot track its visibility anymore. We assume such + // RenderWidgetHost to be visible for the sake of internal accounting - be + // careful about changing this - see http://crbug.com/401859. + // + // We need to at least make sure that the RenderProcessHost is notified about + // the |is_hidden_| change, so that the renderer will have correct visibility + // set when respawned. + if (!is_hidden_) { + process_->WidgetRestored(); + is_hidden_ = false; + } // Reset this to ensure the hung renderer mechanism is working properly. in_flight_event_count_ = 0; diff --git a/src/content/browser/renderer_host/render_widget_host_impl.h b/src/content/browser/renderer_host/render_widget_host_impl.h index e883502..6f249d4 100644 --- a/src/content/browser/renderer_host/render_widget_host_impl.h +++ b/src/content/browser/renderer_host/render_widget_host_impl.h @@ -717,7 +717,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl // Indicates whether a page is loading or not. bool is_loading_; - // Indicates whether a page is hidden or not. + // Indicates whether a page is hidden or not. It has to stay in sync with the + // most recent call to process_->WidgetRestored() / WidgetHidden(). bool is_hidden_; // Indicates whether a page is fullscreen or not. diff --git a/src/content/browser/renderer_host/render_widget_host_view_android.cc b/src/content/browser/renderer_host/render_widget_host_view_android.cc index f421735..ff24085 100644 --- a/src/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/src/content/browser/renderer_host/render_widget_host_view_android.cc @@ -40,6 +40,7 @@ #include "content/browser/renderer_host/dip_util.h" #include "content/browser/renderer_host/image_transport_factory_android.h" #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h" +#include "content/browser/renderer_host/input/web_input_event_builders_android.h" #include "content/browser/renderer_host/input/web_input_event_util.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" @@ -187,6 +188,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( switches::kDisableOverscrollEdgeEffect)), overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)), gesture_provider_(CreateGestureProviderConfig(), this), + gesture_text_selector_(this), flush_input_requested_(false), accelerated_surface_route_id_(0), using_synchronous_compositor_(SynchronousCompositorImpl::FromID( @@ -544,13 +546,11 @@ void RenderWidgetHostViewAndroid::OnStartContentIntent( } void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted( - const base::string16& result) { - // Custom serialization over IPC isn't allowed normally for security reasons. - // Since this feature is only used in (single-process) WebView, there are no - // security issues. Enforce that it's only called in single process mode. - CHECK(RenderProcessHost::run_renderer_in_process()); + const base::string16& text, + const base::string16& html, + const gfx::Rect rect) { if (content_view_core_) - content_view_core_->OnSmartClipDataExtracted(result); + content_view_core_->OnSmartClipDataExtracted(text, html, rect); } bool RenderWidgetHostViewAndroid::OnTouchEvent( @@ -561,6 +561,11 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent( if (!gesture_provider_.OnTouchEvent(event)) return false; + if (gesture_text_selector_.OnTouchEvent(event)) { + gesture_provider_.OnTouchEventAck(false); + return true; + } + // Short-circuit touch forwarding if no touch handlers exist. if (!host_->ShouldForwardTouchEvent()) { const bool event_consumed = false; @@ -1290,6 +1295,9 @@ void RenderWidgetHostViewAndroid::RunAckCallbacks() { void RenderWidgetHostViewAndroid::OnGestureEvent( const ui::GestureEventData& gesture) { + if (gesture_text_selector_.OnGestureEvent(gesture)) + return; + SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture)); } @@ -1437,6 +1445,31 @@ SkBitmap::Config RenderWidgetHostViewAndroid::PreferredReadbackFormat() { return SkBitmap::kARGB_8888_Config; } +void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() { + if (content_view_core_) + content_view_core_->ShowSelectionHandlesAutomatically(); +} + +void RenderWidgetHostViewAndroid::SelectRange( + float x1, float y1, float x2, float y2) { + if (content_view_core_) + static_cast(content_view_core_->GetWebContents())-> + SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2)); +} + +void RenderWidgetHostViewAndroid::Unselect() { + if (content_view_core_) + content_view_core_->GetWebContents()->Unselect(); +} + +void RenderWidgetHostViewAndroid::LongPress( + base::TimeTicks time, float x, float y) { + blink::WebGestureEvent long_press = WebGestureEventBuilder::Build( + blink::WebInputEvent::GestureLongPress, + (time - base::TimeTicks()).InSecondsF(), x, y); + SendGestureEvent(long_press); +} + // static void RenderWidgetHostViewBase::GetDefaultScreenInfo( blink::WebScreenInfo* results) { diff --git a/src/content/browser/renderer_host/render_widget_host_view_android.h b/src/content/browser/renderer_host/render_widget_host_view_android.h index 4707734..4d81add 100644 --- a/src/content/browser/renderer_host/render_widget_host_view_android.h +++ b/src/content/browser/renderer_host/render_widget_host_view_android.h @@ -20,6 +20,7 @@ #include "content/browser/renderer_host/delegated_frame_evictor.h" #include "content/browser/renderer_host/image_transport_factory_android.h" #include "content/browser/renderer_host/ime_adapter_android.h" +#include "content/browser/renderer_host/input/gesture_text_selector.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/common/content_export.h" #include "gpu/command_buffer/common/mailbox.h" @@ -65,7 +66,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid public ImageTransportFactoryAndroidObserver, public ui::GestureProviderClient, public ui::WindowAndroidObserver, - public DelegatedFrameEvictorClient { + public DelegatedFrameEvictorClient, + public GestureTextSelectorClient { public: RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget, ContentViewCoreImpl* content_view_core); @@ -186,6 +188,12 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE; + // GestureTextSelectorClient implementation. + virtual void ShowSelectionHandlesAutomatically() OVERRIDE; + virtual void SelectRange(float x1, float y1, float x2, float y2) OVERRIDE; + virtual void Unselect() OVERRIDE; + virtual void LongPress(base::TimeTicks time, float x, float y) OVERRIDE; + // Non-virtual methods void SetContentViewCore(ContentViewCoreImpl* content_view_core); SkColor GetCachedBackgroundColor() const; @@ -198,7 +206,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid void OnDidChangeBodyBackgroundColor(SkColor color); void OnStartContentIntent(const GURL& content_url); void OnSetNeedsBeginFrame(bool enabled); - void OnSmartClipDataExtracted(const base::string16& result); + void OnSmartClipDataExtracted(const base::string16& text, + const base::string16& html, + const gfx::Rect rect); bool OnTouchEvent(const ui::MotionEvent& event); void ResetGestureDetection(); @@ -334,6 +344,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid // Android MotionEvent's) and touch event acks. ui::FilteredGestureProvider gesture_provider_; + // Handles gesture based text selection + GestureTextSelector gesture_text_selector_; + bool flush_input_requested_; int accelerated_surface_route_id_; diff --git a/src/content/browser/web_contents/web_contents_android.cc b/src/content/browser/web_contents/web_contents_android.cc index fb8c0db..fbb5071 100644 --- a/src/content/browser/web_contents/web_contents_android.cc +++ b/src/content/browser/web_contents/web_contents_android.cc @@ -62,6 +62,12 @@ ScopedJavaLocalRef WebContentsAndroid::GetTitle( web_contents_->GetTitle()); } +ScopedJavaLocalRef WebContentsAndroid::GetVisibleURL( + JNIEnv* env, jobject obj) const { + return base::android::ConvertUTF8ToJavaString( + env, web_contents_->GetVisibleURL().spec()); +} + void WebContentsAndroid::Stop(JNIEnv* env, jobject obj) { web_contents_->Stop(); } diff --git a/src/content/browser/web_contents/web_contents_android.h b/src/content/browser/web_contents/web_contents_android.h index eec6127..eda0235 100644 --- a/src/content/browser/web_contents/web_contents_android.h +++ b/src/content/browser/web_contents/web_contents_android.h @@ -36,6 +36,8 @@ class CONTENT_EXPORT WebContentsAndroid // Methods called from Java base::android::ScopedJavaLocalRef GetTitle(JNIEnv* env, jobject obj) const; + base::android::ScopedJavaLocalRef GetVisibleURL(JNIEnv* env, + jobject obj) const; void Stop(JNIEnv* env, jobject obj); private: diff --git a/src/content/common/media/media_player_messages_android.h b/src/content/common/media/media_player_messages_android.h index 4548f0b..2908a2f 100644 --- a/src/content/common/media/media_player_messages_android.h +++ b/src/content/common/media/media_player_messages_android.h @@ -71,6 +71,7 @@ IPC_STRUCT_BEGIN(MediaPlayerHostMsg_Initialize_Params) IPC_STRUCT_MEMBER(GURL, url) IPC_STRUCT_MEMBER(GURL, first_party_for_cookies) IPC_STRUCT_MEMBER(GURL, frame_url) + IPC_STRUCT_MEMBER(bool, allow_credentials) IPC_STRUCT_END() // Chrome for Android seek message sequence is: diff --git a/src/content/common/view_messages.h b/src/content/common/view_messages.h index d12ba35..2a95e3f 100644 --- a/src/content/common/view_messages.h +++ b/src/content/common/view_messages.h @@ -1661,11 +1661,10 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_SetNeedsBeginFrame, bool /* enabled */) // Reply to the ViewMsg_ExtractSmartClipData message. -// TODO(juhui24.lee@samsung.com): this should be changed to a vector of structs -// instead of encoding the data as a string which is not allowed normally. Since -// ths is only used in Android WebView, it's allowed temporarily. -// http://crbug.com/330872 -IPC_MESSAGE_ROUTED1(ViewHostMsg_SmartClipDataExtracted, base::string16) +IPC_MESSAGE_ROUTED3(ViewHostMsg_SmartClipDataExtracted, + base::string16 /* text */, + base::string16 /* html */, + gfx::Rect /* rect */) #elif defined(OS_MACOSX) // Request that the browser load a font into shared memory for us. diff --git a/src/content/content_browser.gypi b/src/content/content_browser.gypi index 33f796f..00f8ce0 100644 --- a/src/content/content_browser.gypi +++ b/src/content/content_browser.gypi @@ -871,6 +871,8 @@ 'browser/renderer_host/ime_adapter_android.h', 'browser/renderer_host/input/gesture_event_queue.cc', 'browser/renderer_host/input/gesture_event_queue.h', + 'browser/renderer_host/input/gesture_text_selector.cc', + 'browser/renderer_host/input/gesture_text_selector.h', 'browser/renderer_host/input/input_ack_handler.h', 'browser/renderer_host/input/input_router.h', 'browser/renderer_host/input/input_router_client.h', diff --git a/src/content/content_renderer.gypi b/src/content/content_renderer.gypi index b2973f9..0ea623d 100644 --- a/src/content/content_renderer.gypi +++ b/src/content/content_renderer.gypi @@ -58,7 +58,6 @@ 'public/renderer/render_frame_observer.cc', 'public/renderer/render_frame_observer.h', 'public/renderer/render_frame_observer_tracker.h', - 'public/renderer/render_font_warmup_win.cc', 'public/renderer/render_font_warmup_win.h', 'public/renderer/render_process_observer.cc', 'public/renderer/render_process_observer.h', @@ -373,6 +372,7 @@ 'renderer/notification_provider.h', 'renderer/push_messaging_dispatcher.cc', 'renderer/push_messaging_dispatcher.h', + 'renderer/render_font_warmup_win.cc', 'renderer/render_frame_impl.cc', 'renderer/render_frame_impl.h', 'renderer/render_frame_proxy.cc', @@ -398,6 +398,8 @@ 'renderer/renderer_clipboard_client.h', 'renderer/renderer_date_time_picker.cc', 'renderer/renderer_date_time_picker.h', + 'renderer/renderer_font_platform_win.cc', + 'renderer/renderer_font_platform_win.h', 'renderer/renderer_main.cc', 'renderer/renderer_main_platform_delegate.h', 'renderer/renderer_main_platform_delegate_android.cc', diff --git a/src/content/content_tests.gypi b/src/content/content_tests.gypi index d17648d..bb754ae 100644 --- a/src/content/content_tests.gypi +++ b/src/content/content_tests.gypi @@ -532,6 +532,7 @@ 'browser/quota/usage_tracker_unittest.cc', 'browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc', 'browser/renderer_host/input/gesture_event_queue_unittest.cc', + 'browser/renderer_host/input/gesture_text_selector_unittest.cc', 'browser/renderer_host/input/input_router_impl_unittest.cc', 'browser/renderer_host/input/mock_input_ack_handler.cc', 'browser/renderer_host/input/mock_input_ack_handler.h', diff --git a/src/content/public/OWNERS b/src/content/public/OWNERS new file mode 100644 index 0000000..cac71c1 --- /dev/null +++ b/src/content/public/OWNERS @@ -0,0 +1,2 @@ +# DWrite specific changes +per-file render_font_warmup_win.h=scottmg@chromium.org diff --git a/src/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png b/src/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png index 7bdcefee6e4e9965401cf0bf2ea88b496b335a6b..8a5a98af49271eb27158f69f68767ca770f1942b 100644 GIT binary patch literal 2954 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 diff --git a/src/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png b/src/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png index 5258446ec7ca56357212584ca676d1b77c68b593..bc619f30f624c060a9c4a054ca62c5a799e37742 100644 GIT binary patch literal 2897 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 DSpK05 diff --git a/src/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png b/src/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png index 40604f10e15ac500ac85bbbed6eb15ec7a41cc89..8f4dcb8cf7d4a4e1ecf4ed3803424d4e0e5adda2 100644 GIT binary patch literal 3076 zcmV+f4EytmP)X+uL$Nkc;* zP;zf(X>4Tx07wm;mUmQB*%pV-y*Itk5+Wca^cs2zAksTX6$DXM^`x7XQc?|s+0 z08spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO_(THK{JlMynW#v{v-a*T zfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH1j_W4DKdsJG8Ul;qO2n0 z#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#itsL#`S=Q!g`M=rU9)45( zJ;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J<>9PP?;rs31pu_(obw)r zY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q7e9d`Nfk3?MdhZarb|T3 z%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|xfmo0(WD10T)!}~_HYW!e zew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^Xswa2bB{85{^$B13tWnB z;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^BfHQCd-XH*kfJhJnmIE$G z0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK<41h;K3WmW;Fah3yX$XSw z5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%HgQ}rJP(Ab`bQ-z{U4#0d z2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG;Yzp`J`T6S7vUT504#-H z!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0k#Xb$28W?xm>3qu8RLgp zjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT=5u1%I#8zOBU|X=4u>;s) z>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l?}87(bMRt(A-)QK9Dg3) zj~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N5P8I0VkxnX*g?EW941ba z6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|XrzUnLKcKTwn?CKOLf97RIe zPB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhvt&^*fYnAJldnHel*Ozyf zUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZVwz%!VuRu}#Ze`^l7W)9 z5>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP=)Lp_WhG@>R;lZ?BJkMlIuMhw8ApiF&yDYW2hFJ?fJhni{?u z85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$RAwc!i#egKuI;BS(LSWz zt39n_sIypSqfWEV6J3%nTQ@-4i zi$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^u!)^Xl1YupO;gy^-c(?^ z&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zii=7tT7GEswEK@D(EFW1Z zSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcHnq9En7Q0Tn&-M=XBKs!$ zF$X<|c!#|X_tWYh)GZit z(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z{kZ!p4@(b`M~lalr<3Oz z&kJ6Nm#vN_+kA5{dW4@^Vjg_`q%qU1ULk& z3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFjair&;wpi!{CU}&@N=Eg#~ zLQ&zpEzVmGY{hI9Z0+4-0xS$$Xe-OToc?Y*V;rTcf_ zb_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ=k7SRuGN`h>O0Q~1)u-yD z>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEidtwC+YVcg-Y!_VuY>bk#Y ze_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{;Ppd$6RYV^Go!iq1UMl% z@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2-|2wUogK~{EkB$8eDsX= znVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gcj=lwb=lWgyFW&aLedUh- zof`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*%^u_SYjF;2ng}*8Ow)d6M ztDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@e5TCq;UFc5u?5FfyXL`Mc# z_=RkY4D5VHVd~JS>SwSpA+>*yU+7Xk00bMKfVpcLRZZMTaec-{cakOhl5^g@cb2T^ z49M&&E>K`j(-H>f>`T@xz6e`|AB@dCKFk*Uih!Rb3)%(D;+vAVDK^aK2A&gQ%v3c6 zO-o*9YGsjp&G#`&=am)6+BAW`mQNK>1&(AO`w}`il7PeEcXt2T((JDTt+H1@69`lZ z-rJ}G-qZyOR0RSN>Aj6A;7whiKvf_Rk>1;=0^ZaG3Y5Ez3f(^2d20!^8Hv4?QNWx6 z*E8VuvmQKWpMc4nfvYKS`M87I%-2slU!a+c0;7j6JeRNg)?klJ0)t`r2goGw{@g|6 z@^#-D?2$PGZ<88GQ#K5~@ePL9A7JbPt^XhW0jWKeDWQm2Y620-c793~aMBXdsR~3S z+xe+~pg`Sw;LI+0Ct+s=s^ozl23Y0a?7=N7-1R{>q8A$6%96G*M#f5*8T&8$hddm* Szp+#R0000us`t$7pC*oQPKG(w>&DEJ42G$2$(t$iy+f^WqK^|?*! zTd5Dmp!k$LXc5Aqp+dn5QUy^=Vkq6+lHFwg-FwfS&s_%g1Bb)uGN&{Sd<@KY;PT@) z-*;!mt11A$d{#Og&-c0|XT9TNBFu^aSfBtFs`WWrwj530tIb;bn|rZd1^zmoaB*Dm zvvV)%7#nziU;RK9=4ZHk-yA0o4xm>;;iw0q9vDr5QmFd8%!eoIi8Okr2VT$hu# zZgb`0_vMkZFX{-u5Bq#~7wYJIG$pk_@290SCqSowvI}JaD4!TtdsxSl3q}(I z2k3g3?Zt4;;Pz*!xlVl+l;sVoico7Zk9?(J!(eGDO44d9-Oq+Gz=`mQqoN| zL^zbjp&Gx{HZ0kk8q>D^mjdr@XbeJ}Tdy$%G{chRVrYzJs%RL^>x3!18Eg0S(9EPL zYL;RE?Y4ZMXQ}zdYoVw@oV9&RX^pja#%cUiXuhRnEp7Mt zmav?NftjTg3_wz-d{_g^fvSIpoNO#n^bZ*f23BpZn2~%-XiZmaZyN|WffBg==a)J3 zsb@&Rl+`zWjt7bYgci4?1wPx78mIt;gT9C5t3N_<9QgP-irzsKWxDwetAF_gD~ms2 z=)eg$0L`$JUYE>R{dU~niNFEAfNlwc3YLHS9814{ZqG_kkO~GR^!wl)h-6v{HD|>< zOX<1@lpY4%2s$1?HHqwOT54z>`Ic;5)t=y%*5SyRAM%mYPgBkw0foutGRxPVXX)yXIW`AQKqFwCr8w1F zs{bEr`?41TtZu;ksi!#n=y?zrkJbT@a)$fQoTu7a<<9FbF+U5g$h1W5>At-yxdy1F zusMeNAAXW*vW@DLpcMd4JR*+aPVUCFmzbMIYtCg`N{!`Pvi0e1R1g%3xub+ILe<`{ zgH92t@WZ3=+X(~*PVz0OL0gTXExp3V2U84IlQw21;ca|L)8 zAqz2v97_iDp46CGD+F8#g+eGnr5-k15g2{fJ-|b(y}E5 zly%~8KEN9qI3<$%-jQ>9$cGBMA-oCn0r3n^yjqR_dCC_VmTE77O%`&2EH@1xhmOAr zEC4J1_%{|8mtS5uHxqbJm4g!S z_q3&gis6A(cjDZe4}9*Yzbm@4{{n6R?*LN|+yut1GrKYW_zN5G!t1~s&;f*db0{zd z?gBS~zX5*--j3_wfo-C62Mh^;5u-*U-JwIt(G7nFQlbJP z-6=ID&-dQvcixA4e;@9-=bn4c@5_xbGJw)ib5R2T06Lhi*5kid_urr-|I4PkSSSEM zt?sU=X#~^M)Y7jJ32^=TV+i`!#aM3t7Yg_~P7p zV9EP5+++<&a$`NWp#sjr1uQS!AL@HPSUyL;sS!6YXPUOaFEQ* za@~IH>7GQGQ|ouJ4kNJt%ylSQP(f3O96+r-E&m_{%)SatHNp0AN?(J9PtruCqwYzw z6;Ksc3oiH8d7YN6-EAGpz<^f@xZq=)ZL)c&R-=V1;iV!JsK6>i_@`^p8wzLK6Id2t z_3ZZKPc61$F;1wgS&BD1Ca|8rXruHhe`O(K+D7obUf=XRiVnH!5hf=25 z4ENQIL6^%ztjUGLy}PMBkCxsA>ElltXcMH^!|I-;Ym*4Wy))g=yEQz!yYQJcw~LOs zMcxn-B4qG2!SoQkgU?e(<-r%dcB&Qc4gK0n}y4A8KU zbIcp%Ws}_di&lgtZfD2KpCsQ?;_ik5AwT@ta7UEVS?0(d!A!Z7T@`r?#wz2iy;@pU z`cP|hl$IWYcOsrKUN3hlx&JfNBbJlj$$l8QVQRdQN)-{~)*AT$X`UqEL>&=2y%fqJ zFG9f?lIzLh_R8`Ug8(#dkqY^!z6K(;EgA1o54N|t)u8MA6Qy7OS-<3? zv5NIs(pMKWSv#dobn+7}6yq#fjPU9L-bkW&@t#^1DIoKB(`6)0 zCza3zx~qXcs;hkc`-1nrk_5c8D z_1nw$6yyA|IRuF3r1$*cBCA}s#75c_*_9gBE zfLNq$cM7H2ASLO9jyWawp_WFHxey7HfG1k87+9g5l|*06-5jrr_FW+*k1nv!;9%?L zT#kmLmK@CNXB_mTrZXHf%=FpU%|)tJ1E}Pgvg5^j&Fm8GEbB2J zNWa?eDD%({baMXUc^=ZlVI}P&R|{%nm_@aQZTHYEfe(Y)?kuqEhck5fA2_@bXr~V4 z3FTc(McNusgMh&Bm}+D4*X}m?2r!DD^g&#ZZq& zTVu{ZNv~P$mD(%KlE-xAK2zqE87;XMhBz&R9zqhDB7-@`EDzPBRG~f7wlTrNhN-id zK#Z+KzKE?rsNSE_t0tgvms*zzvZ&syKxe6;8xjfA&MHiEc;}Gi5aaOnmt3E*a9c7m zx$%Z!h1zEQ7vT~CE{(~OS6`YM9yQ$m=KM|SCRCxAFqyL1cfz-UJE3wGcD7u-y~?x7 zwTc~nOx`VJcP{govjmlbYDFa;%dR!!m+{}_>)dUw+eFhY?)cn!lO~wvl17r2SgCLN zY?@^{x6-@Pa7xMp>|yUQ=Rug3sEWsz;REyVxwf*`D_7B5^(`^4n=U=?6kvV^6AdZSgNNuY+|LrHT<+dAX@0u|%@n*8DpXoqF!aOXJx zH@i6X?5^^H*n$rGJo}<0$6J-?s);*A7DdYaijJRsV-Ho9Ey49Mxv*qd{LmwluTu+8 z>{{>*cv{ajH?VA#T_c6+2+}7#dgI^#J9!x z;G%FcbMJ<&`pcegy;+{tj);LMk7Y;fSn2%Qr65*+o0zKQ>Ne3mMyj~M<30`uLtyc_s)NX%n_RicNrcsprLUCsbwka zTzDFrcbK}T=%;m!$!8Ax9{Xh~_f=w4;#HX21KO()lIQkBATi)_{&@Ca{c@II2vP)9 zQ*BTegLFV<6e={*R5!?8f_l10x?02eB)`}SSxvD4HLf%RA|Fu6(OR=!`g2H#$yS4R zUNxBpg#-nH#2vJ?G<#ch69>NxLgV7u99IqaO{c>$^yk- z3Sr~pW(^h!@T)lcGXF4odFL1P@}7i@RXTR(o8PC^iV=Kml5H2<_YN;N-_1qF>lo(l zidFsE6Wiv%RnTloYcwHwz5nid{Gs)^^A#F|iTD^Xp@r$Sj&X$5!dPL;KtuIUKVN>d zJwmQjq$Z^niON(=RQ%%}(Qw`{sUd71TYuMD1|ou!?2#>!(rg)apWZWNE>xR9>)-Z= zyR>E`{L%ldixSEfeha6;dVE}Pg*xXC8;>%rovdW7_>9~fIvyf~$hpV`zI1I5_!D*2 zCAa5EUlTb~YxTX^Akez2W$AbOcA_`Gx9;4*h|Wm7GxwrT?821sd*k|cJ2&k9TE9lK zhVc?ke9V&GtIvzoYj@rSTjTK^BWN@6+hOEa>@P#%AIaN`aKzJ#`O(veU0lg&2_f)j z0A=8h`OTJN^GpZ0&D?nHPwSf1(WAnn#@44h?Pm6tzIF`miB5?P(&Zm9Vcj zEhJZB)*5arxN$f4+ranPjz#a#Ns@TdJ_;3H7M`}y!80Sz8g=hJ`yWfyJ^1ayt(Feg zP}@+gUEM=89vTTP8R$-YIjuZ3t5B|xD&HNS-2Y+Oci&G6N8f+?LZzi)s5>sb$*z8yF9Y?q_ z#Z$Y;Q zD{sy%MN`8jV^j=wD3*7u+TS|fNRp9b=>da(LeLa*{e>a}vmdV7*s}U)#jHx(r?qC~ zLhw+upPI3G8z`g}0YI4s5~2#%i3iVC#unr{zypKvh&-i;(XmxyK#{UgiUvfRraF{D@;H zr%%wljl|tlKowv5`--@SR_ifNxAjA2AAlX=Xv%Z^{{Rp2Gdjj>AIH(S4XtD=LL~TY zYs?9Tw1foVlcumYqSsB?`R$%)452BE=h1Z`Z*q^XxZg 1 ? event.getY(1) : 0, event.getPointerId(0), pointerCount > 1 ? event.getPointerId(1) : -1, event.getTouchMajor(), pointerCount > 1 ? event.getTouchMajor(1) : 0, - event.getRawX(), event.getRawY()); + event.getRawX(), event.getRawY(), + event.getToolType(0), + pointerCount > 1 ? event.getToolType(1) : MotionEvent.TOOL_TYPE_UNKNOWN, + event.getButtonState()); if (offset != null) offset.recycle(); return consumed; @@ -2421,6 +2490,12 @@ public class ContentViewCore @SuppressWarnings("unused") @CalledByNative + private void showSelectionHandlesAutomatically() { + getSelectionHandleController().allowAutomaticShowing(); + } + + @SuppressWarnings("unused") + @CalledByNative private void onSelectionBoundsChanged(Rect anchorRectDip, int anchorDir, Rect focusRectDip, int focusDir, boolean isAnchorFirst) { // All coordinates are in DIP. @@ -3024,14 +3099,30 @@ public class ContentViewCore public void extractSmartClipData(int x, int y, int width, int height) { if (mNativeContentViewCore != 0) { + x += mSmartClipOffsetX; + y += mSmartClipOffsetY; nativeExtractSmartClipData(mNativeContentViewCore, x, y, width, height); } } + /** + * Set offsets for smart clip. + * + *

This should be called if there is a viewport change introduced by, + * e.g., show and hide of a location bar. + * + * @param offsetX Offset for X position. + * @param offsetY Offset for Y position. + */ + public void setSmartClipOffsets(int offsetX, int offsetY) { + mSmartClipOffsetX = offsetX; + mSmartClipOffsetY = offsetY; + } + @CalledByNative - private void onSmartClipDataExtracted(String result) { + private void onSmartClipDataExtracted(String text, String html, Rect clipRect) { if (mSmartClipDataListener != null ) { - mSmartClipDataListener.onSmartClipDataExtracted(result); + mSmartClipDataListener.onSmartClipDataExtracted(text, html, clipRect); } } @@ -3138,7 +3229,8 @@ public class ContentViewCore float x0, float y0, float x1, float y1, int pointerId0, int pointerId1, float touchMajor0, float touchMajor1, - float rawX, float rawY); + float rawX, float rawY, + int androidToolType0, int androidToolType1, int androidButtonState); private native int nativeSendMouseMoveEvent( long nativeContentViewCoreImpl, long timeMs, float x, float y); diff --git a/src/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java b/src/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java index 63c829e..5b62432 100644 --- a/src/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java +++ b/src/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java @@ -9,6 +9,7 @@ import android.content.pm.PackageManager; import android.media.MediaMetadataRetriever; import android.net.ConnectivityManager; import android.net.NetworkInfo; +import android.os.ParcelFileDescriptor; import android.text.TextUtils; import android.util.Log; @@ -117,6 +118,23 @@ class MediaResourceGetter { context, url, cookies, userAgent); } + @CalledByNative + private static MediaMetadata extractMediaMetadataFromFd(int fd, + long offset, + long length) { + return new MediaResourceGetter().extract(fd, offset, length); + } + + @VisibleForTesting + MediaMetadata extract(int fd, long offset, long length) { + if (!androidDeviceOk(android.os.Build.MODEL, android.os.Build.VERSION.SDK_INT)) { + return EMPTY_METADATA; + } + + configure(fd, offset, length); + return doExtractMetadata(); + } + @VisibleForTesting MediaMetadata extract(final Context context, final String url, final String cookies, final String userAgent) { @@ -128,7 +146,10 @@ class MediaResourceGetter { Log.e(TAG, "Unable to configure metadata extractor"); return EMPTY_METADATA; } + return doExtractMetadata(); + } + private MediaMetadata doExtractMetadata() { try { String durationString = extractMetadata( MediaMetadataRetriever.METADATA_KEY_DURATION); @@ -367,6 +388,21 @@ class MediaResourceGetter { } @VisibleForTesting + void configure(int fd, long offset, long length) { + ParcelFileDescriptor parcelFd = ParcelFileDescriptor.adoptFd(fd); + try { + mRetriever.setDataSource(parcelFd.getFileDescriptor(), + offset, length); + } finally { + try { + parcelFd.close(); + } catch (IOException e) { + Log.e(TAG, "Failed to close file descriptor: " + e); + } + } + } + + @VisibleForTesting void configure(String url, Map headers) { mRetriever.setDataSource(url, headers); } diff --git a/src/content/public/android/java/src/org/chromium/content/browser/SmartClipProvider.java b/src/content/public/android/java/src/org/chromium/content/browser/SmartClipProvider.java new file mode 100644 index 0000000..346f217 --- /dev/null +++ b/src/content/public/android/java/src/org/chromium/content/browser/SmartClipProvider.java @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.browser; + +import android.os.Handler; + +/** + * An interface to provide smart clip data when requested. + * + * NOTE: Some platforms may call these functions to extract smart clip data. + * Please make sure implementation of them is somewhere in the view + * hierarchy. + */ +public interface SmartClipProvider { + /** + * Initiate extraction of text, HTML, and other information for clipping puposes (smart clip) + * from the rectangle area defined by starting positions (x and y), and width and height. + */ + void extractSmartClipData(int x, int y, int width, int height); + + /** + * Register a handler to handle smart clip data once extraction is done. + */ + void setSmartClipResultHandler(final Handler resultHandler); +} diff --git a/src/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/src/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java index 3da256e..c481b10 100644 --- a/src/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java +++ b/src/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java @@ -55,10 +55,16 @@ import org.chromium.content_public.browser.WebContents; } @Override + public String getVisibleUrl() { + return nativeGetVisibleURL(mNativeWebContentsAndroid); + } + + @Override public void stop() { nativeStop(mNativeWebContentsAndroid); } private native String nativeGetTitle(long nativeWebContentsAndroid); + private native String nativeGetVisibleURL(long nativeWebContentsAndroid); private native void nativeStop(long nativeWebContentsAndroid); } diff --git a/src/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/src/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java index c68ace6..5bd2dab 100644 --- a/src/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java +++ b/src/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java @@ -19,6 +19,11 @@ public interface WebContents { String getTitle(); /** + * @return The URL for the current visible page. + */ + String getVisibleUrl(); + + /** * Stop any pending navigation. */ void stop(); diff --git a/src/content/public/android/javatests/src/org/chromium/content/browser/MediaResourceGetterTest.java b/src/content/public/android/javatests/src/org/chromium/content/browser/MediaResourceGetterTest.java index 7eae2d6..a6adc96 100644 --- a/src/content/public/android/javatests/src/org/chromium/content/browser/MediaResourceGetterTest.java +++ b/src/content/public/android/javatests/src/org/chromium/content/browser/MediaResourceGetterTest.java @@ -27,7 +27,7 @@ import java.util.Map; @SuppressLint("SdCardPath") public class MediaResourceGetterTest extends InstrumentationTestCase { private static final String TEST_HTTP_URL = "http://example.com"; - private static final String TEST_USER_AGENT = // Anyhting, really + private static final String TEST_USER_AGENT = // Anything, really "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 " + "(KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36"; private static final String TEST_FILE_PATH = "/mnt/sdcard/test"; @@ -101,6 +101,9 @@ public class MediaResourceGetterTest extends InstrumentationTestCase { String mUri = null; Map mHeaders = null; String mPath = null; + int mFd; + long mOffset; + long mLength; // Write these before tests to configure functionality SparseArray mMetadata = null; @@ -111,6 +114,17 @@ public class MediaResourceGetterTest extends InstrumentationTestCase { // Can't use a real MediaMetadataRetriever as we have no media @Override + public void configure(int fd, long offset, long length) { + if (mThrowExceptionInConfigure) { + throw new RuntimeException("test exception"); + } + mFd = fd; + mOffset = offset; + mLength = length; + } + + // Can't use a real MediaMetadataRetriever as we have no media + @Override public void configure(String uri, Map headers) { if (mThrowExceptionInConfigure) { throw new RuntimeException("test exception"); @@ -505,6 +519,22 @@ public class MediaResourceGetterTest extends InstrumentationTestCase { } @SmallTest + public void testExtractFromFileDescriptor_ValidMetadata() { + mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1"); + mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO, "yes"); + mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH, "2"); + mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT, "3"); + final MediaMetadata expected = new MediaMetadata(1, 2, 3, true); + int fd = 1234; + long offset = 1000; + long length = 9000; + assertEquals(expected, mFakeMRG.extract(fd, offset, length)); + assertEquals(fd, mFakeMRG.mFd); + assertEquals(offset, mFakeMRG.mOffset); + assertEquals(length, mFakeMRG.mLength); + } + + @SmallTest public void testAndroidDeviceOk_BadModel_BadVersion() { assertFalse(MediaResourceGetter.androidDeviceOk( "GT-I9100", android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)); diff --git a/src/content/public/common/common_param_traits_macros.h b/src/content/public/common/common_param_traits_macros.h index 61d8b85..3de44ee 100644 --- a/src/content/public/common/common_param_traits_macros.h +++ b/src/content/public/common/common_param_traits_macros.h @@ -191,6 +191,7 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences) IPC_STRUCT_TRAITS_MEMBER(use_legacy_background_size_shorthand_behavior) IPC_STRUCT_TRAITS_MEMBER(wide_viewport_quirk) IPC_STRUCT_TRAITS_MEMBER(use_wide_viewport) + IPC_STRUCT_TRAITS_MEMBER(force_zero_layout_height) IPC_STRUCT_TRAITS_MEMBER(viewport_meta_layout_size_quirk) IPC_STRUCT_TRAITS_MEMBER(viewport_meta_merge_content_quirk) IPC_STRUCT_TRAITS_MEMBER(viewport_meta_non_user_scalable_quirk) diff --git a/src/content/renderer/OWNERS b/src/content/renderer/OWNERS index b3105d0..b9a7ad4 100644 --- a/src/content/renderer/OWNERS +++ b/src/content/renderer/OWNERS @@ -3,3 +3,9 @@ jamesr@chromium.org # Mac Sandbox profiles. per-file *.sb=set noparent per-file *.sb=jeremy@chromium.org + +# DirectWrite specific changes +per-file render_font_warmup_win.cc=scottmg@chromium.org +per-file renderer_font_platform_win.*=shrikant@chromium.org +per-file renderer_font_platform_win.*=scottmg@chromium.org +per-file renderer_font_platform_win.*=cpu@chromium.org diff --git a/src/content/renderer/media/android/media_info_loader.cc b/src/content/renderer/media/android/media_info_loader.cc index 8a49e04..caa66af 100644 --- a/src/content/renderer/media/android/media_info_loader.cc +++ b/src/content/renderer/media/android/media_info_loader.cc @@ -29,6 +29,7 @@ MediaInfoLoader::MediaInfoLoader( const ReadyCB& ready_cb) : loader_failed_(false), url_(url), + allow_stored_credentials_(false), cors_mode_(cors_mode), single_origin_(true), ready_cb_(ready_cb) {} @@ -41,6 +42,7 @@ void MediaInfoLoader::Start(blink::WebFrame* frame) { CHECK(frame); start_time_ = base::TimeTicks::Now(); + first_party_url_ = frame->document().firstPartyForCookies(); // Prepare the request. WebURLRequest request(url_); @@ -56,14 +58,17 @@ void MediaInfoLoader::Start(blink::WebFrame* frame) { options.allowCredentials = true; options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyAllow; + allow_stored_credentials_ = true; } else { options.exposeAllResponseHeaders = true; // The author header set is empty, no preflight should go ahead. options.preflightPolicy = WebURLLoaderOptions::PreventPreflight; options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; - if (cors_mode_ == blink::WebMediaPlayer::CORSModeUseCredentials) + if (cors_mode_ == blink::WebMediaPlayer::CORSModeUseCredentials) { options.allowCredentials = true; + allow_stored_credentials_ = true; + } } loader.reset(frame->createAssociatedURLLoader(options)); } @@ -92,6 +97,8 @@ void MediaInfoLoader::willSendRequest( single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin(); url_ = newRequest.url(); + first_party_url_ = newRequest.firstPartyForCookies(); + allow_stored_credentials_ = newRequest.allowStoredCredentials(); } void MediaInfoLoader::didSendData( @@ -187,7 +194,8 @@ void MediaInfoLoader::DidBecomeReady(Status status) { base::TimeTicks::Now() - start_time_); active_loader_.reset(); if (!ready_cb_.is_null()) - base::ResetAndReturn(&ready_cb_).Run(status); + base::ResetAndReturn(&ready_cb_).Run(status, url_, first_party_url_, + allow_stored_credentials_); } } // namespace content diff --git a/src/content/renderer/media/android/media_info_loader.h b/src/content/renderer/media/android/media_info_loader.h index d87b67c..caefc9d 100644 --- a/src/content/renderer/media/android/media_info_loader.h +++ b/src/content/renderer/media/android/media_info_loader.h @@ -14,6 +14,7 @@ #include "content/renderer/media/active_loader.h" #include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" +#include "third_party/WebKit/public/web/WebDocument.h" #include "url/gurl.h" namespace blink { @@ -44,11 +45,16 @@ class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient { kOk, }; + // Callback when MediaInfoLoader finishes loading the url. Args: whether URL + // is successfully loaded, the final URL destination following all the + // redirect, the first party URL for the final destination, and whether + // credentials needs to be sent to the final destination. + typedef base::Callback ReadyCB; + // Start loading information about the given media URL. // |url| - URL for the media resource to be loaded. // |cors_mode| - HTML media element's crossorigin attribute. // |ready_cb| - Called when media info has finished or failed loading. - typedef base::Callback ReadyCB; MediaInfoLoader( const GURL& url, blink::WebMediaPlayer::CORSMode cors_mode, @@ -66,10 +72,6 @@ class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient { // Only valid to call after the loader becomes ready. bool DidPassCORSAccessCheck() const; - void set_single_origin(bool single_origin) { - single_origin_ = single_origin; - } - private: friend class MediaInfoLoaderTest; @@ -115,6 +117,8 @@ class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient { bool loader_failed_; GURL url_; + GURL first_party_url_; + bool allow_stored_credentials_; blink::WebMediaPlayer::CORSMode cors_mode_; bool single_origin_; diff --git a/src/content/renderer/media/android/media_info_loader_unittest.cc b/src/content/renderer/media/android/media_info_loader_unittest.cc index ffde792..41a7b89 100644 --- a/src/content/renderer/media/android/media_info_loader_unittest.cc +++ b/src/content/renderer/media/android/media_info_loader_unittest.cc @@ -86,7 +86,7 @@ class MediaInfoLoaderTest : public testing::Test { void SendResponse( int http_status, MediaInfoLoader::Status expected_status) { - EXPECT_CALL(*this, ReadyCallback(expected_status)); + EXPECT_CALL(*this, ReadyCallback(expected_status, _, _, _)); EXPECT_CALL(*url_loader_, cancel()); WebURLResponse response(gurl_); @@ -98,11 +98,13 @@ class MediaInfoLoaderTest : public testing::Test { } void FailLoad() { - EXPECT_CALL(*this, ReadyCallback(MediaInfoLoader::kFailed)); + EXPECT_CALL(*this, ReadyCallback( + MediaInfoLoader::kFailed, _, _, _)); loader_->didFail(url_loader_, WebURLError()); } - MOCK_METHOD1(ReadyCallback, void(MediaInfoLoader::Status)); + MOCK_METHOD4(ReadyCallback, + void(MediaInfoLoader::Status, const GURL&, const GURL&, bool)); protected: GURL gurl_; diff --git a/src/content/renderer/media/android/renderer_media_player_manager.cc b/src/content/renderer/media/android/renderer_media_player_manager.cc index f3e0bc0..88af474 100644 --- a/src/content/renderer/media/android/renderer_media_player_manager.cc +++ b/src/content/renderer/media/android/renderer_media_player_manager.cc @@ -67,8 +67,8 @@ void RendererMediaPlayerManager::Initialize( const GURL& url, const GURL& first_party_for_cookies, int demuxer_client_id, - const GURL& frame_url) { - + const GURL& frame_url, + bool allow_credentials) { MediaPlayerHostMsg_Initialize_Params media_player_params; media_player_params.type = type; media_player_params.player_id = player_id; @@ -76,6 +76,7 @@ void RendererMediaPlayerManager::Initialize( media_player_params.url = url; media_player_params.first_party_for_cookies = first_party_for_cookies; media_player_params.frame_url = frame_url; + media_player_params.allow_credentials = allow_credentials; Send(new MediaPlayerHostMsg_Initialize(routing_id(), media_player_params)); } diff --git a/src/content/renderer/media/android/renderer_media_player_manager.h b/src/content/renderer/media/android/renderer_media_player_manager.h index 4bcb288..e8698c9 100644 --- a/src/content/renderer/media/android/renderer_media_player_manager.h +++ b/src/content/renderer/media/android/renderer_media_player_manager.h @@ -45,7 +45,8 @@ class RendererMediaPlayerManager : public RenderFrameObserver { const GURL& url, const GURL& first_party_for_cookies, int demuxer_client_id, - const GURL& frame_url); + const GURL& frame_url, + bool allow_credentials); // Starts the player. void Start(int player_id); diff --git a/src/content/renderer/media/android/webmediaplayer_android.cc b/src/content/renderer/media/android/webmediaplayer_android.cc index a7e9401..33b1fc0 100644 --- a/src/content/renderer/media/android/webmediaplayer_android.cc +++ b/src/content/renderer/media/android/webmediaplayer_android.cc @@ -7,6 +7,7 @@ #include #include +#include "base/android/build_info.h" #include "base/bind.h" #include "base/callback_helpers.h" #include "base/command_line.h" @@ -55,6 +56,7 @@ #include "ui/gfx/image/image.h" static const uint32 kGLTextureExternalOES = 0x8D65; +static const int kSDKVersionToSupportSecurityOriginCheck = 20; using blink::WebMediaPlayer; using blink::WebSize; @@ -109,12 +111,9 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid( texture_id_(0), stream_id_(0), is_playing_(false), - playing_started_(false), needs_establish_peer_(true), stream_texture_proxy_initialized_(false), has_size_info_(false), - has_media_metadata_(false), - has_media_info_(false), stream_texture_factory_(factory), needs_external_surface_(false), video_frame_provider_client_(NULL), @@ -124,6 +123,7 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid( is_remote_(false), media_log_(media_log), web_cdm_(NULL), + allow_stored_credentials_(false), weak_factory_(this) { DCHECK(player_manager_); DCHECK(cdm_manager_); @@ -191,13 +191,9 @@ void WebMediaPlayerAndroid::load(LoadType load_type, return; } - has_media_metadata_ = false; - has_media_info_ = false; - + url_ = url; int demuxer_client_id = 0; if (player_type_ != MEDIA_PLAYER_TYPE_URL) { - has_media_info_ = true; - RendererDemuxerAndroid* demuxer = RenderThreadImpl::current()->renderer_demuxer(); demuxer_client_id = demuxer->GetNextDemuxerClientID(); @@ -221,6 +217,8 @@ void WebMediaPlayerAndroid::load(LoadType load_type, weak_factory_.GetWeakPtr()), base::Bind(&WebMediaPlayerAndroid::OnDurationChanged, weak_factory_.GetWeakPtr())); + InitializePlayer(url_, frame_->document().firstPartyForCookies(), + true, demuxer_client_id); } } else { info_loader_.reset( @@ -229,28 +227,18 @@ void WebMediaPlayerAndroid::load(LoadType load_type, cors_mode, base::Bind(&WebMediaPlayerAndroid::DidLoadMediaInfo, weak_factory_.GetWeakPtr()))); - // TODO(qinmin): The url might be redirected when android media player - // requests the stream. As a result, we cannot guarantee there is only - // a single origin. Remove the following line when b/12573548 is fixed. - // Check http://crbug.com/334204. - info_loader_->set_single_origin(false); info_loader_->Start(frame_); } - - url_ = url; - GURL first_party_url = frame_->document().firstPartyForCookies(); - player_manager_->Initialize( - player_type_, player_id_, url, first_party_url, demuxer_client_id, - frame_->document().url()); - - if (player_manager_->ShouldEnterFullscreen(frame_)) - player_manager_->EnterFullscreen(player_id_, frame_); - + UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); UpdateReadyState(WebMediaPlayer::ReadyStateHaveNothing); } -void WebMediaPlayerAndroid::DidLoadMediaInfo(MediaInfoLoader::Status status) { +void WebMediaPlayerAndroid::DidLoadMediaInfo( + MediaInfoLoader::Status status, + const GURL& redirected_url, + const GURL& first_party_for_cookies, + bool allow_stored_credentials) { DCHECK(!media_source_delegate_); if (status == MediaInfoLoader::kFailed) { info_loader_.reset(); @@ -258,17 +246,10 @@ void WebMediaPlayerAndroid::DidLoadMediaInfo(MediaInfoLoader::Status status) { return; } - has_media_info_ = true; - if (has_media_metadata_ && - ready_state_ != WebMediaPlayer::ReadyStateHaveEnoughData) { - UpdateReadyState(WebMediaPlayer::ReadyStateHaveMetadata); - UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); - } - // Android doesn't start fetching resources until an implementation-defined - // event (e.g. playback request) occurs. Sets the network state to IDLE - // if play is not requested yet. - if (!playing_started_) - UpdateNetworkState(WebMediaPlayer::NetworkStateIdle); + InitializePlayer( + redirected_url, first_party_for_cookies, allow_stored_credentials, 0); + + UpdateNetworkState(WebMediaPlayer::NetworkStateIdle); } void WebMediaPlayerAndroid::play() { @@ -292,7 +273,6 @@ void WebMediaPlayerAndroid::play() { player_manager_->Start(player_id_); UpdatePlayingState(true); UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); - playing_started_ = true; } void WebMediaPlayerAndroid::pause() { @@ -545,12 +525,23 @@ bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( } bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const { - if (info_loader_) - return info_loader_->HasSingleOrigin(); - // The info loader may have failed. - if (player_type_ == MEDIA_PLAYER_TYPE_URL) + if (player_type_ != MEDIA_PLAYER_TYPE_URL) + return true; + + if (!info_loader_ || !info_loader_->HasSingleOrigin()) return false; - return true; + + // TODO(qinmin): The url might be redirected when android media player + // requests the stream. As a result, we cannot guarantee there is only + // a single origin. Only if the HTTP request was made without credentials, + // we will honor the return value from HasSingleSecurityOriginInternal() + // in pre-L android versions. + // Check http://crbug.com/334204. + if (!allow_stored_credentials_) + return true; + + return base::android::BuildInfo::GetInstance()->sdk_int() >= + kSDKVersionToSupportSecurityOriginCheck; } bool WebMediaPlayerAndroid::didPassCORSAccessCheck() const { @@ -614,9 +605,7 @@ void WebMediaPlayerAndroid::OnMediaMetadataChanged( } } - has_media_metadata_ = true; - if (has_media_info_ && - ready_state_ != WebMediaPlayer::ReadyStateHaveEnoughData) { + if (ready_state_ != WebMediaPlayer::ReadyStateHaveEnoughData) { UpdateReadyState(WebMediaPlayer::ReadyStateHaveMetadata); UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); } @@ -885,6 +874,19 @@ void WebMediaPlayerAndroid::OnDestruct() { "the RenderFrame goes away."; } +void WebMediaPlayerAndroid::InitializePlayer( + const GURL& url, + const GURL& first_party_for_cookies, + bool allow_stored_credentials, + int demuxer_client_id) { + allow_stored_credentials_ = allow_stored_credentials; + player_manager_->Initialize( + player_type_, player_id_, url, first_party_for_cookies, demuxer_client_id, + frame_->document().url(), allow_stored_credentials); + if (player_manager_->ShouldEnterFullscreen(frame_)) + player_manager_->EnterFullscreen(player_id_, frame_); +} + void WebMediaPlayerAndroid::Pause(bool is_media_related_action) { player_manager_->Pause(player_id_, is_media_related_action); UpdatePlayingState(false); diff --git a/src/content/renderer/media/android/webmediaplayer_android.h b/src/content/renderer/media/android/webmediaplayer_android.h index 67d09e0..f20d0ae 100644 --- a/src/content/renderer/media/android/webmediaplayer_android.h +++ b/src/content/renderer/media/android/webmediaplayer_android.h @@ -250,11 +250,18 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer, void SetNeedsEstablishPeer(bool needs_establish_peer); private: + void InitializePlayer(const GURL& url, + const GURL& first_party_for_cookies, + bool allowed_stored_credentials, + int demuxer_client_id); void Pause(bool is_media_related_action); void DrawRemotePlaybackText(const std::string& remote_playback_message); void ReallocateVideoFrame(); void SetCurrentFrameInternal(scoped_refptr& frame); - void DidLoadMediaInfo(MediaInfoLoader::Status status); + void DidLoadMediaInfo(MediaInfoLoader::Status status, + const GURL& redirected_url, + const GURL& first_party_for_cookies, + bool allow_stored_credentials); bool IsKeySystemSupported(const std::string& key_system); // Actually do the work for generateKeyRequest/addKey so they can easily @@ -358,9 +365,6 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer, // Whether the mediaplayer is playing. bool is_playing_; - // Whether the mediaplayer has already started playing. - bool playing_started_; - // Whether media player needs to re-establish the surface texture peer. bool needs_establish_peer_; @@ -370,10 +374,6 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer, // Whether the video size info is available. bool has_size_info_; - // Whether the video metadata and info are available. - bool has_media_metadata_; - bool has_media_info_; - // Object for allocating stream textures. scoped_refptr stream_texture_factory_; @@ -443,6 +443,9 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer, // player_manager_->SetCdm() directly. media::DecryptorReadyCB decryptor_ready_cb_; + // Whether stored credentials are allowed to be passed to the server. + bool allow_stored_credentials_; + // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory weak_factory_; diff --git a/src/content/renderer/render_font_warmup_win.cc b/src/content/renderer/render_font_warmup_win.cc new file mode 100644 index 0000000..90bbab2 --- /dev/null +++ b/src/content/renderer/render_font_warmup_win.cc @@ -0,0 +1,204 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/public/renderer/render_font_warmup_win.h" + +#include + +#include "base/debug/alias.h" +#include "base/logging.h" +#include "base/win/iat_patch_function.h" +#include "base/win/windows_version.h" +#include "content/renderer/renderer_font_platform_win.h" +#include "third_party/WebKit/public/web/win/WebFontRendering.h" +#include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/ports/SkFontMgr.h" +#include "third_party/skia/include/ports/SkTypeface_win.h" + +namespace content { + +namespace { + +SkFontMgr* g_warmup_fontmgr = NULL; + +base::win::IATPatchFunction g_iat_patch_open_sc_manager; +base::win::IATPatchFunction g_iat_patch_close_service_handle; +base::win::IATPatchFunction g_iat_patch_open_service; +base::win::IATPatchFunction g_iat_patch_start_service; +base::win::IATPatchFunction g_iat_patch_nt_connect_port; + +// These are from ntddk.h +#if !defined(STATUS_ACCESS_DENIED) +#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) +#endif + +typedef LONG NTSTATUS; + +SC_HANDLE WINAPI OpenSCManagerWPatch(const wchar_t* machine_name, + const wchar_t* database_name, + DWORD access_mask) { + ::SetLastError(0); + return reinterpret_cast(0xdeadbeef); +} + +SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager, + const wchar_t* service_name, + DWORD access_mask) { + ::SetLastError(0); + return reinterpret_cast(0xdeadbabe); +} + +BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) { + if (service_handle != reinterpret_cast(0xdeadbabe) && + service_handle != reinterpret_cast(0xdeadbeef)) + CHECK(false); + ::SetLastError(0); + return TRUE; +} + +BOOL WINAPI StartServiceWPatch(SC_HANDLE service, + DWORD args, + const wchar_t** arg_vectors) { + if (service != reinterpret_cast(0xdeadbabe)) + CHECK(false); + ::SetLastError(ERROR_ACCESS_DENIED); + return FALSE; +} + +NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle, + void* port_name, + void* object_attribs, + void* port_attribs, + DWORD flags, + void* server_sid, + void* message, + DWORD* buffer_length, + void* out_message_attributes, + void* in_message_attributes, + void* time_out) { + return STATUS_ACCESS_DENIED; +} + +// Directwrite connects to the font cache service to retrieve information about +// fonts installed on the system etc. This works well outside the sandbox and +// within the sandbox as long as the lpc connection maintained by the current +// process with the font cache service remains valid. It appears that there +// are cases when this connection is dropped after which directwrite is unable +// to connect to the font cache service which causes problems with characters +// disappearing. +// Directwrite has fallback code to enumerate fonts if it is unable to connect +// to the font cache service. We need to intercept the following APIs to +// ensure that it does not connect to the font cache service. +// NtALpcConnectPort +// OpenSCManagerW +// OpenServiceW +// StartServiceW +// CloseServiceHandle. +// These are all IAT patched. +void PatchServiceManagerCalls() { + static bool is_patched = false; + if (is_patched) + return; + const char* service_provider_dll = + (base::win::GetVersion() >= base::win::VERSION_WIN8 ? + "api-ms-win-service-management-l1-1-0.dll" : "advapi32.dll"); + + is_patched = true; + + DWORD patched = g_iat_patch_open_sc_manager.Patch(L"dwrite.dll", + service_provider_dll, "OpenSCManagerW", OpenSCManagerWPatch); + DCHECK(patched == 0); + + patched = g_iat_patch_close_service_handle.Patch(L"dwrite.dll", + service_provider_dll, "CloseServiceHandle", CloseServiceHandlePatch); + DCHECK(patched == 0); + + patched = g_iat_patch_open_service.Patch(L"dwrite.dll", + service_provider_dll, "OpenServiceW", OpenServiceWPatch); + DCHECK(patched == 0); + + patched = g_iat_patch_start_service.Patch(L"dwrite.dll", + service_provider_dll, "StartServiceW", StartServiceWPatch); + DCHECK(patched == 0); + + patched = g_iat_patch_nt_connect_port.Patch(L"dwrite.dll", + "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch); + DCHECK(patched == 0); +} + +// Windows-only DirectWrite support. These warm up the DirectWrite paths +// before sandbox lock down to allow Skia access to the Font Manager service. +void CreateDirectWriteFactory(IDWriteFactory** factory) { + typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; + HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll"); + // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. + if (!dwrite_dll) { + DWORD load_library_get_last_error = GetLastError(); + base::debug::Alias(&dwrite_dll); + base::debug::Alias(&load_library_get_last_error); + CHECK(false); + } + + PatchServiceManagerCalls(); + + DWriteCreateFactoryProc dwrite_create_factory_proc = + reinterpret_cast( + GetProcAddress(dwrite_dll, "DWriteCreateFactory")); + // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. + if (!dwrite_create_factory_proc) { + DWORD get_proc_address_get_last_error = GetLastError(); + base::debug::Alias(&dwrite_create_factory_proc); + base::debug::Alias(&get_proc_address_get_last_error); + CHECK(false); + } + CHECK(SUCCEEDED( + dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_ISOLATED, + __uuidof(IDWriteFactory), + reinterpret_cast(factory)))); +} + +HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory, + IDWriteFontCollection** col, + BOOL checkUpdates) { + // We always return pre-created font collection from here. + IDWriteFontCollection* custom_collection = GetCustomFontCollection(factory); + DCHECK(custom_collection != NULL); + *col = custom_collection; + return S_OK; +} + +void PatchDWriteFactory(IDWriteFactory* factory) { + const unsigned int kGetSystemFontCollectionVTableIndex = 3; + + PROC* vtable = *reinterpret_cast(factory); + PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex]; + void* stub_function = &StubFontCollection; + base::win::ModifyCode(function_ptr, &stub_function, sizeof(PROC)); +} + +} // namespace + +void DoPreSandboxWarmupForTypeface(SkTypeface* typeface) { + SkPaint paint_warmup; + paint_warmup.setTypeface(typeface); + wchar_t glyph = L'S'; + paint_warmup.measureText(&glyph, 2); +} + +SkFontMgr* GetPreSandboxWarmupFontMgr() { + if (!g_warmup_fontmgr) { + IDWriteFactory* factory; + CreateDirectWriteFactory(&factory); + + IDWriteFontCollection* collection = GetCustomFontCollection(factory); + + PatchDWriteFactory(factory); + + blink::WebFontRendering::setDirectWriteFactory(factory); + g_warmup_fontmgr = SkFontMgr_New_DirectWrite(factory); + } + return g_warmup_fontmgr; +} + +} // namespace content diff --git a/src/content/renderer/render_view_impl_android.cc b/src/content/renderer/render_view_impl_android.cc index 679da54..57d1920 100644 --- a/src/content/renderer/render_view_impl_android.cc +++ b/src/content/renderer/render_view_impl_android.cc @@ -65,8 +65,12 @@ void RenderViewImpl::didScrollWithKeyboard(const blink::WebSize& delta) { } void RenderViewImpl::OnExtractSmartClipData(const gfx::Rect& rect) { + blink::WebString clip_text; + blink::WebString clip_html; + blink::WebRect clip_rect; + webview()->extractSmartClipData(rect, clip_text, clip_html, clip_rect); Send(new ViewHostMsg_SmartClipDataExtracted( - routing_id_, webview()->getSmartClipData(rect))); + routing_id_, clip_text, clip_html, clip_rect)); } } // namespace content diff --git a/src/content/renderer/renderer_font_platform_win.cc b/src/content/renderer/renderer_font_platform_win.cc new file mode 100644 index 0000000..2087046 --- /dev/null +++ b/src/content/renderer/renderer_font_platform_win.cc @@ -0,0 +1,305 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/renderer_font_platform_win.h" + +#include +#include +#include +#include +#include + +#include "base/debug/alias.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_path.h" +#include "base/files/memory_mapped_file.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/path_service.h" +#include "base/time/time.h" +#include "base/win/iat_patch_function.h" +#include "base/win/registry.h" +#include "base/win/scoped_comptr.h" + +namespace { + +namespace mswr = Microsoft::WRL; +namespace mswrw = Microsoft::WRL::Wrappers; + +class FontCollectionLoader + : public mswr::RuntimeClass, + IDWriteFontCollectionLoader> { + public: + // IDWriteFontCollectionLoader methods. + virtual HRESULT STDMETHODCALLTYPE + CreateEnumeratorFromKey(IDWriteFactory* factory, + void const* key, + UINT32 key_size, + IDWriteFontFileEnumerator** file_enumerator); + + static HRESULT Initialize(IDWriteFactory* factory); + + UINT32 GetFontMapSize(); + + std::wstring GetFontNameFromKey(UINT32 idx); + + bool LoadFontListFromRegistry(); + + FontCollectionLoader() {}; + virtual ~FontCollectionLoader() {}; + + private: + mswr::ComPtr file_loader_; + + std::vector reg_fonts_; +}; + +mswr::ComPtr g_font_loader; + +class FontFileStream + : public mswr::RuntimeClass, + IDWriteFontFileStream> { + public: + // IDWriteFontFileStream methods. + virtual HRESULT STDMETHODCALLTYPE + ReadFileFragment(void const** fragment_start, + UINT64 file_offset, + UINT64 fragment_size, + void** context) { + if (!memory_.get() || !memory_->IsValid()) + return E_FAIL; + + *fragment_start = static_cast(memory_->data()) + + static_cast(file_offset); + *context = NULL; + return S_OK; + } + + virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* context) {} + + virtual HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* file_size) { + if (!memory_.get() || !memory_->IsValid()) + return E_FAIL; + + *file_size = memory_->length(); + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* last_write_time) { + if (!memory_.get() || !memory_->IsValid()) + return E_FAIL; + + // According to MSDN article http://goo.gl/rrSYzi the "last modified time" + // is used by DirectWrite font selection algorithms to determine whether + // one font resource is more up to date than another one. + // So by returning 0 we are assuming that it will treat all fonts to be + // equally up to date. + // TODO(shrikant): We should further investigate this. + *last_write_time = 0; + return S_OK; + } + + FontFileStream::FontFileStream() : font_key_(0) { + }; + + HRESULT RuntimeClassInitialize(UINT32 font_key) { + base::FilePath path; + PathService::Get(base::DIR_WINDOWS_FONTS, &path); + path = path.Append(g_font_loader->GetFontNameFromKey(font_key).c_str()); + memory_.reset(new base::MemoryMappedFile()); + + // Put some debug information on stack. + WCHAR font_name[256]; + path.value().copy(font_name, arraysize(font_name)); + base::debug::Alias(font_name); + + if (!memory_->Initialize(path)) { + memory_.reset(); + return E_FAIL; + } + + font_key_ = font_key; + return S_OK; + } + + virtual ~FontFileStream() {} + + UINT32 font_key_; + scoped_ptr memory_; +}; + +class FontFileLoader + : public mswr::RuntimeClass, + IDWriteFontFileLoader> { + public: + // IDWriteFontFileLoader methods. + virtual HRESULT STDMETHODCALLTYPE + CreateStreamFromKey(void const* ref_key, + UINT32 ref_key_size, + IDWriteFontFileStream** stream) { + if (ref_key_size != sizeof(UINT32)) + return E_FAIL; + + UINT32 font_key = *static_cast(ref_key); + mswr::ComPtr font_stream; + HRESULT hr = mswr::MakeAndInitialize(&font_stream, + font_key); + if (SUCCEEDED(hr)) { + *stream = font_stream.Detach(); + return S_OK; + } + return E_FAIL; + } + + FontFileLoader() {} + virtual ~FontFileLoader() {} +}; + +class FontFileEnumerator + : public mswr::RuntimeClass, + IDWriteFontFileEnumerator> { + public: + // IDWriteFontFileEnumerator methods. + virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* has_current_file) { + *has_current_file = FALSE; + + if (current_file_) + current_file_.ReleaseAndGetAddressOf(); + + if (font_idx_ < g_font_loader->GetFontMapSize()) { + HRESULT hr = + factory_->CreateCustomFontFileReference(&font_idx_, + sizeof(UINT32), + file_loader_.Get(), + current_file_.GetAddressOf()); + DCHECK(SUCCEEDED(hr)); + *has_current_file = TRUE; + font_idx_++; + } + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE + GetCurrentFontFile(IDWriteFontFile** font_file) { + if (!current_file_) { + *font_file = NULL; + return E_FAIL; + } + + *font_file = current_file_.Detach(); + return S_OK; + } + + FontFileEnumerator(const void* keys, + UINT32 buffer_size, + IDWriteFactory* factory, + IDWriteFontFileLoader* file_loader) + : factory_(factory), file_loader_(file_loader), font_idx_(0) {} + + virtual ~FontFileEnumerator() {} + + mswr::ComPtr factory_; + mswr::ComPtr current_file_; + mswr::ComPtr file_loader_; + UINT32 font_idx_; +}; + +// IDWriteFontCollectionLoader methods. +HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey( + IDWriteFactory* factory, + void const* key, + UINT32 key_size, + IDWriteFontFileEnumerator** file_enumerator) { + *file_enumerator = mswr::Make( + key, key_size, factory, file_loader_.Get()).Detach(); + return S_OK; +} + +// static +HRESULT FontCollectionLoader::Initialize(IDWriteFactory* factory) { + DCHECK(g_font_loader == NULL); + + g_font_loader = mswr::Make(); + if (!g_font_loader) { + DCHECK(FALSE); + return E_FAIL; + } + + CHECK(g_font_loader->LoadFontListFromRegistry()); + + g_font_loader->file_loader_ = mswr::Make().Detach(); + + factory->RegisterFontFileLoader(g_font_loader->file_loader_.Get()); + factory->RegisterFontCollectionLoader(g_font_loader.Get()); + + return S_OK; +} + +UINT32 FontCollectionLoader::GetFontMapSize() { + return reg_fonts_.size(); +} + +std::wstring FontCollectionLoader::GetFontNameFromKey(UINT32 idx) { + DCHECK(idx < reg_fonts_.size()); + return reg_fonts_[idx]; +} + +bool FontCollectionLoader::LoadFontListFromRegistry() { + const wchar_t kFontsRegistry[] = + L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"; + CHECK(reg_fonts_.empty()); + base::win::RegKey regkey; + if (regkey.Open(HKEY_LOCAL_MACHINE, kFontsRegistry, KEY_READ) != + ERROR_SUCCESS) { + return false; + } + + std::wstring name; + std::wstring value; + for (DWORD idx = 0; idx < regkey.GetValueCount(); idx++) { + if (regkey.GetValueNameAt(idx, &name) == ERROR_SUCCESS && + regkey.ReadValue(name.c_str(), &value) == ERROR_SUCCESS) { + base::FilePath path(value.c_str()); + // We need to check if file name is the only component that exists, + // we will ignore all other registry entries. + std::vector components; + path.GetComponents(&components); + if (components.size() == 1) { + reg_fonts_.push_back(value.c_str()); + } + } + } + return true; +} + +} // namespace + +namespace content { + +mswr::ComPtr g_font_collection; + +IDWriteFontCollection* GetCustomFontCollection(IDWriteFactory* factory) { + if (g_font_collection.Get() != NULL) + return g_font_collection.Get(); + + base::TimeTicks start_tick = base::TimeTicks::Now(); + + FontCollectionLoader::Initialize(factory); + + HRESULT hr = factory->CreateCustomFontCollection( + g_font_loader.Get(), NULL, 0, g_font_collection.GetAddressOf()); + + base::TimeDelta time_delta = base::TimeTicks::Now() - start_tick; + int64 delta = time_delta.ToInternalValue(); + base::debug::Alias(&delta); + UINT32 size = g_font_loader->GetFontMapSize(); + base::debug::Alias(&size); + + CHECK(SUCCEEDED(hr)); + CHECK(g_font_collection.Get() != NULL); + + return g_font_collection.Get(); +} + +} // namespace content diff --git a/src/content/renderer/renderer_font_platform_win.h b/src/content/renderer/renderer_font_platform_win.h new file mode 100644 index 0000000..a04901b --- /dev/null +++ b/src/content/renderer/renderer_font_platform_win.h @@ -0,0 +1,17 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_RENDERER_FONT_PLATFORM_WIN_H_ +#define CHROME_RENDERER_RENDERER_FONT_PLATFORM_WIN_H_ + +struct IDWriteFactory; +struct IDWriteFontCollection; + +namespace content { + +IDWriteFontCollection* GetCustomFontCollection(IDWriteFactory* factory); + +} // namespace content + +#endif // CHROME_RENDERER_RENDERER_FONT_PLATFORM_WIN_H_ diff --git a/src/content/shell/android/shell_apk/AndroidManifest.xml b/src/content/shell/android/shell_apk/AndroidManifest.xml index 3cd5a12..83f50e8 100644 --- a/src/content/shell/android/shell_apk/AndroidManifest.xml +++ b/src/content/shell/android/shell_apk/AndroidManifest.xml @@ -95,6 +95,8 @@ android:permission="org.chromium.content_shell.permission.SANDBOX" android:isolatedProcess="true" android:exported="false" /> + diff --git a/src/google_apis/gcm/engine/gcm_store_impl.cc b/src/google_apis/gcm/engine/gcm_store_impl.cc index e27e82e..6f128f5 100644 --- a/src/google_apis/gcm/engine/gcm_store_impl.cc +++ b/src/google_apis/gcm/engine/gcm_store_impl.cc @@ -339,7 +339,8 @@ void GCMStoreImpl::Backend::RemoveRegistration(const std::string& app_id, leveldb::WriteOptions write_options; write_options.sync = true; - leveldb::Status status = db_->Delete(write_options, MakeSlice(app_id)); + leveldb::Status status = + db_->Delete(write_options, MakeSlice(MakeRegistrationKey(app_id))); if (status.ok()) { foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); return; diff --git a/src/google_apis/gcm/engine/gcm_store_impl_unittest.cc b/src/google_apis/gcm/engine/gcm_store_impl_unittest.cc index 7b9c893..8db28cc 100644 --- a/src/google_apis/gcm/engine/gcm_store_impl_unittest.cc +++ b/src/google_apis/gcm/engine/gcm_store_impl_unittest.cc @@ -261,6 +261,25 @@ TEST_F(GCMStoreImplTest, Registrations) { load_result->registrations["app2"]->sender_ids[0]); EXPECT_EQ(registration2->sender_ids[1], load_result->registrations["app2"]->sender_ids[1]); + + gcm_store->RemoveRegistration( + "app2", + base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this))); + PumpLoop(); + + gcm_store = BuildGCMStore().Pass(); + gcm_store->Load(base::Bind( + &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result)); + PumpLoop(); + + ASSERT_EQ(1u, load_result->registrations.size()); + ASSERT_TRUE(load_result->registrations.find("app1") != + load_result->registrations.end()); + EXPECT_EQ(registration1->registration_id, + load_result->registrations["app1"]->registration_id); + ASSERT_EQ(1u, load_result->registrations["app1"]->sender_ids.size()); + EXPECT_EQ(registration1->sender_ids[0], + load_result->registrations["app1"]->sender_ids[0]); } // Verify saving some incoming messages, reopening the directory, and then diff --git a/src/gpu/command_buffer/service/gles2_cmd_decoder.cc b/src/gpu/command_buffer/service/gles2_cmd_decoder.cc index 02ac2f6..5a829e9 100644 --- a/src/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/src/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -5020,7 +5020,8 @@ void GLES2DecoderImpl::ClearUnclearedAttachments( 1.0f); state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); clear_bits |= GL_COLOR_BUFFER_BIT; - framebuffer->PrepareDrawBuffersForClear(); + if (feature_info_->feature_flags().ext_draw_buffers) + framebuffer->PrepareDrawBuffersForClear(); } if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) || @@ -5041,7 +5042,8 @@ void GLES2DecoderImpl::ClearUnclearedAttachments( state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); glClear(clear_bits); - if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0) + if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0 && + feature_info_->feature_flags().ext_draw_buffers) framebuffer->RestoreDrawBuffersAfterClear(); framebuffer_manager()->MarkAttachmentsAsCleared( diff --git a/src/gpu/config/gpu_driver_bug_list_json.cc b/src/gpu/config/gpu_driver_bug_list_json.cc index bcd2dd4..991f2b5 100644 --- a/src/gpu/config/gpu_driver_bug_list_json.cc +++ b/src/gpu/config/gpu_driver_bug_list_json.cc @@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "6.7", + "version": "6.10", "entries": [ { "id": 1, @@ -1094,6 +1094,22 @@ LONG_STRING_CONST( "features": [ "disable_d3d11" ] + }, + { + "id": 87, + "description": "Disable use of Direct3D 11 on older AMD drivers", + "cr_bugs": [402134], + "os": { + "type": "win" + }, + "vendor_id": "0x1002", + "driver_date": { + "op": "<", + "value": "2011.1" + }, + "features": [ + "disable_d3d11" + ] } ] } diff --git a/src/media/audio/pulse/pulse_output.cc b/src/media/audio/pulse/pulse_output.cc index 19fc47b..e0a0b42 100644 --- a/src/media/audio/pulse/pulse_output.cc +++ b/src/media/audio/pulse/pulse_output.cc @@ -124,26 +124,31 @@ void PulseAudioOutputStream::FulfillWriteRequest(size_t requested_bytes) { CHECK_GE(pa_stream_begin_write(pa_stream_, &buffer, &bytes_to_fill), 0); CHECK_EQ(bytes_to_fill, static_cast(params_.GetBytesPerBuffer())); + // NOTE: |bytes_to_fill| may be larger than |requested_bytes| now, this is + // okay since pa_stream_begin_write() is the authoritative source on how + // much can be written. + int frames_filled = 0; if (source_callback_) { - uint32 hardware_delay = pulse::GetHardwareLatencyInBytes( - pa_stream_, params_.sample_rate(), - params_.GetBytesPerFrame()); + const uint32 hardware_delay = pulse::GetHardwareLatencyInBytes( + pa_stream_, params_.sample_rate(), params_.GetBytesPerFrame()); frames_filled = source_callback_->OnMoreData( audio_bus_.get(), AudioBuffersState(0, hardware_delay)); - } - // Zero any unfilled data so it plays back as silence. - if (frames_filled < audio_bus_->frames()) { - audio_bus_->ZeroFramesPartial( - frames_filled, audio_bus_->frames() - frames_filled); - } + // Zero any unfilled data so it plays back as silence. + if (frames_filled < audio_bus_->frames()) { + audio_bus_->ZeroFramesPartial( + frames_filled, audio_bus_->frames() - frames_filled); + } - // Note: If this ever changes to output raw float the data must be clipped - // and sanitized since it may come from an untrusted source such as NaCl. - audio_bus_->Scale(volume_); - audio_bus_->ToInterleaved( - audio_bus_->frames(), params_.bits_per_sample() / 8, buffer); + // Note: If this ever changes to output raw float the data must be clipped + // and sanitized since it may come from an untrusted source such as NaCl. + audio_bus_->Scale(volume_); + audio_bus_->ToInterleaved( + audio_bus_->frames(), params_.bits_per_sample() / 8, buffer); + } else { + memset(buffer, 0, bytes_to_fill); + } if (pa_stream_write(pa_stream_, buffer, bytes_to_fill, NULL, 0LL, PA_SEEK_RELATIVE) < 0) { @@ -152,7 +157,23 @@ void PulseAudioOutputStream::FulfillWriteRequest(size_t requested_bytes) { } } + // NOTE: As mentioned above, |bytes_remaining| may be negative after this. bytes_remaining -= bytes_to_fill; + + // Despite telling Pulse to only request certain buffer sizes, it will not + // always obey. In these cases we need to avoid back to back reads from + // the renderer as it won't have time to complete the request. + // + // We can't defer the callback as Pulse will never call us again until we've + // satisfied writing the requested number of bytes. + // + // TODO(dalecurtis): It might be worth choosing the sleep duration based on + // the hardware latency return above. Watch http://crbug.com/366433 to see + // if a more complicated wait process is necessary. We may also need to see + // if a PostDelayedTask should be used here to avoid blocking the PulseAudio + // command thread. + if (source_callback_ && bytes_remaining > 0) + base::PlatformThread::Sleep(params_.GetBufferDuration() / 4); } } diff --git a/src/media/audio/pulse/pulse_util.cc b/src/media/audio/pulse/pulse_util.cc index 1539793..357352a 100644 --- a/src/media/audio/pulse/pulse_util.cc +++ b/src/media/audio/pulse/pulse_util.cc @@ -283,9 +283,13 @@ bool CreateOutputStream(pa_threaded_mainloop** mainloop, // |minreq| bytes. |tlength| should be a multiple of |minreq|; too low and // Pulse will issue callbacks way too fast, too high and we don't get // callbacks frequently enough. + // + // Setting |minreq| to the exact buffer size leads to more callbacks than + // necessary, so we've clipped it to half the buffer size. Regardless of the + // requested amount, we'll always fill |params.GetBytesPerBuffer()| though. pa_buffer_attr pa_buffer_attributes; pa_buffer_attributes.maxlength = static_cast(-1); - pa_buffer_attributes.minreq = params.GetBytesPerBuffer(); + pa_buffer_attributes.minreq = params.GetBytesPerBuffer() / 2; pa_buffer_attributes.prebuf = static_cast(-1); pa_buffer_attributes.tlength = params.GetBytesPerBuffer() * 3; pa_buffer_attributes.fragsize = static_cast(-1); diff --git a/src/media/audio/win/audio_device_listener_win.cc b/src/media/audio/win/audio_device_listener_win.cc index ecf8387..81d6798 100644 --- a/src/media/audio/win/audio_device_listener_win.cc +++ b/src/media/audio/win/audio_device_listener_win.cc @@ -125,9 +125,6 @@ STDMETHODIMP AudioDeviceListenerWin::OnDeviceRemoved(LPCWSTR device_id) { STDMETHODIMP AudioDeviceListenerWin::OnDeviceStateChanged(LPCWSTR device_id, DWORD new_state) { - if (new_state != DEVICE_STATE_ACTIVE && new_state != DEVICE_STATE_NOTPRESENT) - return S_OK; - base::SystemMonitor* monitor = base::SystemMonitor::Get(); if (monitor) monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); diff --git a/src/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java b/src/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java index a5299d9..d575c27 100644 --- a/src/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java +++ b/src/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java @@ -8,6 +8,8 @@ import android.content.Context; import android.media.MediaPlayer; import android.net.Uri; import android.os.AsyncTask; +import android.os.Build; +import android.os.ParcelFileDescriptor; import android.text.TextUtils; import android.util.Base64; import android.util.Base64InputStream; @@ -156,6 +158,12 @@ public class MediaPlayerBridge { if (hideUrlLog) headersMap.put("x-hide-urls-from-log", "true"); if (!TextUtils.isEmpty(cookies)) headersMap.put("Cookie", cookies); if (!TextUtils.isEmpty(userAgent)) headersMap.put("User-Agent", userAgent); + // The security origin check is enforced for devices above K. For devices below K, + // only anonymous media HTTP request (no cookies) may be considered same-origin. + // Note that if the server rejects the request we must not consider it same-origin. + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + headersMap.put("allow-cross-domain-redirect", "false"); + } try { if (sResourceLoadFilter != null && sResourceLoadFilter.shouldOverrideResourceLoading( @@ -170,6 +178,19 @@ public class MediaPlayerBridge { } @CalledByNative + protected boolean setDataSourceFromFd(int fd, long offset, long length) { + try { + ParcelFileDescriptor parcelFd = ParcelFileDescriptor.adoptFd(fd); + getLocalPlayer().setDataSource(parcelFd.getFileDescriptor(), offset, length); + parcelFd.close(); + return true; + } catch (IOException e) { + Log.e(TAG, "Failed to set data source from file descriptor: " + e); + return false; + } + } + + @CalledByNative protected boolean setDataUriDataSource(final Context context, final String url) { if (mLoadDataUriTask != null) { mLoadDataUriTask.cancel(true); diff --git a/src/media/base/android/media_player_bridge.cc b/src/media/base/android/media_player_bridge.cc index 9628aa1..6d0ad91 100644 --- a/src/media/base/android/media_player_bridge.cc +++ b/src/media/base/android/media_player_bridge.cc @@ -13,6 +13,7 @@ #include "jni/MediaPlayerBridge_jni.h" #include "media/base/android/media_player_manager.h" #include "media/base/android/media_resource_getter.h" +#include "media/base/android/media_url_interceptor.h" using base::android::ConvertUTF8ToJavaString; using base::android::ScopedJavaLocalRef; @@ -34,7 +35,8 @@ MediaPlayerBridge::MediaPlayerBridge( MediaPlayerManager* manager, const RequestMediaResourcesCB& request_media_resources_cb, const ReleaseMediaResourcesCB& release_media_resources_cb, - const GURL& frame_url) + const GURL& frame_url, + bool allow_credentials) : MediaPlayerAndroid(player_id, manager, request_media_resources_cb, @@ -53,6 +55,7 @@ MediaPlayerBridge::MediaPlayerBridge( can_seek_backward_(true), is_surface_in_use_(false), volume_(-1.0), + allow_credentials_(allow_credentials), weak_factory_(this) { listener_.reset(new MediaPlayerListener(base::MessageLoopProxy::current(), weak_factory_.GetWeakPtr())); @@ -84,6 +87,13 @@ void MediaPlayerBridge::Initialize() { return; } + // Start extracting the metadata immediately if the request is anonymous. + // Otherwise, wait for user credentials to be retrieved first. + if (!allow_credentials_) { + ExtractMediaMetadata(url_.spec()); + return; + } + resource_getter->GetCookies(url_, first_party_for_cookies_, base::Bind(&MediaPlayerBridge::OnCookiesRetrieved, @@ -164,30 +174,43 @@ void MediaPlayerBridge::SetDataSource(const std::string& url) { JNIEnv* env = base::android::AttachCurrentThread(); CHECK(env); - // Create a Java String for the URL. - ScopedJavaLocalRef j_url_string = ConvertUTF8ToJavaString(env, url); - ScopedJavaLocalRef j_cookies = ConvertUTF8ToJavaString( - env, cookies_); - ScopedJavaLocalRef j_user_agent = ConvertUTF8ToJavaString( - env, user_agent_); + int fd; + int64 offset; + int64 size; + if (InterceptMediaUrl(url, &fd, &offset, &size)) { + if (!Java_MediaPlayerBridge_setDataSourceFromFd( + env, j_media_player_bridge_.obj(), fd, offset, size)) { + OnMediaError(MEDIA_ERROR_FORMAT); + return; + } + } else { + // Create a Java String for the URL. + ScopedJavaLocalRef j_url_string = + ConvertUTF8ToJavaString(env, url); + + jobject j_context = base::android::GetApplicationContext(); + DCHECK(j_context); + + const std::string data_uri_prefix("data:"); + if (StartsWithASCII(url, data_uri_prefix, true)) { + if (!Java_MediaPlayerBridge_setDataUriDataSource( + env, j_media_player_bridge_.obj(), j_context, j_url_string.obj())) { + OnMediaError(MEDIA_ERROR_FORMAT); + } + return; + } - jobject j_context = base::android::GetApplicationContext(); - DCHECK(j_context); + ScopedJavaLocalRef j_cookies = ConvertUTF8ToJavaString( + env, cookies_); + ScopedJavaLocalRef j_user_agent = ConvertUTF8ToJavaString( + env, user_agent_); - const std::string data_uri_prefix("data:"); - if (StartsWithASCII(url, data_uri_prefix, true)) { - if (!Java_MediaPlayerBridge_setDataUriDataSource( - env, j_media_player_bridge_.obj(), j_context, j_url_string.obj())) { + if (!Java_MediaPlayerBridge_setDataSource( + env, j_media_player_bridge_.obj(), j_context, j_url_string.obj(), + j_cookies.obj(), j_user_agent.obj(), hide_url_log_)) { OnMediaError(MEDIA_ERROR_FORMAT); + return; } - return; - } - - if (!Java_MediaPlayerBridge_setDataSource( - env, j_media_player_bridge_.obj(), j_context, j_url_string.obj(), - j_cookies.obj(), j_user_agent.obj(), hide_url_log_)) { - OnMediaError(MEDIA_ERROR_FORMAT); - return; } request_media_resources_cb_.Run(player_id()); @@ -195,6 +218,25 @@ void MediaPlayerBridge::SetDataSource(const std::string& url) { OnMediaError(MEDIA_ERROR_FORMAT); } +bool MediaPlayerBridge::InterceptMediaUrl( + const std::string& url, int* fd, int64* offset, int64* size) { + // Sentinel value to check whether the output arguments have been set. + const int kUnsetValue = -1; + + *fd = kUnsetValue; + *offset = kUnsetValue; + *size = kUnsetValue; + media::MediaUrlInterceptor* url_interceptor = + manager()->GetMediaUrlInterceptor(); + if (url_interceptor && url_interceptor->Intercept(url, fd, offset, size)) { + DCHECK_NE(kUnsetValue, *fd); + DCHECK_NE(kUnsetValue, *offset); + DCHECK_NE(kUnsetValue, *size); + return true; + } + return false; +} + void MediaPlayerBridge::OnDidSetDataUriDataSource(JNIEnv* env, jobject obj, jboolean success) { if (!success) { @@ -213,12 +255,20 @@ void MediaPlayerBridge::OnCookiesRetrieved(const std::string& cookies) { } void MediaPlayerBridge::ExtractMediaMetadata(const std::string& url) { - manager()->GetMediaResourceGetter()->ExtractMediaMetadata( - url, - cookies_, - user_agent_, - base::Bind(&MediaPlayerBridge::OnMediaMetadataExtracted, - weak_factory_.GetWeakPtr())); + int fd; + int64 offset; + int64 size; + if (InterceptMediaUrl(url, &fd, &offset, &size)) { + manager()->GetMediaResourceGetter()->ExtractMediaMetadata( + fd, offset, size, + base::Bind(&MediaPlayerBridge::OnMediaMetadataExtracted, + weak_factory_.GetWeakPtr())); + } else { + manager()->GetMediaResourceGetter()->ExtractMediaMetadata( + url, cookies_, user_agent_, + base::Bind(&MediaPlayerBridge::OnMediaMetadataExtracted, + weak_factory_.GetWeakPtr())); + } } void MediaPlayerBridge::OnMediaMetadataExtracted( diff --git a/src/media/base/android/media_player_bridge.h b/src/media/base/android/media_player_bridge.h index f63d626..792ebc1 100644 --- a/src/media/base/android/media_player_bridge.h +++ b/src/media/base/android/media_player_bridge.h @@ -50,7 +50,8 @@ class MEDIA_EXPORT MediaPlayerBridge : public MediaPlayerAndroid { MediaPlayerManager* manager, const RequestMediaResourcesCB& request_media_resources_cb, const ReleaseMediaResourcesCB& release_media_resources_cb, - const GURL& frame_url); + const GURL& frame_url, + bool allow_credentials); virtual ~MediaPlayerBridge(); // Initialize this object and extract the metadata from the media. @@ -132,6 +133,11 @@ class MEDIA_EXPORT MediaPlayerBridge : public MediaPlayerAndroid { void OnMediaMetadataExtracted(base::TimeDelta duration, int width, int height, bool success); + // Returns true if a MediaUrlInterceptor registered by the embedder has + // intercepted the url. + bool InterceptMediaUrl( + const std::string& url, int* fd, int64* offset, int64* size); + // Whether the player is prepared for playback. bool prepared_; @@ -180,6 +186,9 @@ class MEDIA_EXPORT MediaPlayerBridge : public MediaPlayerAndroid { // Volume of playback. double volume_; + // Whether user credentials are allowed to be passed. + bool allow_credentials_; + // Weak pointer passed to |listener_| for callbacks. // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory weak_factory_; diff --git a/src/media/base/android/media_player_manager.h b/src/media/base/android/media_player_manager.h index 0b79f18..be84b08 100644 --- a/src/media/base/android/media_player_manager.h +++ b/src/media/base/android/media_player_manager.h @@ -14,15 +14,19 @@ namespace media { class MediaPlayerAndroid; class MediaResourceGetter; +class MediaUrlInterceptor; // This class is responsible for managing active MediaPlayerAndroid objects. class MEDIA_EXPORT MediaPlayerManager { public: virtual ~MediaPlayerManager() {} - // Return a pointer to the MediaResourceGetter object. + // Returns a pointer to the MediaResourceGetter object. virtual MediaResourceGetter* GetMediaResourceGetter() = 0; + // Returns a pointer to the MediaUrlInterceptor object or null. + virtual MediaUrlInterceptor* GetMediaUrlInterceptor() = 0; + // Called when time update messages need to be sent. Args: player ID, // current time. virtual void OnTimeUpdate(int player_id, base::TimeDelta current_time) = 0; diff --git a/src/media/base/android/media_resource_getter.h b/src/media/base/android/media_resource_getter.h index 075f9d0..72f204f 100644 --- a/src/media/base/android/media_resource_getter.h +++ b/src/media/base/android/media_resource_getter.h @@ -35,13 +35,21 @@ class MEDIA_EXPORT MediaResourceGetter { const GURL& url, const GetPlatformPathCB& callback) = 0; - // Extract the metadata from a media URL. Once completed, the provided + // Extracts the metadata from a media URL. Once completed, the provided // callback function will be run. virtual void ExtractMediaMetadata( const std::string& url, const std::string& cookies, const std::string& user_agent, const ExtractMediaMetadataCB& callback) = 0; + + // Extracts the metadata from a file descriptor. Once completed, the + // provided callback function will be run. + virtual void ExtractMediaMetadata( + const int fd, + const int64 offset, + const int64 size, + const ExtractMediaMetadataCB& callback) = 0; }; } // namespace media diff --git a/src/media/base/android/media_source_player_unittest.cc b/src/media/base/android/media_source_player_unittest.cc index 604c195..09b031c 100644 --- a/src/media/base/android/media_source_player_unittest.cc +++ b/src/media/base/android/media_source_player_unittest.cc @@ -13,6 +13,7 @@ #include "media/base/android/media_drm_bridge.h" #include "media/base/android/media_player_manager.h" #include "media/base/android/media_source_player.h" +#include "media/base/android/media_url_interceptor.h" #include "media/base/android/video_decoder_job.h" #include "media/base/bind_to_current_loop.h" #include "media/base/decoder_buffer.h" @@ -52,6 +53,9 @@ class MockMediaPlayerManager : public MediaPlayerManager { virtual MediaResourceGetter* GetMediaResourceGetter() OVERRIDE { return NULL; } + virtual MediaUrlInterceptor* GetMediaUrlInterceptor() OVERRIDE { + return NULL; + } virtual void OnTimeUpdate(int player_id, base::TimeDelta current_time) OVERRIDE { timestamp_updated_ = true; diff --git a/src/media/base/android/media_url_interceptor.h b/src/media/base/android/media_url_interceptor.h new file mode 100644 index 0000000..e1db623 --- /dev/null +++ b/src/media/base/android/media_url_interceptor.h @@ -0,0 +1,36 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_ANDROID_MEDIA_URL_INTERCEPTOR_H_ +#define MEDIA_BASE_ANDROID_MEDIA_URL_INTERCEPTOR_H_ + +#include + +#include "base/android/jni_android.h" +#include "media/base/media_export.h" + +namespace media { + +// Interceptor for content embedders to handle custom media urls +// and translate them into files containing media. +class MEDIA_EXPORT MediaUrlInterceptor { + public: + virtual ~MediaUrlInterceptor() {}; + + // Returns true if the embedder has intercepted the url and + // false otherwise. + // Output arguments (only when the url has been intercepted): + // - |fd|: file descriptor to the file containing the media element. + // - |offset|: offset in bytes from the start of the file to the + // media element. + // - |size|: size in bytes of the media element. + virtual bool Intercept(const std::string& url, + int* fd, + int64* offset, + int64* size) const = 0; +}; + +} // namespace media + +#endif // MEDIA_BASE_ANDROID_MEDIA_URL_INTERCEPTOR_H_ diff --git a/src/media/filters/ffmpeg_demuxer.cc b/src/media/filters/ffmpeg_demuxer.cc index 62b39c1..f5b4fdd 100644 --- a/src/media/filters/ffmpeg_demuxer.cc +++ b/src/media/filters/ffmpeg_demuxer.cc @@ -67,7 +67,6 @@ FFmpegDemuxerStream::FFmpegDemuxerStream( type_(UNKNOWN), end_of_stream_(false), last_packet_timestamp_(kNoTimestamp()), - last_packet_duration_(kNoTimestamp()), bitstream_converter_enabled_(false) { DCHECK(demuxer_); @@ -231,41 +230,13 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { stream_->time_base, packet->pts)); buffer->set_duration(ConvertStreamTimestamp( stream_->time_base, packet->duration)); - - if (last_packet_timestamp_ != kNoTimestamp()) { - // FFmpeg doesn't support chained ogg correctly. Instead of guaranteeing - // continuity across links in the chain it uses the timestamp information - // from each link directly. Doing so can lead to timestamps which appear to - // go backwards in time. - // - // If the new link starts with a negative timestamp or a timestamp less than - // the original (positive) |start_time|, we will get a negative timestamp - // here. It's also possible FFmpeg returns kNoTimestamp() here if it's not - // able to work out a timestamp using the previous link and the next. - // - // Fixing chained ogg is non-trivial, so for now just reuse the last good - // timestamp. The decoder will rewrite the timestamps to be sample accurate - // later. See http://crbug.com/396864. - if (buffer->timestamp() == kNoTimestamp() || - buffer->timestamp() < last_packet_timestamp_) { - buffer->set_timestamp(last_packet_timestamp_ + - (last_packet_duration_ != kNoTimestamp() - ? last_packet_duration_ - : base::TimeDelta::FromMicroseconds(1))); - } - - // The demuxer should always output positive timestamps. - DCHECK(buffer->timestamp() >= base::TimeDelta()); - DCHECK(buffer->timestamp() != kNoTimestamp()); - - if (last_packet_timestamp_ < buffer->timestamp()) { - buffered_ranges_.Add(last_packet_timestamp_, buffer->timestamp()); - demuxer_->NotifyBufferingChanged(); - } + if (buffer->timestamp() != kNoTimestamp() && + last_packet_timestamp_ != kNoTimestamp() && + last_packet_timestamp_ < buffer->timestamp()) { + buffered_ranges_.Add(last_packet_timestamp_, buffer->timestamp()); + demuxer_->NotifyBufferingChanged(); } - last_packet_timestamp_ = buffer->timestamp(); - last_packet_duration_ = buffer->duration(); buffer_queue_.Push(buffer); SatisfyPendingRead(); @@ -283,7 +254,6 @@ void FFmpegDemuxerStream::FlushBuffers() { buffer_queue_.Clear(); end_of_stream_ = false; last_packet_timestamp_ = kNoTimestamp(); - last_packet_duration_ = kNoTimestamp(); } void FFmpegDemuxerStream::Stop() { diff --git a/src/media/filters/ffmpeg_demuxer.h b/src/media/filters/ffmpeg_demuxer.h index d5cff8c..02682bb 100644 --- a/src/media/filters/ffmpeg_demuxer.h +++ b/src/media/filters/ffmpeg_demuxer.h @@ -124,7 +124,6 @@ class FFmpegDemuxerStream : public DemuxerStream { base::TimeDelta duration_; bool end_of_stream_; base::TimeDelta last_packet_timestamp_; - base::TimeDelta last_packet_duration_; Ranges buffered_ranges_; DecoderBufferQueue buffer_queue_; diff --git a/src/media/media.gyp b/src/media/media.gyp index 71099e9..25497d1 100644 --- a/src/media/media.gyp +++ b/src/media/media.gyp @@ -1643,6 +1643,7 @@ 'base/android/media_player_listener.h', 'base/android/media_source_player.cc', 'base/android/media_source_player.h', + 'base/android/media_url_interceptor.h', 'base/android/video_decoder_job.cc', 'base/android/video_decoder_job.h', 'base/android/webaudio_media_codec_bridge.cc', diff --git a/src/net/android/java/src/org/chromium/net/ProxyChangeListener.java b/src/net/android/java/src/org/chromium/net/ProxyChangeListener.java index 7b57396..63bfb30 100644 --- a/src/net/android/java/src/org/chromium/net/ProxyChangeListener.java +++ b/src/net/android/java/src/org/chromium/net/ProxyChangeListener.java @@ -99,15 +99,19 @@ public class ProxyChangeListener { try { final String GET_HOST_NAME = "getHost"; final String GET_PORT_NAME = "getPort"; - Object props = intent.getExtras().get("proxy"); - if (props == null) { - return null; - } String className; + String proxyInfo; if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { className = "android.net.ProxyProperties"; + proxyInfo = "proxy"; } else { className = "android.net.ProxyInfo"; + proxyInfo = "android.intent.extra.PROXY_INFO"; + } + + Object props = intent.getExtras().get(proxyInfo); + if (props == null) { + return null; } Class cls = Class.forName(className); diff --git a/src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash-expected.txt b/src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash-expected.txt new file mode 100644 index 0000000..50fc47e --- /dev/null +++ b/src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash-expected.txt @@ -0,0 +1,3 @@ + +PASS if this test didn't crash. + diff --git a/src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash.html b/src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash.html new file mode 100644 index 0000000..b520061 --- /dev/null +++ b/src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash.html @@ -0,0 +1,3 @@ + + +

PASS if this test didn't crash.

diff --git a/src/third_party/WebKit/LayoutTests/fast/css/resources/import-layout-with-pending-sheet.html b/src/third_party/WebKit/LayoutTests/fast/css/resources/import-layout-with-pending-sheet.html new file mode 100644 index 0000000..366e415 --- /dev/null +++ b/src/third_party/WebKit/LayoutTests/fast/css/resources/import-layout-with-pending-sheet.html @@ -0,0 +1,11 @@ + + +

+ diff --git a/src/third_party/WebKit/Source/core/dom/Document.cpp b/src/third_party/WebKit/Source/core/dom/Document.cpp index 68bf2f9..8eccef9 100644 --- a/src/third_party/WebKit/Source/core/dom/Document.cpp +++ b/src/third_party/WebKit/Source/core/dom/Document.cpp @@ -3462,7 +3462,10 @@ void Document::styleResolverChanged(StyleResolverUpdateMode updateMode) // We need to manually repaint because we avoid doing all repaints in layout or style // recalc while sheets are still loading to avoid FOUC. m_pendingSheetLayout = IgnoreLayoutWithPendingSheets; - renderView()->repaintViewAndCompositedLayers(); + + ASSERT(renderView() || importsController()); + if (renderView()) + renderView()->repaintViewAndCompositedLayers(); } } diff --git a/src/third_party/WebKit/Source/core/frame/Settings.in b/src/third_party/WebKit/Source/core/frame/Settings.in index 20b7363..90fc417 100644 --- a/src/third_party/WebKit/Source/core/frame/Settings.in +++ b/src/third_party/WebKit/Source/core/frame/Settings.in @@ -203,6 +203,10 @@ viewportMetaMergeContentQuirk initial=false # See http://crbug.com/288037. wideViewportQuirkEnabled initial=false +# Used by the android_webview to support a horizontal height auto-sizing +# mode. +forceZeroLayoutHeight initial=false, invalidate=ViewportDescription + # Touch based text selection and editing on desktop. # crbug.com/304873 tracks removal once it's been enabled on all platforms. touchEditingEnabled initial=false diff --git a/src/third_party/WebKit/Source/core/frame/SmartClip.cpp b/src/third_party/WebKit/Source/core/frame/SmartClip.cpp index 40c773e..329412c 100644 --- a/src/third_party/WebKit/Source/core/frame/SmartClip.cpp +++ b/src/third_party/WebKit/Source/core/frame/SmartClip.cpp @@ -61,33 +61,14 @@ static Node* nodeInsideFrame(Node* node) return 0; } -// FIXME: SmartClipData is eventually returned via -// SLookSmartClip.DataExtractionListener: -// http://img-developer.samsung.com/onlinedocs/sms/com/samsung/android/sdk/look/... -// however the original author of this change chose to use a string-serialization -// format (presumably to make IPC easy?). -// If we're going to use this as a Pickle format, we should at least have the -// read/write code in one place! -String SmartClipData::toString() +IntRect SmartClipData::rect() const { - if (m_isEmpty) - return emptyString(); - - const UChar fieldSeparator = 0xFFFE; - const UChar rowSeparator = 0xFFFF; + return m_rect; +} - StringBuilder result; - result.append(String::number(m_rect.x())); - result.append(fieldSeparator); - result.append(String::number(m_rect.y())); - result.append(fieldSeparator); - result.append(String::number(m_rect.width())); - result.append(fieldSeparator); - result.append(String::number(m_rect.height())); - result.append(fieldSeparator); - result.append(m_string); - result.append(rowSeparator); - return result.toString(); +const String& SmartClipData::clipData() const +{ + return m_string; } SmartClip::SmartClip(PassRefPtr frame) diff --git a/src/third_party/WebKit/Source/core/frame/SmartClip.h b/src/third_party/WebKit/Source/core/frame/SmartClip.h index 21955a2..76b0c49 100644 --- a/src/third_party/WebKit/Source/core/frame/SmartClip.h +++ b/src/third_party/WebKit/Source/core/frame/SmartClip.h @@ -50,7 +50,8 @@ public: { } - String toString(); + IntRect rect() const; + const String& clipData() const; private: bool m_isEmpty; diff --git a/src/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/src/third_party/WebKit/Source/web/WebLocalFrameImpl.h index 4993b76..5991c02 100644 --- a/src/third_party/WebKit/Source/web/WebLocalFrameImpl.h +++ b/src/third_party/WebKit/Source/web/WebLocalFrameImpl.h @@ -313,6 +313,9 @@ public: PassRefPtr initializeAsChildFrame(WebCore::FrameHost*, WebCore::FrameOwner*, const AtomicString& name, const AtomicString& fallbackName); + // Returns a hit-tested VisiblePosition for the given point + WebCore::VisiblePosition visiblePositionForWindowPoint(const WebPoint&); + private: friend class FrameLoaderClientImpl; @@ -323,9 +326,6 @@ private: void loadJavaScriptURL(const WebCore::KURL&); - // Returns a hit-tested VisiblePosition for the given point - WebCore::VisiblePosition visiblePositionForWindowPoint(const WebPoint&); - WebPlugin* focusedPluginIfInputMethodSupported(); FrameLoaderClientImpl m_frameLoaderClientImpl; diff --git a/src/third_party/WebKit/Source/web/WebSettingsImpl.cpp b/src/third_party/WebKit/Source/web/WebSettingsImpl.cpp index be30687..55b2276 100644 --- a/src/third_party/WebKit/Source/web/WebSettingsImpl.cpp +++ b/src/third_party/WebKit/Source/web/WebSettingsImpl.cpp @@ -661,6 +661,11 @@ void WebSettingsImpl::setGestureTapHighlightEnabled(bool enableHighlight) m_gestureTapHighlightEnabled = enableHighlight; } +void WebSettingsImpl::setForceZeroLayoutHeight(bool enabled) +{ + m_settings->setForceZeroLayoutHeight(enabled); +} + void WebSettingsImpl::setAllowCustomScrollbarInMainFrame(bool enabled) { m_settings->setAllowCustomScrollbarInMainFrame(enabled); diff --git a/src/third_party/WebKit/Source/web/WebSettingsImpl.h b/src/third_party/WebKit/Source/web/WebSettingsImpl.h index 45b0dfe..26dd7e3 100644 --- a/src/third_party/WebKit/Source/web/WebSettingsImpl.h +++ b/src/third_party/WebKit/Source/web/WebSettingsImpl.h @@ -100,6 +100,7 @@ public: virtual void setFantasyFontFamily(const WebString&, UScriptCode = USCRIPT_COMMON) OVERRIDE; virtual void setFixedFontFamily(const WebString&, UScriptCode = USCRIPT_COMMON) OVERRIDE; virtual void setGestureTapHighlightEnabled(bool) OVERRIDE; + virtual void setForceZeroLayoutHeight(bool) OVERRIDE; virtual void setHyperlinkAuditingEnabled(bool) OVERRIDE; virtual void setIgnoreMainFrameOverflowHiddenQuirk(bool) OVERRIDE; virtual void setImagesEnabled(bool) OVERRIDE; diff --git a/src/third_party/WebKit/Source/web/WebViewImpl.cpp b/src/third_party/WebKit/Source/web/WebViewImpl.cpp index 6eed6fc..2c16122 100644 --- a/src/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/src/third_party/WebKit/Source/web/WebViewImpl.cpp @@ -40,8 +40,10 @@ #include "core/dom/Text.h" #include "core/editing/Editor.h" #include "core/editing/FrameSelection.h" +#include "core/editing/HTMLInterchange.h" #include "core/editing/InputMethodController.h" #include "core/editing/TextIterator.h" +#include "core/editing/markup.h" #include "core/events/KeyboardEvent.h" #include "core/events/WheelEvent.h" #include "core/frame/EventHandlerRegistry.h" @@ -3030,6 +3032,9 @@ void WebViewImpl::updateMainFrameLayoutSize() } } + if (page()->settings().forceZeroLayoutHeight()) + layoutSize.height = 0; + view->setLayoutSize(layoutSize); } @@ -3495,12 +3500,48 @@ void WebViewImpl::showContextMenu() m_contextMenuAllowed = false; } +// FIXME: This should be removed when the chromium side patch lands +// http://codereview.chromium.org/260623004 WebString WebViewImpl::getSmartClipData(WebRect rect) { + return WebString(); +} + +void WebViewImpl::getSmartClipData(WebRect rect, WebString& clipText, WebRect& clipRect) +{ LocalFrame* frame = toLocalFrame(focusedWebCoreFrame()); if (!frame) - return WebString(); - return WebCore::SmartClip(frame).dataForRect(rect).toString(); + return; + SmartClipData clipData = WebCore::SmartClip(frame).dataForRect(rect); + clipText = clipData.clipData(); + clipRect = clipData.rect(); +} + +void WebViewImpl::extractSmartClipData(WebRect rect, WebString& clipText, WebString& clipHtml, WebRect& clipRect) +{ + LocalFrame* localFrame = toLocalFrame(focusedWebCoreFrame()); + if (!localFrame) + return; + SmartClipData clipData = WebCore::SmartClip(localFrame).dataForRect(rect); + clipText = clipData.clipData(); + clipRect = clipData.rect(); + + WebLocalFrameImpl* frame = mainFrameImpl(); + if (!frame) + return; + WebPoint startPoint(rect.x, rect.y); + WebPoint endPoint(rect.x + rect.width, rect.y + rect.height); + VisiblePosition startVisiblePosition = frame->visiblePositionForWindowPoint(startPoint); + VisiblePosition endVisiblePosition = frame->visiblePositionForWindowPoint(endPoint); + + Position startPosition = startVisiblePosition.deepEquivalent(); + Position endPosition = endVisiblePosition.deepEquivalent(); + + RefPtr range = Range::create(*startPosition.document(), startPosition, endPosition); + if (!range) + return; + + clipHtml = createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs); } void WebViewImpl::hidePopups() diff --git a/src/third_party/WebKit/Source/web/WebViewImpl.h b/src/third_party/WebKit/Source/web/WebViewImpl.h index 66ec102..9b42e4a 100644 --- a/src/third_party/WebKit/Source/web/WebViewImpl.h +++ b/src/third_party/WebKit/Source/web/WebViewImpl.h @@ -245,7 +245,11 @@ public: unsigned inactiveForegroundColor) OVERRIDE; virtual void performCustomContextMenuAction(unsigned action) OVERRIDE; virtual void showContextMenu() OVERRIDE; + // FIXME: This should be removed when the chromium side patch lands + // http://codereview.chromium.org/260623004 virtual WebString getSmartClipData(WebRect) OVERRIDE; + virtual void getSmartClipData(WebRect, WebString&, WebRect&) OVERRIDE; + virtual void extractSmartClipData(WebRect, WebString&, WebString&, WebRect&) OVERRIDE; virtual void hidePopups() OVERRIDE; virtual void addPageOverlay(WebPageOverlay*, int /* zOrder */) OVERRIDE; virtual void removePageOverlay(WebPageOverlay*) OVERRIDE; diff --git a/src/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/src/third_party/WebKit/Source/web/tests/WebFrameTest.cpp index d248761..31fbdaf 100644 --- a/src/third_party/WebKit/Source/web/tests/WebFrameTest.cpp +++ b/src/third_party/WebKit/Source/web/tests/WebFrameTest.cpp @@ -1368,6 +1368,86 @@ TEST_F(WebFrameTest, WideViewportInitialScaleDoesNotExpandFixedLayoutWidth) EXPECT_EQ(0.5f, webViewHelper.webView()->pageScaleFactor()); } +TEST_F(WebFrameTest, SetForceZeroLayoutHeight) +{ + UseMockScrollbarSettings mockScrollbarSettings; + registerMockedHttpURLLoad("200-by-300.html"); + + FixedLayoutTestWebViewClient client; + client.m_screenInfo.deviceScaleFactor = 1; + int viewportWidth = 640; + int viewportHeight = 480; + + FrameTestHelpers::WebViewHelper webViewHelper; + + webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings); + webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); + webViewHelper.webView()->layout(); + + EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); + webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true); + EXPECT_TRUE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout()); + + EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); + + webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight * 2)); + EXPECT_FALSE(webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->needsLayout()); + EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); + + webViewHelper.webView()->resize(WebSize(viewportWidth * 2, viewportHeight)); + webViewHelper.webView()->layout(); + EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); + + webViewHelper.webView()->settings()->setForceZeroLayoutHeight(false); + EXPECT_LE(viewportHeight, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); +} + +TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations) +{ + UseMockScrollbarSettings mockScrollbarSettings; + registerMockedHttpURLLoad("200-by-300.html"); + registerMockedHttpURLLoad("large-div.html"); + + FixedLayoutTestWebViewClient client; + client.m_screenInfo.deviceScaleFactor = 1; + int viewportWidth = 640; + int viewportHeight = 480; + + FrameTestHelpers::WebViewHelper webViewHelper; + + webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings); + webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true); + webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); + webViewHelper.webView()->layout(); + + FrameTestHelpers::loadFrame(webViewHelper.webView()->mainFrame(), m_baseURL + "large-div.html"); + webViewHelper.webView()->layout(); + + EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); +} + +TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk) +{ + UseMockScrollbarSettings mockScrollbarSettings; + registerMockedHttpURLLoad("200-by-300.html"); + + FixedLayoutTestWebViewClient client; + client.m_screenInfo.deviceScaleFactor = 1; + int viewportWidth = 640; + int viewportHeight = 480; + + FrameTestHelpers::WebViewHelper webViewHelper; + + webViewHelper.initializeAndLoad(m_baseURL + "200-by-300.html", true, 0, &client, enableViewportSettings); + webViewHelper.webView()->settings()->setWideViewportQuirkEnabled(true); + webViewHelper.webView()->settings()->setUseWideViewport(true); + webViewHelper.webView()->settings()->setForceZeroLayoutHeight(true); + webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); + webViewHelper.webView()->layout(); + + EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height()); +} + TEST_F(WebFrameTest, WideViewportAndWideContentWithInitialScale) { UseMockScrollbarSettings mockScrollbarSettings; diff --git a/src/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/src/third_party/WebKit/Source/web/tests/WebViewTest.cpp index 4d6dd81..af2752f 100644 --- a/src/third_party/WebKit/Source/web/tests/WebViewTest.cpp +++ b/src/third_party/WebKit/Source/web/tests/WebViewTest.cpp @@ -1548,6 +1548,26 @@ TEST_F(WebViewTest, DispatchesFocusBlurOnViewToggle) TEST_F(WebViewTest, SmartClipData) { + static const char* kExpectedClipText = "\nPrice 10,000,000won"; + static const char* kExpectedClipHtml = + "
Air " + "conditioner
Price 10,000,000won
"; + WebString clipText; + WebString clipHtml; + WebRect clipRect; URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("Ahem.ttf")); URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("smartclip.html")); WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "smartclip.html"); @@ -1555,9 +1575,9 @@ TEST_F(WebViewTest, SmartClipData) webView->resize(WebSize(500, 500)); webView->layout(); WebRect cropRect(300, 125, 100, 50); - - // FIXME: We should test the structure of the data we get back. - EXPECT_FALSE(webView->getSmartClipData(cropRect).isEmpty()); + webView->extractSmartClipData(cropRect, clipText, clipHtml, clipRect); + EXPECT_STREQ(kExpectedClipText, clipText.utf8().c_str()); + EXPECT_STREQ(kExpectedClipHtml, clipHtml.utf8().c_str()); } class CreateChildCounterFrameClient : public FrameTestHelpers::TestWebFrameClient { diff --git a/src/third_party/WebKit/public/web/WebSettings.h b/src/third_party/WebKit/public/web/WebSettings.h index 3ea9d69..95c85a3 100644 --- a/src/third_party/WebKit/public/web/WebSettings.h +++ b/src/third_party/WebKit/public/web/WebSettings.h @@ -123,6 +123,7 @@ public: virtual void setFantasyFontFamily(const WebString&, UScriptCode = USCRIPT_COMMON) = 0; virtual void setFixedFontFamily(const WebString&, UScriptCode = USCRIPT_COMMON) = 0; virtual void setGestureTapHighlightEnabled(bool) = 0; + virtual void setForceZeroLayoutHeight(bool) = 0; virtual void setHyperlinkAuditingEnabled(bool) = 0; virtual void setIgnoreMainFrameOverflowHiddenQuirk(bool) = 0; virtual void setImagesEnabled(bool) = 0; diff --git a/src/third_party/WebKit/public/web/WebView.h b/src/third_party/WebKit/public/web/WebView.h index 098baac..a0525bc 100644 --- a/src/third_party/WebKit/public/web/WebView.h +++ b/src/third_party/WebKit/public/web/WebView.h @@ -409,8 +409,14 @@ public: // SmartClip support --------------------------------------------------- + // FIXME: This should be removed when the chromium side patch lands + // http://codereview.chromium.org/260623004 virtual WebString getSmartClipData(WebRect) = 0; + // TODO(changwan): remove this + virtual void getSmartClipData(WebRect, WebString&, WebRect& resultRect) = 0; + virtual void extractSmartClipData(WebRect initRect, WebString& text, WebString& html, WebRect& resultRect) = 0; + // Popup menu ---------------------------------------------------------- diff --git a/src/third_party/angle/src/compiler/translator/OutputHLSL.cpp b/src/third_party/angle/src/compiler/translator/OutputHLSL.cpp index 5520c86..5cc2c14 100644 --- a/src/third_party/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/third_party/angle/src/compiler/translator/OutputHLSL.cpp @@ -582,7 +582,11 @@ void OutputHLSL::header() else { const TStructure *structure = type.getStruct(); - const TString &typeName = (structure ? structureTypeName(*structure, false, false) : typeString(type)); + // If this is a nameless struct, we need to use its full definition, rather than its (empty) name. + // TypeString() will invoke defineNameless in this case, but layout qualifiers, if relevant, will not + // be taken into account. + const TString &typeName = ((structure && !structure->name().empty()) ? + structureTypeName(*structure, false, false) : typeString(type)); const TString ®isterString = TString("register(") + RegisterPrefix(type) + str(registerIndex) + ")"; diff --git a/src/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/src/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java index 7391ac5..0f0f94b 100644 --- a/src/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java +++ b/src/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java @@ -7,13 +7,14 @@ package org.chromium.ui.base; import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; -import android.database.Cursor; import android.net.Uri; +import android.os.AsyncTask; import android.os.Environment; import android.provider.MediaStore; import android.text.TextUtils; import org.chromium.base.CalledByNative; +import org.chromium.base.ContentUriUtils; import org.chromium.base.JNINamespace; import org.chromium.ui.R; @@ -130,31 +131,6 @@ class SelectFileDialog implements WindowAndroid.IntentCallback{ } /** - * @return the display name of the @code uri if present in the database - * or an empty string otherwise. - */ - private String resolveFileName(Uri uri, ContentResolver contentResolver) { - if (contentResolver == null || uri == null) return ""; - Cursor cursor = null; - try { - cursor = contentResolver.query(uri, null, null, null, null); - - if (cursor != null && cursor.getCount() >= 1) { - cursor.moveToFirst(); - int index = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME); - if (index > -1) return cursor.getString(index); - } - } catch (NullPointerException e) { - // Some android models don't handle the provider call correctly. - // see crbug.com/345393 - return ""; - } finally { - if (cursor != null) cursor.close(); - } - return ""; - } - - /** * Callback method to handle the intent results and pass on the path to the native * SelectFileDialog. * @param window The window that has access to the application activity. @@ -190,10 +166,8 @@ class SelectFileDialog implements WindowAndroid.IntentCallback{ } if (ContentResolver.SCHEME_CONTENT.equals(results.getScheme())) { - nativeOnFileSelected(mNativeSelectFileDialog, - results.getData().toString(), - resolveFileName(results.getData(), - contentResolver)); + GetDisplayNameTask task = new GetDisplayNameTask(contentResolver, false); + task.execute(results.getData()); return; } @@ -255,6 +229,36 @@ class SelectFileDialog implements WindowAndroid.IntentCallback{ return false; } + private class GetDisplayNameTask extends AsyncTask { + String[] mFilePaths; + final ContentResolver mContentResolver; + final boolean mIsMultiple; + + public GetDisplayNameTask(ContentResolver contentResolver, boolean isMultiple) { + mContentResolver = contentResolver; + mIsMultiple = isMultiple; + } + + @Override + protected String[] doInBackground(Uri...uris) { + mFilePaths = new String[uris.length]; + String[] displayNames = new String[uris.length]; + for (int i = 0; i < uris.length; i++) { + mFilePaths[i] = uris[i].toString(); + displayNames[i] = ContentUriUtils.getDisplayName( + uris[i], mContentResolver, MediaStore.MediaColumns.DISPLAY_NAME); + } + return displayNames; + } + + @Override + protected void onPostExecute(String[] result) { + if (!mIsMultiple) { + nativeOnFileSelected(mNativeSelectFileDialog, mFilePaths[0], result[0]); + } + } + } + @CalledByNative private static SelectFileDialog create(long nativeSelectFileDialog) { return new SelectFileDialog(nativeSelectFileDialog); diff --git a/src/ui/aura/window_event_dispatcher.cc b/src/ui/aura/window_event_dispatcher.cc index 87d25b1..5cf693d 100644 --- a/src/ui/aura/window_event_dispatcher.cc +++ b/src/ui/aura/window_event_dispatcher.cc @@ -281,6 +281,9 @@ ui::EventDispatchDetails WindowEventDispatcher::ProcessGestures( return details; Window* target = GetGestureTarget(gestures->get().at(0)); + if (!target) + return details; + for (size_t i = 0; i < gestures->size(); ++i) { ui::GestureEvent* event = gestures->get().at(i); event->ConvertLocationToTarget(window(), target); diff --git a/src/ui/aura/window_event_dispatcher_unittest.cc b/src/ui/aura/window_event_dispatcher_unittest.cc index 11eeaa0..23e0b23 100644 --- a/src/ui/aura/window_event_dispatcher_unittest.cc +++ b/src/ui/aura/window_event_dispatcher_unittest.cc @@ -776,6 +776,19 @@ TEST_F(WindowEventDispatcherTest, TouchMovesHeld) { EXPECT_TRUE(recorder.events().empty()); } +// Verifies that a direct call to ProcessedTouchEvent() with a +// TOUCH_PRESSED event does not cause a crash. +TEST_F(WindowEventDispatcherTest, CallToProcessedTouchEvent) { + test::TestWindowDelegate delegate; + scoped_ptr window(CreateTestWindowWithDelegate( + &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window())); + + ui::TouchEvent touch( + ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 1, ui::EventTimeForNow()); + host()->dispatcher()->ProcessedTouchEvent( + &touch, window.get(), ui::ER_UNHANDLED); +} + // This event handler requests the dispatcher to start holding pointer-move // events when it receives the first scroll-update gesture. class HoldPointerOnScrollHandler : public ui::test::TestEventHandler { diff --git a/src/ui/base/ime/chromeos/ime_keymap.cc b/src/ui/base/ime/chromeos/ime_keymap.cc index c668609..ec3513a 100644 --- a/src/ui/base/ime/chromeos/ime_keymap.cc +++ b/src/ui/base/ime/chromeos/ime_keymap.cc @@ -134,6 +134,10 @@ const struct KeyCodeTable { {VKEY_VOLUME_MUTE, "VolumeMute"}, {VKEY_VOLUME_DOWN, "VolumeDown"}, {VKEY_VOLUME_UP, "VolumeUp"}, + {VKEY_BRIGHTNESS_DOWN, "BrightnessDown"}, + {VKEY_BRIGHTNESS_UP, "BrightnessUp"}, + {VKEY_MEDIA_LAUNCH_APP1, "ChromeOSSwitchWindow"}, + {VKEY_MEDIA_LAUNCH_APP2, "ChromeOSFullscreen"}, {VKEY_MEDIA_NEXT_TRACK, "MediaTrackNext"}, {VKEY_MEDIA_PREV_TRACK, "MediaTrackPrevious"}, {VKEY_MEDIA_STOP, "MediaStop"}, @@ -154,18 +158,27 @@ const struct KeyCodeTable { class KeyCodeMap { public: KeyCodeMap() { - for (size_t i = 0; i < arraysize(kKeyCodeTable); ++i) - map_[kKeyCodeTable[i].dom_code] = kKeyCodeTable[i].keyboard_code; + for (size_t i = 0; i < arraysize(kKeyCodeTable); ++i) { + map_dom_key_[kKeyCodeTable[i].dom_code] = kKeyCodeTable[i].keyboard_code; + map_key_dom_[kKeyCodeTable[i].keyboard_code] = kKeyCodeTable[i].dom_code; + } } KeyboardCode GetKeyboardCode(const std::string& dom_code) const { std::map::const_iterator it = - map_.find(dom_code); - return (it == map_.end()) ? VKEY_UNKNOWN : it->second; + map_dom_key_.find(dom_code); + return (it == map_dom_key_.end()) ? VKEY_UNKNOWN : it->second; + } + + std::string GetDomKeycode(KeyboardCode key_code) const { + std::map::const_iterator it = + map_key_dom_.find(key_code); + return (it == map_key_dom_.end()) ? "" : it->second; } private: - std::map map_; + std::map map_dom_key_; + std::map map_key_dom_; }; base::LazyInstance::Leaky g_keycode_map = @@ -177,4 +190,8 @@ KeyboardCode DomKeycodeToKeyboardCode(const std::string& code) { return g_keycode_map.Get().GetKeyboardCode(code); } +std::string KeyboardCodeToDomKeycode(KeyboardCode code) { + return g_keycode_map.Get().GetDomKeycode(code); +} + } // namespace ui diff --git a/src/ui/base/ime/chromeos/ime_keymap.h b/src/ui/base/ime/chromeos/ime_keymap.h index 7d41b3f..a4cdf0d 100644 --- a/src/ui/base/ime/chromeos/ime_keymap.h +++ b/src/ui/base/ime/chromeos/ime_keymap.h @@ -15,6 +15,9 @@ namespace ui { // Translates the DOM4 key code string to ui::KeyboardCode. UI_BASE_EXPORT KeyboardCode DomKeycodeToKeyboardCode(const std::string& code); +// Translates the ui::KeyboardCode to DOM4 key code string. +UI_BASE_EXPORT std::string KeyboardCodeToDomKeycode(KeyboardCode code); + } // namespace ui #endif // UI_BASE_IME_CHROMEOS_IME_KEYMAP_H_ diff --git a/src/ui/events/BUILD.gn b/src/ui/events/BUILD.gn index 26c4b1e..e4dba26 100644 --- a/src/ui/events/BUILD.gn +++ b/src/ui/events/BUILD.gn @@ -231,6 +231,8 @@ source_set("events_test_support") { "test/events_test_utils.h", "test/events_test_utils_x11.cc", "test/events_test_utils_x11.h", + "test/mock_motion_event.cc", + "test/mock_motion_event.h", "test/platform_event_waiter.cc", "test/platform_event_waiter.h", "test/test_event_handler.cc", @@ -274,8 +276,6 @@ test("events_unittests") { "gestures/velocity_calculator_unittest.cc", "gesture_detection/bitset_32_unittest.cc", "gesture_detection/gesture_provider_unittest.cc", - "gesture_detection/mock_motion_event.h", - "gesture_detection/mock_motion_event.cc", "gesture_detection/velocity_tracker_unittest.cc", "gesture_detection/touch_disposition_gesture_filter_unittest.cc", "keycodes/dom4/keycode_converter_unittest.cc", diff --git a/src/ui/events/events.gyp b/src/ui/events/events.gyp index 890708d..8f8e911 100644 --- a/src/ui/events/events.gyp +++ b/src/ui/events/events.gyp @@ -236,6 +236,8 @@ 'test/events_test_utils.h', 'test/events_test_utils_x11.cc', 'test/events_test_utils_x11.h', + 'test/mock_motion_event.cc', + 'test/mock_motion_event.h', 'test/platform_event_waiter.cc', 'test/platform_event_waiter.h', 'test/test_event_handler.cc', @@ -286,8 +288,6 @@ 'gestures/velocity_calculator_unittest.cc', 'gesture_detection/bitset_32_unittest.cc', 'gesture_detection/gesture_provider_unittest.cc', - 'gesture_detection/mock_motion_event.h', - 'gesture_detection/mock_motion_event.cc', 'gesture_detection/velocity_tracker_unittest.cc', 'gesture_detection/touch_disposition_gesture_filter_unittest.cc', 'keycodes/dom4/keycode_converter_unittest.cc', diff --git a/src/ui/events/gesture_detection/gesture_provider_unittest.cc b/src/ui/events/gesture_detection/gesture_provider_unittest.cc index 985aa37..2d122fd 100644 --- a/src/ui/events/gesture_detection/gesture_provider_unittest.cc +++ b/src/ui/events/gesture_detection/gesture_provider_unittest.cc @@ -11,12 +11,13 @@ #include "ui/events/event_constants.h" #include "ui/events/gesture_detection/gesture_event_data.h" #include "ui/events/gesture_detection/gesture_provider.h" -#include "ui/events/gesture_detection/mock_motion_event.h" #include "ui/events/gesture_detection/motion_event.h" +#include "ui/events/test/mock_motion_event.h" #include "ui/gfx/geometry/point_f.h" using base::TimeDelta; using base::TimeTicks; +using ui::test::MockMotionEvent; namespace ui { namespace { diff --git a/src/ui/events/gesture_detection/motion_event.h b/src/ui/events/gesture_detection/motion_event.h index 3cf4235..b69a38f 100644 --- a/src/ui/events/gesture_detection/motion_event.h +++ b/src/ui/events/gesture_detection/motion_event.h @@ -24,6 +24,21 @@ class GESTURE_DETECTION_EXPORT MotionEvent { ACTION_POINTER_UP, }; + enum ToolType { + TOOL_TYPE_UNKNOWN, + TOOL_TYPE_FINGER, + TOOL_TYPE_STYLUS, + TOOL_TYPE_MOUSE, + }; + + enum ButtonType { + BUTTON_PRIMARY = 1 << 0, + BUTTON_SECONDARY = 1 << 1, + BUTTON_TERTIARY = 1 << 2, + BUTTON_BACK = 1 << 3, + BUTTON_FORWARD = 1 << 4, + }; + // The implementer promises that |GetPointerId()| will never exceed this. enum { MAX_POINTER_ID = 31 }; @@ -53,6 +68,8 @@ class GESTURE_DETECTION_EXPORT MotionEvent { size_t historical_index) const = 0; virtual float GetHistoricalY(size_t pointer_index, size_t historical_index) const = 0; + virtual ToolType GetToolType(size_t pointer_index) const = 0; + virtual int GetButtonState() const = 0; virtual scoped_ptr Clone() const = 0; virtual scoped_ptr Cancel() const = 0; diff --git a/src/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc b/src/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc index a5471f7..c7e744a 100644 --- a/src/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc +++ b/src/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc @@ -5,8 +5,10 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/gesture_detection/mock_motion_event.h" #include "ui/events/gesture_detection/touch_disposition_gesture_filter.h" +#include "ui/events/test/mock_motion_event.h" + +using ui::test::MockMotionEvent; namespace ui { diff --git a/src/ui/events/gesture_detection/velocity_tracker_unittest.cc b/src/ui/events/gesture_detection/velocity_tracker_unittest.cc index eda1606..326c710 100644 --- a/src/ui/events/gesture_detection/velocity_tracker_unittest.cc +++ b/src/ui/events/gesture_detection/velocity_tracker_unittest.cc @@ -7,13 +7,14 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/gesture_detection/mock_motion_event.h" #include "ui/events/gesture_detection/velocity_tracker_state.h" +#include "ui/events/test/mock_motion_event.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/vector2d_f.h" using base::TimeDelta; using base::TimeTicks; +using ui::test::MockMotionEvent; namespace ui { namespace { diff --git a/src/ui/events/gestures/motion_event_aura.cc b/src/ui/events/gestures/motion_event_aura.cc index 2bf4e9b..6eea922 100644 --- a/src/ui/events/gestures/motion_event_aura.cc +++ b/src/ui/events/gestures/motion_event_aura.cc @@ -156,6 +156,16 @@ float MotionEventAura::GetHistoricalY(size_t pointer_index, return 0; } +MotionEvent::ToolType MotionEventAura::GetToolType(size_t pointer_index) const { + NOTIMPLEMENTED(); + return MotionEvent::TOOL_TYPE_UNKNOWN; +} + +int MotionEventAura::GetButtonState() const { + NOTIMPLEMENTED(); + return 0; +} + scoped_ptr MotionEventAura::Clone() const { return scoped_ptr(new MotionEventAura(pointer_count_, last_touch_time_, diff --git a/src/ui/events/gestures/motion_event_aura.h b/src/ui/events/gestures/motion_event_aura.h index 7ebf264..bf0a502 100644 --- a/src/ui/events/gestures/motion_event_aura.h +++ b/src/ui/events/gestures/motion_event_aura.h @@ -48,6 +48,8 @@ class EVENTS_EXPORT MotionEventAura : public MotionEvent { size_t historical_index) const OVERRIDE; virtual float GetHistoricalY(size_t pointer_index, size_t historical_index) const OVERRIDE; + virtual ToolType GetToolType(size_t pointer_index) const OVERRIDE; + virtual int GetButtonState() const OVERRIDE; virtual scoped_ptr Clone() const OVERRIDE; virtual scoped_ptr Cancel() const OVERRIDE; diff --git a/src/ui/events/gesture_detection/mock_motion_event.cc b/src/ui/events/test/mock_motion_event.cc similarity index 81% rename from src/ui/events/gesture_detection/mock_motion_event.cc rename to src/ui/events/test/mock_motion_event.cc index d6e0a91..98fceae 100644 --- a/src/ui/events/gesture_detection/mock_motion_event.cc +++ b/src/ui/events/test/mock_motion_event.cc @@ -2,20 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/events/gesture_detection/mock_motion_event.h" +#include "ui/events/test/mock_motion_event.h" #include "base/logging.h" using base::TimeTicks; namespace ui { +namespace test { MockMotionEvent::MockMotionEvent() - : action(ACTION_CANCEL), pointer_count(1), touch_major(TOUCH_MAJOR), id(0) { + : action(ACTION_CANCEL), pointer_count(1), touch_major(TOUCH_MAJOR), id(0), + button_state(0) { } MockMotionEvent::MockMotionEvent(Action action) - : action(action), pointer_count(1), touch_major(TOUCH_MAJOR), id(0) { + : action(action), pointer_count(1), touch_major(TOUCH_MAJOR), id(0), + button_state(0) { } MockMotionEvent::MockMotionEvent(Action action, @@ -26,8 +29,10 @@ MockMotionEvent::MockMotionEvent(Action action, pointer_count(1), time(time), touch_major(TOUCH_MAJOR), - id(0) { + id(0), + button_state(0) { points[0].SetPoint(x, y); + tool_types[0] = TOOL_TYPE_UNKNOWN; } MockMotionEvent::MockMotionEvent(Action action, @@ -40,9 +45,12 @@ MockMotionEvent::MockMotionEvent(Action action, pointer_count(2), time(time), touch_major(TOUCH_MAJOR), - id(0) { + id(0), + button_state(0) { points[0].SetPoint(x0, y0); + tool_types[0] = TOOL_TYPE_UNKNOWN; points[1].SetPoint(x1, y1); + tool_types[1] = TOOL_TYPE_UNKNOWN; } MockMotionEvent::MockMotionEvent(Action action, @@ -57,10 +65,14 @@ MockMotionEvent::MockMotionEvent(Action action, pointer_count(3), time(time), touch_major(TOUCH_MAJOR), - id(0) { + id(0), + button_state(0) { points[0].SetPoint(x0, y0); + tool_types[0] = TOOL_TYPE_UNKNOWN; points[1].SetPoint(x1, y1); + tool_types[1] = TOOL_TYPE_UNKNOWN; points[2].SetPoint(x2, y2); + tool_types[2] = TOOL_TYPE_UNKNOWN; } MockMotionEvent::MockMotionEvent(const MockMotionEvent& other) @@ -68,9 +80,12 @@ MockMotionEvent::MockMotionEvent(const MockMotionEvent& other) pointer_count(other.pointer_count), time(other.time), touch_major(other.touch_major), - id(other.GetId()) { - for (size_t i = 0; i < pointer_count; ++i) + id(other.GetId()), + button_state(other.GetButtonState()) { + for (size_t i = 0; i < pointer_count; ++i) { points[i] = other.points[i]; + tool_types[i] = other.tool_types[i]; + } } MockMotionEvent::~MockMotionEvent() {} @@ -140,6 +155,15 @@ float MockMotionEvent::GetHistoricalY(size_t pointer_index, return 0; } +MotionEvent::ToolType MockMotionEvent::GetToolType(size_t pointer_index) const { + DCHECK_LT(pointer_index, pointer_count); + return tool_types[pointer_index]; +} + +int MockMotionEvent::GetButtonState() const { + return button_state; +} + scoped_ptr MockMotionEvent::Clone() const { return scoped_ptr(new MockMotionEvent(*this)); } @@ -166,12 +190,14 @@ void MockMotionEvent::PressPoint(float x, float y) { DCHECK_LT(pointer_count, static_cast(MAX_POINTERS)); points[pointer_count++] = gfx::PointF(x, y); + tool_types[pointer_count] = TOOL_TYPE_UNKNOWN; action = pointer_count > 1 ? ACTION_POINTER_DOWN : ACTION_DOWN; } void MockMotionEvent::MovePoint(size_t index, float x, float y) { DCHECK_LT(index, pointer_count); points[index] = gfx::PointF(x, y); + tool_types[index] = TOOL_TYPE_UNKNOWN; action = ACTION_MOVE; } @@ -201,4 +227,14 @@ void MockMotionEvent::SetRawOffset(float raw_offset_x, float raw_offset_y) { raw_offset.set_y(raw_offset_y); } +void MockMotionEvent::SetToolType(size_t pointer_index, ToolType tool_type) { + DCHECK_LT(pointer_index, pointer_count); + tool_types[pointer_index] = tool_type; +} + +void MockMotionEvent::SetButtonState(int new_button_state) { + button_state = new_button_state; +} + +} // namespace test } // namespace ui diff --git a/src/ui/events/gesture_detection/mock_motion_event.h b/src/ui/events/test/mock_motion_event.h similarity index 91% rename from src/ui/events/gesture_detection/mock_motion_event.h rename to src/ui/events/test/mock_motion_event.h index 433de7b..f525810 100644 --- a/src/ui/events/gesture_detection/mock_motion_event.h +++ b/src/ui/events/test/mock_motion_event.h @@ -10,6 +10,7 @@ #include "ui/gfx/geometry/point_f.h" namespace ui { +namespace test { struct MockMotionEvent : public MotionEvent { enum { MAX_POINTERS = 3 }; @@ -36,6 +37,7 @@ struct MockMotionEvent : public MotionEvent { base::TimeTicks time, const std::vector& positions); MockMotionEvent(const MockMotionEvent& other); + virtual ~MockMotionEvent(); // MotionEvent methods. @@ -60,6 +62,8 @@ struct MockMotionEvent : public MotionEvent { size_t historical_index) const OVERRIDE; virtual float GetHistoricalY(size_t pointer_index, size_t historical_index) const OVERRIDE; + virtual ToolType GetToolType(size_t pointer_index) const OVERRIDE; + virtual int GetButtonState() const OVERRIDE; virtual scoped_ptr Clone() const OVERRIDE; virtual scoped_ptr Cancel() const OVERRIDE; @@ -73,14 +77,19 @@ struct MockMotionEvent : public MotionEvent { void CancelPoint(); void SetTouchMajor(float new_touch_major); void SetRawOffset(float raw_offset_x, float raw_offset_y); + void SetToolType(size_t index, ToolType tool_type); + void SetButtonState(int button_state); MotionEvent::Action action; size_t pointer_count; gfx::PointF points[MAX_POINTERS]; + ToolType tool_types[MAX_POINTERS]; gfx::Vector2dF raw_offset; base::TimeTicks time; float touch_major; int id; + int button_state; }; +} // namespace test } // namespace ui diff --git a/src/v8/src/mark-compact.cc b/src/v8/src/mark-compact.cc index df38d30..593ac99 100644 --- a/src/v8/src/mark-compact.cc +++ b/src/v8/src/mark-compact.cc @@ -2045,16 +2045,11 @@ int MarkCompactCollector::DiscoverAndPromoteBlackObjectsOnPage( static void DiscoverGreyObjectsInSpace(Heap* heap, MarkingDeque* marking_deque, PagedSpace* space) { - if (!space->was_swept_conservatively()) { - HeapObjectIterator it(space); - DiscoverGreyObjectsWithIterator(heap, marking_deque, &it); - } else { - PageIterator it(space); - while (it.has_next()) { - Page* p = it.next(); - DiscoverGreyObjectsOnPage(marking_deque, p); - if (marking_deque->IsFull()) return; - } + PageIterator it(space); + while (it.has_next()) { + Page* p = it.next(); + DiscoverGreyObjectsOnPage(marking_deque, p); + if (marking_deque->IsFull()) return; } } diff --git a/src/v8/src/objects.cc b/src/v8/src/objects.cc index 1965cc6..94fa5a4 100644 --- a/src/v8/src/objects.cc +++ b/src/v8/src/objects.cc @@ -6860,8 +6860,8 @@ bool JSObject::DefineFastAccessor(Handle object, ASSERT(target->NumberOfOwnDescriptors() == object->map()->NumberOfOwnDescriptors()); // This works since descriptors are sorted in order of addition. - ASSERT(object->map()->instance_descriptors()-> - GetKey(descriptor_number) == *name); + ASSERT(Name::Equals(handle(object->map()->instance_descriptors()-> + GetKey(descriptor_number)), name)); return TryAccessorTransition(object, target, descriptor_number, component, accessor, attributes); } diff --git a/src/v8/src/version.cc b/src/v8/src/version.cc index 1d8adfe..d6c5135 100644 --- a/src/v8/src/version.cc +++ b/src/v8/src/version.cc @@ -35,7 +35,7 @@ #define MAJOR_VERSION 3 #define MINOR_VERSION 27 #define BUILD_NUMBER 34 -#define PATCH_LEVEL 12 +#define PATCH_LEVEL 14 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) #define IS_CANDIDATE_VERSION 0 diff --git a/src/webkit/common/webpreferences.cc b/src/webkit/common/webpreferences.cc index a953f4a..a5d61b4 100644 --- a/src/webkit/common/webpreferences.cc +++ b/src/webkit/common/webpreferences.cc @@ -126,6 +126,7 @@ WebPreferences::WebPreferences() use_legacy_background_size_shorthand_behavior(false), wide_viewport_quirk(false), use_wide_viewport(true), + force_zero_layout_height(false), viewport_meta_layout_size_quirk(false), viewport_meta_merge_content_quirk(false), viewport_meta_non_user_scalable_quirk(false), diff --git a/src/webkit/common/webpreferences.h b/src/webkit/common/webpreferences.h index 241fde3..be6e501 100644 --- a/src/webkit/common/webpreferences.h +++ b/src/webkit/common/webpreferences.h @@ -172,6 +172,7 @@ struct WEBKIT_COMMON_EXPORT WebPreferences { bool use_legacy_background_size_shorthand_behavior; bool wide_viewport_quirk; bool use_wide_viewport; + bool force_zero_layout_height; bool viewport_meta_layout_size_quirk; bool viewport_meta_merge_content_quirk; bool viewport_meta_non_user_scalable_quirk; diff --git a/src/webkit/glue/resources/webkit_strings_sr.xtb b/src/webkit/glue/resources/webkit_strings_sr.xtb index 0938474..af51ed2 100644 --- a/src/webkit/glue/resources/webkit_strings_sr.xtb +++ b/src/webkit/glue/resources/webkit_strings_sr.xtb @@ -27,7 +27,7 @@ статус пређите на режим целог екрана преостало време -Учитавање... +Учитава се... аудио притисни мапа слике diff --git a/src/xwalk/DEPS.xwalk b/src/xwalk/DEPS.xwalk index 1e50bdb..65b6c59 100644 --- a/src/xwalk/DEPS.xwalk +++ b/src/xwalk/DEPS.xwalk @@ -17,9 +17,9 @@ # Edit these when rolling DEPS.xwalk. # ----------------------------------- -chromium_crosswalk_rev = 'f506465773c4515957798e38250a3a7becb2bea6' -blink_crosswalk_rev = 'ebedaf16c0976221debb8547c9a5fc0017998090' -v8_crosswalk_rev = '8ddfc6f1a103ddbe20e38afeb12c3e0666c8a361' +chromium_crosswalk_rev = 'b959b9627080362e119a6e4425c9c2b0e4f313b9' +blink_crosswalk_rev = '8971a658e086b47f630db86850014fef0d065f8f' +v8_crosswalk_rev = '33bed61998cd976161d9c239832e81699785191e' ozone_wayland_rev = '3372a0e23d925d5402eb16abbbe58dd82b583a5a' crosswalk_git = 'https://github.com/crosswalk-project' diff --git a/src/xwalk/VERSION b/src/xwalk/VERSION index 5fc5c3c..2bdd6d4 100644 --- a/src/xwalk/VERSION +++ b/src/xwalk/VERSION @@ -1,4 +1,4 @@ MAJOR=9 MINOR=37 -BUILD=195 +BUILD=197 PATCH=0 diff --git a/src/xwalk/application/browser/application.cc b/src/xwalk/application/browser/application.cc index 27e29f9..ee32215 100644 --- a/src/xwalk/application/browser/application.cc +++ b/src/xwalk/application/browser/application.cc @@ -58,6 +58,7 @@ Application::Application( runtime_context_(runtime_context), observer_(observer), entry_point_used_(Default), + remote_debugging_enabled_(false), weak_factory_(this) { DCHECK(runtime_context_); DCHECK(data_.get()); @@ -83,6 +84,8 @@ bool Application::Launch(const LaunchParams& launch_params) { if (!url.is_valid()) return false; + remote_debugging_enabled_ = launch_params.remote_debugging; + Runtime* runtime = Runtime::Create( runtime_context_, this, content::SiteInstance::CreateForURL(runtime_context_, url)); @@ -226,6 +229,7 @@ int Application::GetRenderProcessHostID() const { void Application::OnRuntimeAdded(Runtime* runtime) { DCHECK(runtime); + runtime->set_remote_debugging_enabled(remote_debugging_enabled_); runtimes_.insert(runtime); } diff --git a/src/xwalk/application/browser/application.h b/src/xwalk/application/browser/application.h index 97bc9fa..091652a 100644 --- a/src/xwalk/application/browser/application.h +++ b/src/xwalk/application/browser/application.h @@ -71,7 +71,8 @@ class Application : public Runtime::Observer, LaunchParams() : entry_points(Default), launcher_pid(0), - force_fullscreen(false) {} + force_fullscreen(false), + remote_debugging(false) {} LaunchEntryPoints entry_points; @@ -80,6 +81,7 @@ class Application : public Runtime::Observer, int32 launcher_pid; bool force_fullscreen; + bool remote_debugging; }; // Closes all the application's runtimes (application pages). @@ -180,6 +182,8 @@ class Application : public Runtime::Observer, StoredPermissionMap permission_map_; // Security policy. scoped_ptr security_policy_; + // Remote debugging enabled or not for this Application + bool remote_debugging_enabled_; // WeakPtrFactory should be always declared the last. base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(Application); diff --git a/src/xwalk/application/browser/application_system.cc b/src/xwalk/application/browser/application_system.cc index ab30ddc..603f938 100644 --- a/src/xwalk/application/browser/application_system.cc +++ b/src/xwalk/application/browser/application_system.cc @@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/file_util.h" #include "content/public/browser/render_process_host.h" +#include "content/public/common/content_switches.h" #include "net/base/filename_util.h" #include "xwalk/application/browser/application.h" #include "xwalk/application/browser/application_service.h" @@ -53,6 +54,8 @@ bool ApplicationSystem::LaunchWithCommandLineParam( const T& param, const base::CommandLine& cmd_line) { Application::LaunchParams launch_params; launch_params.force_fullscreen = cmd_line.HasSwitch(switches::kFullscreen); + launch_params.remote_debugging = + cmd_line.HasSwitch(switches::kRemoteDebuggingPort); return application_service_->Launch(param, launch_params); } @@ -75,6 +78,8 @@ bool ApplicationSystem::LaunchWithCommandLineParam( Application::LaunchParams launch_params; launch_params.force_fullscreen = cmd_line.HasSwitch(switches::kFullscreen); launch_params.entry_points = Application::StartURLKey; + launch_params.remote_debugging = + cmd_line.HasSwitch(switches::kRemoteDebuggingPort); return !!application_service_->Launch(application_data, launch_params); } diff --git a/src/xwalk/application/browser/linux/running_applications_manager.cc b/src/xwalk/application/browser/linux/running_applications_manager.cc index 09fd3b4..b020e31 100644 --- a/src/xwalk/application/browser/linux/running_applications_manager.cc +++ b/src/xwalk/application/browser/linux/running_applications_manager.cc @@ -139,10 +139,12 @@ void RunningApplicationsManager::OnLaunch( // We might want to pass key-value pairs if have more parameters in future. unsigned int launcher_pid; bool fullscreen; + bool remote_debugging; if (!reader.PopString(&app_id_or_url) || !reader.PopUint32(&launcher_pid) || - !reader.PopBool(&fullscreen)) { + !reader.PopBool(&fullscreen) || + !reader.PopBool(&remote_debugging)) { scoped_ptr response = CreateError(method_call, "Error parsing message. Missing arguments."); @@ -153,6 +155,7 @@ void RunningApplicationsManager::OnLaunch( Application::LaunchParams params; params.launcher_pid = launcher_pid; params.force_fullscreen = fullscreen; + params.remote_debugging = remote_debugging; Application* application; if (GURL(app_id_or_url).spec().empty()) { diff --git a/src/xwalk/application/common/installer/package_installer.cc b/src/xwalk/application/common/installer/package_installer.cc index 88d9aa7..244d09f 100644 --- a/src/xwalk/application/common/installer/package_installer.cc +++ b/src/xwalk/application/common/installer/package_installer.cc @@ -105,6 +105,8 @@ bool PackageInstaller::Install(const base::FilePath& path, std::string* id) { scoped_ptr package; if (!base::DirectoryExists(path)) { package = Package::Create(path); + if (!package->IsValid()) + return false; package->Extract(&unpacked_dir); app_id = package->Id(); } else { diff --git a/src/xwalk/application/common/installer/signature_data.h b/src/xwalk/application/common/installer/signature_data.h index 8f69b2e..19116c2 100644 --- a/src/xwalk/application/common/installer/signature_data.h +++ b/src/xwalk/application/common/installer/signature_data.h @@ -12,7 +12,6 @@ #include "base/files/file_path.h" #include "libxml/tree.h" #include "libxml/xpath.h" -#include "xwalk/application/common/signature_types.h" namespace xwalk { namespace application { @@ -90,14 +89,6 @@ class SignatureData { certificate_list_ = certificate_list; } - ReferenceHashMap& reference_hash_map() { - return reference_hash_map_; - } - - void set_reference_hash_map(const ReferenceHashMap& reference_hash_map) { - reference_hash_map_ = reference_hash_map; - } - bool isAuthorSignature() const { return signature_number_ == -1; } @@ -119,7 +110,6 @@ class SignatureData { std::string signature_method_; std::set reference_set_; std::list certificate_list_; - ReferenceHashMap reference_hash_map_; DISALLOW_COPY_AND_ASSIGN(SignatureData); }; diff --git a/src/xwalk/application/common/installer/signature_parser.cc b/src/xwalk/application/common/installer/signature_parser.cc index 3dc0586..a50b158 100644 --- a/src/xwalk/application/common/installer/signature_parser.cc +++ b/src/xwalk/application/common/installer/signature_parser.cc @@ -150,12 +150,9 @@ bool ParseSignedInfoElement( return false; } - std::string uri, transform_algorithm, digest_method, digest_value; - xmlNodePtr refer_node, transforms_node, transform_node, digest_method_node, - digest_value_node; - ReferenceData reference_data; + std::string uri; + xmlNodePtr refer_node; std::set reference_set; - ReferenceHashMap reference_hash_map; for (size_t i = 0; i < reference_vec.size(); ++i) { refer_node = reference_vec[i]; uri = GetAttribute(refer_node, kTokenURI); @@ -164,50 +161,8 @@ bool ParseSignedInfoElement( return false; } reference_set.insert(uri); - - // Parse - transforms_node = - GetFirstChild(refer_node, signature_ns, kTokenTransforms); - if (!transforms_node) { - transform_node = - GetFirstChild(transforms_node, signature_ns, kTokenTransform); - if (!transforms_node) { - reference_data.transform_algorithm = - GetAttribute(transform_node, kTokenAlgorithm); - } - } - - // Parse - digest_method_node = - GetFirstChild(refer_node, signature_ns, kTokenDigestMethod); - if (!digest_method_node) { - LOG(ERROR) << "Missing DigestMethod tag."; - return false; - } - reference_data.digest_method = - GetAttribute(digest_method_node, kTokenAlgorithm); - if (reference_data.digest_method.empty()) { - LOG(ERROR) << "Missing DigestMethod attribute."; - return false; - } - - // Parser - digest_value_node = - GetFirstChild(refer_node, signature_ns, kTokenDigestValue); - if (!digest_value_node) { - LOG(ERROR) << "Missing DigestValue tag."; - return false; - } - reference_data.digest_value = - XmlStringToStdString(xmlNodeGetContent(digest_value_node)); - if (reference_data.digest_value.empty()) { - LOG(ERROR) << "Missing DigestValue."; - return false; - } - reference_hash_map.insert(make_pair(uri, reference_data)); } data->set_reference_set(reference_set); - data->set_reference_hash_map(reference_hash_map); return true; } diff --git a/src/xwalk/application/common/installer/tizen/signature_validator.cc b/src/xwalk/application/common/installer/tizen/signature_validator.cc index 66b9f72..b04281e 100644 --- a/src/xwalk/application/common/installer/tizen/signature_validator.cc +++ b/src/xwalk/application/common/installer/tizen/signature_validator.cc @@ -4,13 +4,16 @@ #include "xwalk/application/common/installer/tizen/signature_validator.h" +#include #include #include "base/files/file_enumerator.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "libxml/tree.h" #include "libxml/parser.h" #include "libxml/xmlschemas.h" #include "third_party/re2/re2/re2.h" +#include "xwalk/application/common/installer/signature_data.h" #include "xwalk/application/common/installer/signature_parser.h" namespace { @@ -24,7 +27,7 @@ const char kTokenRoleDistributor[] = "http://www.w3.org/ns/widgets-digsig#role-distributor"; const char kTokenProfileURI[] = "http://www.w3.org/ns/widgets-digsig#profile"; -const char kSignatureSchemaPath[] = "/usr/share/xwalk/schema.xsd"; +const char kSignatureSchemaPath[] = "/usr/share/xwalk/signature_schema.xsd"; // A wrapper of LOG(ERROR) function, which is used as parameter of function // xmlSchemaSetValidErrors @@ -72,7 +75,7 @@ class SignatureFile { }; typedef std::set SignatureFileSet; -const SignatureFileSet& GetSignatureFiles(const base::FilePath& widget_path) { +const SignatureFileSet GetSignatureFiles(const base::FilePath& widget_path) { SignatureFileSet signature_set; std::string file_name; int number; @@ -183,7 +186,7 @@ bool CheckProfileURI(const xwalk::application::SignatureData& signature_data) { bool CheckReference( const xwalk::application::SignatureData& signature_data) { base::FilePath widget_path = signature_data.GetExtractedWidgetPath(); - int prefix_length = widget_path.value().length() + 1; + int prefix_length = widget_path.value().length(); std::string file_name; std::set reference_set = signature_data.reference_set(); base::FileEnumerator iter(widget_path, true, base::FileEnumerator::FILES); @@ -214,7 +217,7 @@ SignatureValidator::Status SignatureValidator::Check( LOG(INFO) << "Verifying widget signature file."; // Process every signature files (author and distributor) according to // http://www.w3.org/TR/widgets-digsig/#signature-verification. - SignatureFileSet signature_set = GetSignatureFiles(widget_path); + const SignatureFileSet& signature_set = GetSignatureFiles(widget_path); if (signature_set.empty()) { LOG(INFO) << "No signed signature in the package."; return UNTRUSTED; diff --git a/src/xwalk/application/common/installer/tizen/signature_validator.h b/src/xwalk/application/common/installer/tizen/signature_validator.h index ffb4584..abe0ca7 100644 --- a/src/xwalk/application/common/installer/tizen/signature_validator.h +++ b/src/xwalk/application/common/installer/tizen/signature_validator.h @@ -5,13 +5,7 @@ #ifndef XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_SIGNATURE_VALIDATOR_H_ #define XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_SIGNATURE_VALIDATOR_H_ -#include -#include - #include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "xwalk/application/common/installer/signature_data.h" -#include "xwalk/application/common/signature_types.h" namespace xwalk { namespace application { diff --git a/src/xwalk/application/common/signature_types.h b/src/xwalk/application/common/signature_types.h deleted file mode 100644 index c26d4f9..0000000 --- a/src/xwalk/application/common/signature_types.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2013 Intel Corporation. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef XWALK_APPLICATION_COMMON_SIGNATURE_TYPES_H_ -#define XWALK_APPLICATION_COMMON_SIGNATURE_TYPES_H_ - -#include -#include - -namespace xwalk { -namespace application { - -struct ReferenceData { - std::string transform_algorithm; - std::string digest_method; - std::string digest_value; -}; - -typedef std::map ReferenceHashMap; -} // namespace application -} // namespace xwalk - -#endif // XWALK_APPLICATION_COMMON_SIGNATURE_TYPES_H_ diff --git a/src/xwalk/application/tools/linux/xwalk_launcher_main.cc b/src/xwalk/application/tools/linux/xwalk_launcher_main.cc index 66c77cf..57816d2 100644 --- a/src/xwalk/application/tools/linux/xwalk_launcher_main.cc +++ b/src/xwalk/application/tools/linux/xwalk_launcher_main.cc @@ -41,6 +41,7 @@ static int g_argc; static char** g_argv; static gboolean query_running = FALSE; static gboolean fullscreen = FALSE; +static gboolean remote_debugging = FALSE; static gchar** cmd_appid_or_url; static GOptionEntry entries[] = { @@ -48,6 +49,8 @@ static GOptionEntry entries[] = { "Check whether the application is running", NULL }, { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen, "Run the application as fullscreen", NULL }, + { "debugging_port", 'd', 0, G_OPTION_ARG_NONE, &remote_debugging, + "Enable remote debugging for the application", NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &cmd_appid_or_url, "ID of the application to be launched or URL to open", NULL }, { NULL } @@ -172,7 +175,8 @@ static int query_application_running(const char* app_id) { } static void launch_application(const char* appid_or_url, - gboolean fullscreen) { + gboolean fullscreen, + gboolean remote_debugging) { ep_launcher = new XWalkExtensionProcessLauncher(); GError* error = NULL; g_signal_connect(g_running_apps_manager, "object-removed", @@ -192,7 +196,8 @@ static void launch_application(const char* appid_or_url, unsigned int launcher_pid = getpid(); GVariant* result = g_dbus_proxy_call_sync(running_proxy, "Launch", - g_variant_new("(sub)", appid_or_url, launcher_pid, fullscreen), + g_variant_new("(subb)", appid_or_url, launcher_pid, fullscreen, + remote_debugging), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (!result) { fprintf(stderr, "Couldn't call 'Launch' method: %s\n", error->message); @@ -304,7 +309,7 @@ int main(int argc, char** argv) { return query_application_running(appid_or_url); } - launch_application(appid_or_url, fullscreen); + launch_application(appid_or_url, fullscreen, remote_debugging); free(appid_or_url); return 0; } diff --git a/src/xwalk/application/tools/linux/xwalkctl_main.cc b/src/xwalk/application/tools/linux/xwalkctl_main.cc index be469ac..0c4c436 100644 --- a/src/xwalk/application/tools/linux/xwalkctl_main.cc +++ b/src/xwalk/application/tools/linux/xwalkctl_main.cc @@ -56,26 +56,6 @@ const dbus::ObjectPath kRunningManagerDBusPath("/running1"); } // namespace -static void TerminateIfRunning(const std::string& app_id) { - dbus::Bus::Options options; -#if defined(OS_TIZEN_MOBILE) - options.bus_type = dbus::Bus::CUSTOM_ADDRESS; - options.address.assign("unix:path=/run/user/app/dbus/user_bus_socket"); -#endif - scoped_refptr bus(new dbus::Bus(options)); - dbus::ObjectProxy* app_proxy = - bus->GetObjectProxy(xwalk_service_name, kRunningManagerDBusPath); - if (!app_proxy) - return; - - dbus::MethodCall method_call( - xwalk_running_manager_iface, "TerminateIfRunning"); - dbus::MessageWriter writer(&method_call); - writer.AppendString(app_id); - - app_proxy->CallMethodAndBlock(&method_call, 1000); -} - static bool enable_remote_debugging(gint debugging_port) { dbus::Bus::Options options; #if defined(OS_TIZEN_MOBILE) @@ -168,9 +148,6 @@ int main(int argc, char* argv[]) { success = installer->Update(app_id, path); } } else if (uninstall_appid) { -#if defined(SHARED_PROCESS_MODE) - TerminateIfRunning(uninstall_appid); -#endif success = installer->Uninstall(uninstall_appid); } else if (debugging_port >= 0) { #if defined(SHARED_PROCESS_MODE) diff --git a/src/xwalk/packaging/crosswalk.spec b/src/xwalk/packaging/crosswalk.spec index d84106c..6bd9331 100644 --- a/src/xwalk/packaging/crosswalk.spec +++ b/src/xwalk/packaging/crosswalk.spec @@ -16,7 +16,7 @@ %endif Name: crosswalk -Version: 9.37.195.0 +Version: 9.37.197.0 Release: 0 Summary: Crosswalk is an app runtime based on Chromium License: (BSD-3-Clause and LGPL-2.1+) @@ -176,11 +176,6 @@ GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Ddisable_nacl=%{_disable_nacl}" GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Ddisable_fatal_linker_warnings=1" %endif -# Temporarily disable Alsa support while snd_seq_* support is not enabled on -# Tizen. See https://codereview.chromium.org/264973012 and -# https://review.tizen.org/gerrit/#/c/24336/ -GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_alsa=0" - # Temporarily disable WebRTC support because its build currently hardcodes # dependencies on X11 and OpenSSL. We are still trying to get some # clarifications as to whether this is really necessary. See XWALK-2160. diff --git a/src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkContent.java b/src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkContent.java index 41ce248..6f44052 100644 --- a/src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkContent.java +++ b/src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkContent.java @@ -10,7 +10,11 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Rect; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.view.View; +import android.view.WindowManager; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -468,7 +472,20 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa @CalledByNative public void onGetFullscreenFlagFromManifest(boolean enterFullscreen) { - if (enterFullscreen) mContentsClientBridge.onToggleFullscreen(true); + if (enterFullscreen) { + if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { + View decorView = mXWalkView.getActivity().getWindow().getDecorView(); + decorView.setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } else { + mXWalkView.getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + } } public void destroy() { diff --git a/src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkViewInternal.java b/src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkViewInternal.java index 2a44fb5..dad18a3 100644 --- a/src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkViewInternal.java +++ b/src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkViewInternal.java @@ -747,6 +747,7 @@ public class XWalkViewInternal extends android.widget.FrameLayout { * * @hide */ + @XWalkAPI public void setNetworkAvailable(boolean networkUp) { if (mContent == null) return; checkThreadSafety(); diff --git a/src/xwalk/runtime/app/xwalk_main_delegate.cc b/src/xwalk/runtime/app/xwalk_main_delegate.cc index 5a5646a..0d07705 100644 --- a/src/xwalk/runtime/app/xwalk_main_delegate.cc +++ b/src/xwalk/runtime/app/xwalk_main_delegate.cc @@ -73,7 +73,7 @@ int XWalkMainDelegate::RunProcess(const std::string& process_type, return -1; } -#if defined(OS_POSIX) && !defined(OS_ANDROID) +#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX) void XWalkMainDelegate::ZygoteStarting( ScopedVector* delegates) { #if !defined(DISABLE_NACL) diff --git a/src/xwalk/runtime/app/xwalk_main_delegate.h b/src/xwalk/runtime/app/xwalk_main_delegate.h index fea8351..268ad65 100644 --- a/src/xwalk/runtime/app/xwalk_main_delegate.h +++ b/src/xwalk/runtime/app/xwalk_main_delegate.h @@ -26,7 +26,7 @@ class XWalkMainDelegate : public content::ContentMainDelegate { virtual void PreSandboxStartup() OVERRIDE; virtual int RunProcess(const std::string& process_type, const content::MainFunctionParams& main_function_params) OVERRIDE; -#if defined(OS_POSIX) && !defined(OS_ANDROID) +#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX) virtual void ZygoteStarting( ScopedVector* delegates) OVERRIDE; #endif diff --git a/src/xwalk/runtime/browser/devtools/xwalk_devtools_delegate.cc b/src/xwalk/runtime/browser/devtools/xwalk_devtools_delegate.cc index 328a2a9..a1aa64a 100644 --- a/src/xwalk/runtime/browser/devtools/xwalk_devtools_delegate.cc +++ b/src/xwalk/runtime/browser/devtools/xwalk_devtools_delegate.cc @@ -135,8 +135,12 @@ void XWalkDevToolsDelegate::EnumerateTargets(TargetCallback callback) { for (std::vector::iterator it = rvh_list.begin(); it != rvh_list.end(); ++it) { WebContents* web_contents = WebContents::FromRenderViewHost(*it); - if (web_contents) - targets.push_back(new Target(web_contents)); + if (web_contents) { + Runtime* runtime = static_cast(web_contents->GetDelegate()); + if (runtime && runtime->remote_debugging_enabled()) { + targets.push_back(new Target(web_contents)); + } + } } callback.Run(targets); } diff --git a/src/xwalk/runtime/browser/runtime.cc b/src/xwalk/runtime/browser/runtime.cc index 929a474..4f8f9ba 100644 --- a/src/xwalk/runtime/browser/runtime.cc +++ b/src/xwalk/runtime/browser/runtime.cc @@ -74,6 +74,7 @@ Runtime::Runtime(content::WebContents* web_contents, Observer* observer) window_(NULL), weak_ptr_factory_(this), fullscreen_options_(NO_FULLSCREEN), + remote_debugging_enabled_(false), observer_(observer) { web_contents_->SetDelegate(this); content::NotificationService::current()->Notify( diff --git a/src/xwalk/runtime/browser/runtime.h b/src/xwalk/runtime/browser/runtime.h index 51be3f3..5b48ab5 100644 --- a/src/xwalk/runtime/browser/runtime.h +++ b/src/xwalk/runtime/browser/runtime.h @@ -78,6 +78,11 @@ class Runtime : public content::WebContentsDelegate, content::RenderProcessHost* GetRenderProcessHost(); + void set_remote_debugging_enabled(bool enable) { + remote_debugging_enabled_ = enable; + } + bool remote_debugging_enabled() const { return remote_debugging_enabled_; } + #if defined(OS_TIZEN_MOBILE) void CloseRootWindow(); #endif @@ -188,6 +193,7 @@ class Runtime : public content::WebContentsDelegate, }; unsigned int fullscreen_options_; + bool remote_debugging_enabled_; Observer* observer_; }; diff --git a/src/xwalk/runtime/browser/ui/native_app_window_tizen.h b/src/xwalk/runtime/browser/ui/native_app_window_tizen.h index 8f2ed01..450063c 100644 --- a/src/xwalk/runtime/browser/ui/native_app_window_tizen.h +++ b/src/xwalk/runtime/browser/ui/native_app_window_tizen.h @@ -6,13 +6,13 @@ #define XWALK_RUNTIME_BROWSER_UI_NATIVE_APP_WINDOW_TIZEN_H_ #include "base/memory/scoped_ptr.h" -#include "content/browser/screen_orientation/screen_orientation_provider.h" +#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h" +#include "ui/aura/window_observer.h" #include "xwalk/runtime/browser/ui/screen_orientation.h" #include "xwalk/runtime/browser/ui/native_app_window_views.h" #include "xwalk/tizen/mobile/sensor/sensor_provider.h" #include "xwalk/tizen/mobile/ui/tizen_system_indicator_widget.h" #include "xwalk/tizen/mobile/ui/widget_container_view.h" -#include "ui/aura/window_observer.h" namespace xwalk { diff --git a/src/xwalk/sysapps/raw_socket/udp_socket_object.cc b/src/xwalk/sysapps/raw_socket/udp_socket_object.cc index bcbeb6f..47ce92e 100644 --- a/src/xwalk/sysapps/raw_socket/udp_socket_object.cc +++ b/src/xwalk/sysapps/raw_socket/udp_socket_object.cc @@ -26,9 +26,9 @@ UDPSocketObject::UDPSocketObject() : has_write_pending_(false), is_suspended_(false), is_reading_(false), - resolver_(net::HostResolver::CreateDefaultResolver(NULL)), read_buffer_(new net::IOBuffer(kBufferSize)), write_buffer_(new net::IOBuffer(kBufferSize)), + resolver_(net::HostResolver::CreateDefaultResolver(NULL)), single_resolver_(new net::SingleRequestHostResolver(resolver_.get())) { handler_.Register("init", base::Bind(&UDPSocketObject::OnInit, base::Unretained(this))); diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/EnterAndLeaveFullscreenTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/EnterAndLeaveFullscreenTest.java new file mode 100644 index 0000000..c2c5a18 --- /dev/null +++ b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/EnterAndLeaveFullscreenTest.java @@ -0,0 +1,48 @@ +// Copyright (c) 2014 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.xwalk.core.xwview.test; + +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.base.test.util.Feature; + + +/** + * Tests for the hasEnteredFullscreen() and leaveFullscreen() method. + */ +public class EnterAndLeaveFullscreenTest extends XWalkViewTestBase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @SmallTest + @Feature({"XWalkView", "Fullscreen"}) + public void testEnterAndExitFullscreen() throws Throwable { + final String name = "fullscreen_enter_exit.html"; + String fileContent = getFileContent(name); + + loadDataSync(name, fileContent, "text/html", false); + + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + try { + clickOnElementId("enter_fullscreen"); + assertTrue(getXWalkView().hasEnteredFullscreen()); + getXWalkView().leaveFullscreen(); + assertFalse(getXWalkView().hasEnteredFullscreen()); + + clickOnElementId("enter_fullscreen"); + clickOnElementId("exit_fullscreen"); + assertFalse(getXWalkView().hasEnteredFullscreen()); + } catch (Throwable e) { + e.printStackTrace(); + } + } + }); + } +} diff --git a/src/xwalk/test/android/data/fullscreen_enter_exit.html b/src/xwalk/test/android/data/fullscreen_enter_exit.html new file mode 100644 index 0000000..fec6e3e --- /dev/null +++ b/src/xwalk/test/android/data/fullscreen_enter_exit.html @@ -0,0 +1,19 @@ + + + + + +
+ + +
+ + diff --git a/src/xwalk/xwalk_android_tests.gypi b/src/xwalk/xwalk_android_tests.gypi index d71a9e7..ee43528 100644 --- a/src/xwalk/xwalk_android_tests.gypi +++ b/src/xwalk/xwalk_android_tests.gypi @@ -114,6 +114,7 @@ '<(PRODUCT_DIR)/xwalk_internal_xwview_test/assets/echo.html', '<(PRODUCT_DIR)/xwalk_internal_xwview_test/assets/echoSync.html', '<(PRODUCT_DIR)/xwalk_internal_xwview_test/assets/framesEcho.html', + '<(PRODUCT_DIR)/xwalk_xwview_test/assets/fullscreen_enter_exit.html', '<(PRODUCT_DIR)/xwalk_xwview_test/assets/index.html', '<(PRODUCT_DIR)/xwalk_xwview_test/assets/scale_changed.html', '<(PRODUCT_DIR)/xwalk_xwview_test/assets/window.close.html', @@ -128,6 +129,7 @@ 'test/android/data/echo.html', 'test/android/data/echoSync.html', 'test/android/data/framesEcho.html', + 'test/android/data/fullscreen_enter_exit.html', 'test/android/data/index.html', 'test/android/data/scale_changed.html', 'test/android/data/window.close.html', -- 2.7.4