Upstream version 9.37.197.0 90/27090/1
authorEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Thu, 4 Sep 2014 09:27:37 +0000 (09:27 +0000)
committerEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Thu, 4 Sep 2014 09:27:37 +0000 (09:27 +0000)
Upstream commit-id 9b0155ddca7fd02ab92817b9537eca761789f7ab

Change-Id: Ic59b134814a319519a26394b68308f519c5f4fc3
Signed-off-by: Eurogiciel-BOT <eurogiciel.tizen@gmail.com>
273 files changed:
packaging/crosswalk.spec
src/.DEPS.git
src/DEPS
src/android_webview/DEPS
src/android_webview/android_webview.gyp
src/android_webview/android_webview_tests.gypi
src/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
src/android_webview/browser/renderer_host/aw_render_view_host_ext.h
src/android_webview/common/render_view_messages.h
src/android_webview/java/src/org/chromium/android_webview/AwAssets.java [new file with mode: 0644]
src/android_webview/java/src/org/chromium/android_webview/AwContents.java
src/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
src/android_webview/java/src/org/chromium/android_webview/AwSettings.java
src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
src/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
src/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
src/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java
src/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
src/android_webview/lib/main/aw_main_delegate.cc
src/android_webview/native/DEPS
src/android_webview/native/android_webview_jni_registrar.cc
src/android_webview/native/aw_assets.cc [new file with mode: 0644]
src/android_webview/native/aw_assets.h [new file with mode: 0644]
src/android_webview/native/aw_contents.cc
src/android_webview/native/aw_contents.h
src/android_webview/native/aw_media_url_interceptor.cc [new file with mode: 0644]
src/android_webview/native/aw_media_url_interceptor.h [new file with mode: 0644]
src/android_webview/native/aw_media_url_interceptor_unittest.cc [new file with mode: 0644]
src/android_webview/native/aw_settings.cc
src/android_webview/native/aw_web_contents_delegate.cc
src/android_webview/native/webview_native.gyp
src/android_webview/renderer/aw_render_view_ext.cc
src/android_webview/renderer/aw_render_view_ext.h
src/android_webview/test/unittest/assets/asset_file.ogg [new file with mode: 0644]
src/ash/strings/ash_strings_ar.xtb
src/ash/strings/ash_strings_fil.xtb
src/ash/strings/ash_strings_fr.xtb
src/ash/strings/ash_strings_gu.xtb
src/ash/strings/ash_strings_hr.xtb
src/ash/strings/ash_strings_id.xtb
src/ash/strings/ash_strings_it.xtb
src/ash/strings/ash_strings_iw.xtb
src/ash/strings/ash_strings_kn.xtb
src/ash/strings/ash_strings_ko.xtb
src/ash/strings/ash_strings_nl.xtb
src/ash/wm/toplevel_window_event_handler.cc
src/ash/wm/toplevel_window_event_handler_unittest.cc
src/base/android/java/src/org/chromium/base/ContentUriUtils.java
src/base/android/jni_array.cc
src/base/android/jni_array.h
src/base/win/iat_patch_function.cc
src/base/win/iat_patch_function.h
src/chrome/VERSION
src/chrome/android/java/res/drawable-hdpi/pageinfo_bad.png
src/chrome/android/java/res/drawable-hdpi/pageinfo_enterprise_managed.png
src/chrome/android/java/res/drawable-hdpi/pageinfo_good.png
src/chrome/android/java/res/drawable-hdpi/pageinfo_info.png
src/chrome/android/java/res/drawable-hdpi/pageinfo_warning_minor.png
src/chrome/android/java/res/drawable-ldrtl-sw600dp-hdpi/edge_menu_bg.9.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-ldrtl-sw600dp-mdpi/edge_menu_bg.9.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi/edge_menu_bg.9.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-ldrtl-sw600dp-xxhdpi/edge_menu_bg.9.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-mdpi/pageinfo_bad.png
src/chrome/android/java/res/drawable-mdpi/pageinfo_enterprise_managed.png
src/chrome/android/java/res/drawable-mdpi/pageinfo_good.png
src/chrome/android/java/res/drawable-mdpi/pageinfo_info.png
src/chrome/android/java/res/drawable-mdpi/pageinfo_warning_minor.png
src/chrome/android/java/res/drawable-sw600dp-hdpi/edge_menu_bg.9.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-sw600dp-mdpi/edge_menu_bg.9.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-sw600dp-xhdpi/edge_menu_bg.9.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-sw600dp-xxhdpi/edge_menu_bg.9.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-xhdpi/pageinfo_bad.png
src/chrome/android/java/res/drawable-xhdpi/pageinfo_enterprise_managed.png
src/chrome/android/java/res/drawable-xhdpi/pageinfo_good.png
src/chrome/android/java/res/drawable-xhdpi/pageinfo_info.png
src/chrome/android/java/res/drawable-xhdpi/pageinfo_warning_minor.png
src/chrome/android/java/res/drawable-xxhdpi/pageinfo_bad.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-xxhdpi/pageinfo_good.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-xxhdpi/pageinfo_info.png [new file with mode: 0644]
src/chrome/android/java/res/drawable-xxhdpi/pageinfo_warning_minor.png [new file with mode: 0644]
src/chrome/android/java/res/layout/website_settings.xml
src/chrome/android/java/res/values-sw600dp/dimens.xml [new file with mode: 0644]
src/chrome/android/java/res/values/colors.xml
src/chrome/android/java/res/values/dimens.xml
src/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java
src/chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java
src/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java
src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java
src/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuButtonHelper.java
src/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java [new file with mode: 0644]
src/chrome/android/shell/java/AndroidManifest.xml
src/chrome/app/resources/generated_resources_ar.xtb
src/chrome/app/resources/generated_resources_fil.xtb
src/chrome/app/resources/generated_resources_fr.xtb
src/chrome/app/resources/generated_resources_gu.xtb
src/chrome/app/resources/generated_resources_hr.xtb
src/chrome/app/resources/generated_resources_id.xtb
src/chrome/app/resources/generated_resources_it.xtb
src/chrome/app/resources/generated_resources_iw.xtb
src/chrome/app/resources/generated_resources_kn.xtb
src/chrome/app/resources/generated_resources_ko.xtb
src/chrome/app/resources/generated_resources_nl.xtb
src/chrome/app/resources/generated_resources_sr.xtb
src/chrome/app/resources/generated_resources_ta.xtb
src/chrome/app/resources/generated_resources_zh-TW.xtb
src/chrome/browser/android/most_visited_sites.cc
src/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
src/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
src/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
src/chrome/browser/chromeos/input_method/input_method_engine.cc
src/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
src/chrome/browser/chromeos/login/ui/user_adding_screen.cc
src/chrome/browser/extensions/api/system_cpu/cpu_info_provider_linux.cc
src/chrome/browser/extensions/webstore_data_fetcher.cc
src/chrome/browser/extensions/webstore_data_fetcher.h
src/chrome/browser/history/in_memory_url_index.cc
src/chrome/browser/history/in_memory_url_index.h
src/chrome/browser/profiles/profile_info_cache.cc
src/chrome/browser/profiles/profile_info_cache_unittest.cc
src/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher.js
src/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.css
src/chrome/browser/resources/hotword_helper/manifest.json
src/chrome/browser/supervised_user/supervised_user_service.cc
src/chrome/browser/supervised_user/supervised_user_service.h
src/chrome/browser/ui/android/website_settings_popup_android.cc
src/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
src/chrome/browser/ui/views/tabs/tab.cc
src/chrome/browser/ui/views/tabs/window_finder_ash.cc
src/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc
src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc
src/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h
src/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
src/chrome/third_party/chromevox/chromeVoxChromeBackgroundScript.js
src/chrome/third_party/chromevox/chromeVoxChromeOptionsScript.js
src/chrome/third_party/chromevox/chromeVoxChromePageScript.js
src/chrome_elf/blacklist/blacklist.cc
src/components/policy/resources/policy_templates_fa.xtb
src/components/policy/resources/policy_templates_id.xtb
src/components/strings/components_strings_sr.xtb
src/content/browser/android/content_view_core_impl.cc
src/content/browser/android/content_view_core_impl.h
src/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
src/content/browser/media/android/browser_media_player_manager.cc
src/content/browser/media/android/browser_media_player_manager.h
src/content/browser/media/android/media_resource_getter_impl.cc
src/content/browser/media/android/media_resource_getter_impl.h
src/content/browser/renderer_host/input/gesture_text_selector.cc [new file with mode: 0644]
src/content/browser/renderer_host/input/gesture_text_selector.h [new file with mode: 0644]
src/content/browser/renderer_host/input/gesture_text_selector_unittest.cc [new file with mode: 0644]
src/content/browser/renderer_host/input/motion_event_android.cc
src/content/browser/renderer_host/input/motion_event_android.h
src/content/browser/renderer_host/input/motion_event_web.cc
src/content/browser/renderer_host/input/motion_event_web.h
src/content/browser/renderer_host/render_widget_host_impl.cc
src/content/browser/renderer_host/render_widget_host_impl.h
src/content/browser/renderer_host/render_widget_host_view_android.cc
src/content/browser/renderer_host/render_widget_host_view_android.h
src/content/browser/web_contents/web_contents_android.cc
src/content/browser/web_contents/web_contents_android.h
src/content/common/media/media_player_messages_android.h
src/content/common/view_messages.h
src/content/content_browser.gypi
src/content/content_renderer.gypi
src/content/content_tests.gypi
src/content/public/OWNERS [new file with mode: 0644]
src/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png
src/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png
src/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png
src/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png [new file with mode: 0644]
src/content/public/android/java/src/org/chromium/content/browser/ContentView.java
src/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
src/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java
src/content/public/android/java/src/org/chromium/content/browser/SmartClipProvider.java [new file with mode: 0644]
src/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
src/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
src/content/public/android/javatests/src/org/chromium/content/browser/MediaResourceGetterTest.java
src/content/public/common/common_param_traits_macros.h
src/content/renderer/OWNERS
src/content/renderer/media/android/media_info_loader.cc
src/content/renderer/media/android/media_info_loader.h
src/content/renderer/media/android/media_info_loader_unittest.cc
src/content/renderer/media/android/renderer_media_player_manager.cc
src/content/renderer/media/android/renderer_media_player_manager.h
src/content/renderer/media/android/webmediaplayer_android.cc
src/content/renderer/media/android/webmediaplayer_android.h
src/content/renderer/render_font_warmup_win.cc [new file with mode: 0644]
src/content/renderer/render_view_impl_android.cc
src/content/renderer/renderer_font_platform_win.cc [new file with mode: 0644]
src/content/renderer/renderer_font_platform_win.h [new file with mode: 0644]
src/content/shell/android/shell_apk/AndroidManifest.xml
src/google_apis/gcm/engine/gcm_store_impl.cc
src/google_apis/gcm/engine/gcm_store_impl_unittest.cc
src/gpu/command_buffer/service/gles2_cmd_decoder.cc
src/gpu/config/gpu_driver_bug_list_json.cc
src/media/audio/pulse/pulse_output.cc
src/media/audio/pulse/pulse_util.cc
src/media/audio/win/audio_device_listener_win.cc
src/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java
src/media/base/android/media_player_bridge.cc
src/media/base/android/media_player_bridge.h
src/media/base/android/media_player_manager.h
src/media/base/android/media_resource_getter.h
src/media/base/android/media_source_player_unittest.cc
src/media/base/android/media_url_interceptor.h [new file with mode: 0644]
src/media/filters/ffmpeg_demuxer.cc
src/media/filters/ffmpeg_demuxer.h
src/media/media.gyp
src/net/android/java/src/org/chromium/net/ProxyChangeListener.java
src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash-expected.txt [new file with mode: 0644]
src/third_party/WebKit/LayoutTests/fast/css/remove-pending-sheet-html-import-crash.html [new file with mode: 0644]
src/third_party/WebKit/LayoutTests/fast/css/resources/import-layout-with-pending-sheet.html [new file with mode: 0644]
src/third_party/WebKit/Source/core/dom/Document.cpp
src/third_party/WebKit/Source/core/frame/Settings.in
src/third_party/WebKit/Source/core/frame/SmartClip.cpp
src/third_party/WebKit/Source/core/frame/SmartClip.h
src/third_party/WebKit/Source/web/WebLocalFrameImpl.h
src/third_party/WebKit/Source/web/WebSettingsImpl.cpp
src/third_party/WebKit/Source/web/WebSettingsImpl.h
src/third_party/WebKit/Source/web/WebViewImpl.cpp
src/third_party/WebKit/Source/web/WebViewImpl.h
src/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
src/third_party/WebKit/Source/web/tests/WebViewTest.cpp
src/third_party/WebKit/public/web/WebSettings.h
src/third_party/WebKit/public/web/WebView.h
src/third_party/angle/src/compiler/translator/OutputHLSL.cpp
src/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
src/ui/aura/window_event_dispatcher.cc
src/ui/aura/window_event_dispatcher_unittest.cc
src/ui/base/ime/chromeos/ime_keymap.cc
src/ui/base/ime/chromeos/ime_keymap.h
src/ui/events/BUILD.gn
src/ui/events/events.gyp
src/ui/events/gesture_detection/gesture_provider_unittest.cc
src/ui/events/gesture_detection/motion_event.h
src/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
src/ui/events/gesture_detection/velocity_tracker_unittest.cc
src/ui/events/gestures/motion_event_aura.cc
src/ui/events/gestures/motion_event_aura.h
src/ui/events/test/mock_motion_event.cc [moved from src/ui/events/gesture_detection/mock_motion_event.cc with 81% similarity]
src/ui/events/test/mock_motion_event.h [moved from src/ui/events/gesture_detection/mock_motion_event.h with 91% similarity]
src/v8/src/mark-compact.cc
src/v8/src/objects.cc
src/v8/src/version.cc
src/webkit/common/webpreferences.cc
src/webkit/common/webpreferences.h
src/webkit/glue/resources/webkit_strings_sr.xtb
src/xwalk/DEPS.xwalk
src/xwalk/VERSION
src/xwalk/application/browser/application.cc
src/xwalk/application/browser/application.h
src/xwalk/application/browser/application_system.cc
src/xwalk/application/browser/linux/running_applications_manager.cc
src/xwalk/application/common/installer/package_installer.cc
src/xwalk/application/common/installer/signature_data.h
src/xwalk/application/common/installer/signature_parser.cc
src/xwalk/application/common/installer/tizen/signature_validator.cc
src/xwalk/application/common/installer/tizen/signature_validator.h
src/xwalk/application/common/signature_types.h [deleted file]
src/xwalk/application/tools/linux/xwalk_launcher_main.cc
src/xwalk/application/tools/linux/xwalkctl_main.cc
src/xwalk/packaging/crosswalk.spec
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkContent.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkViewInternal.java
src/xwalk/runtime/app/xwalk_main_delegate.cc
src/xwalk/runtime/app/xwalk_main_delegate.h
src/xwalk/runtime/browser/devtools/xwalk_devtools_delegate.cc
src/xwalk/runtime/browser/runtime.cc
src/xwalk/runtime/browser/runtime.h
src/xwalk/runtime/browser/ui/native_app_window_tizen.h
src/xwalk/sysapps/raw_socket/udp_socket_object.cc
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/EnterAndLeaveFullscreenTest.java [new file with mode: 0644]
src/xwalk/test/android/data/fullscreen_enter_exit.html [new file with mode: 0644]
src/xwalk/xwalk_android_tests.gypi

index d84106c..6bd9331 100644 (file)
@@ -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.
index ce27c26..25bbc01 100644 (file)
@@ -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 = {
index 2252ce4..14f8f5b 100644 (file)
--- a/src/DEPS
+++ b/src/DEPS
@@ -185,7 +185,7 @@ deps_os = {
     'src/third_party/WebKit/LayoutTests/w3c/web-platform-tests': None,\r
     'src/chrome/test/data/extensions/api_test/permissions/nacl_enabled/bin': None,\r
     'src/third_party/WebKit/public':\r
-      (Var("blink")) + '/branches/chromium/2062/public@180122',\r
+      (Var("blink")) + '/branches/chromium/2062/public@180557',\r
     'src/native_client': None,\r
     'src/tools/page_cycler/acid3': None,\r
     'src/testing/iossim/third_party/class-dump':\r
@@ -281,7 +281,7 @@ deps = {
   'src/third_party/libwebm/source':\r
     (Var("git.chromium.org")) + '/webm/libwebm.git@8be63972fdd7ae8c041778f8ba674ade903395c9',\r
   'src/third_party/WebKit':\r
-    (Var("blink")) + '/branches/chromium/2062@180122',\r
+    (Var("blink")) + '/branches/chromium/2062@180557',\r
   'src/third_party/openmax_dl':\r
     (Var("webrtc")) + '/deps/third_party/openmax@6483',\r
   'src/third_party/libc++abi/trunk':\r
@@ -345,7 +345,7 @@ deps = {
   'src/sdch/open-vcdiff':\r
     (Var("open-vcdiff")) + '/trunk@42',\r
   'src/third_party/angle':\r
-    (Var("git.chromium.org")) + '/angle/angle.git@75551cf9a7c65bcdb9f9fe44ac78ca15da37942e',\r
+    (Var("git.chromium.org")) + '/angle/angle.git@f4126d2b9eb008d4e792fff2592f338e19c68569',\r
   'build/third_party/lighttpd':\r
     '/trunk/deps/third_party/lighttpd@58968',\r
   'src/buildtools':\r
@@ -419,7 +419,7 @@ deps = {
   'src/third_party/libsrtp':\r
     '/trunk/deps/third_party/libsrtp@261337',\r
   'src/v8':\r
-    (Var("v8")) + '/branches/3.27@22914',\r
+    (Var("v8")) + '/branches/3.27@23158',\r
   'src/third_party/pywebsocket/src':\r
     (Var("pywebsocket")) + '/trunk/src@790',\r
   'src/third_party/libvpx':\r
index 91ac0f5..fe7f839 100644 (file)
@@ -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",
index 2efc46c..1a04365 100644 (file)
@@ -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',
           'includes': [ '../build/java.gypi' ],
         },
       ],
-     }, { # android_webview_build==1
+     }, {  # android_webview_build==1
       'targets': [
         {
           'target_name': 'android_webview_jarjar_ui_resources',
index 390732a..1639e60 100644 (file)
         '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',
       ],
       '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' ],
     },
   ],
index 787a647..676616a 100644 (file)
@@ -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()));
index f56d0a6..773e504 100644 (file)
@@ -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
index 0b8f315..7592fb7 100644 (file)
@@ -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 (file)
index 0000000..97e292f
--- /dev/null
@@ -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};
+        }
+    }
+}
index 79f919f..3745228 100644 (file)
@@ -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);
index 3789dc7..6957a97 100644 (file)
@@ -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
-        //   <div style="height:150%">a</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 <div style="height:120%">
-        // 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());
     }
 }
index 587ca48..76f6adb 100644 (file)
@@ -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);
index bdc5637..bf707eb 100644 (file)
@@ -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);
 }
index 2edef84..96e3b5d 100644 (file)
@@ -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<Void, Void, String[]> {
+        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);
+        }
+    }
 }
index 3ada155..9776f10 100644 (file)
@@ -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);
index 4ef786b..18e06eb 100644 (file)
@@ -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);
     }
 }
index d6ac546..2cadb07 100644 (file)
@@ -1355,6 +1355,127 @@ public class AwSettingsTest extends AwTestBase {
         private int mOnScaleChangedCallCount;
     }
 
+    class AwSettingsForceZeroLayoutHeightTestHelper extends AwSettingsTestHelper<Boolean> {
+
+        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 "<html><head>" +
+                    (mWithViewPortTag ? "<meta name='viewport' content='height=3000' />" : "") +
+                    "  <script type='text/javascript'> " +
+                    "    window.addEventListener('load', function(event) { " +
+                    "       document.title = document.getElementById('testDiv').clientHeight; " +
+                    "    }); " +
+                    "  </script> " +
+                    "</head>" +
+                    "<body> " +
+                    "  <div style='height:50px;'>test</div> " +
+                    "  <div id='testDiv' style='height:100%;'></div> " +
+                    "</body></html>";
+        }
+
+        private final boolean mWithViewPortTag;
+    }
+
+    class AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper extends
+            AwSettingsTestHelper<Boolean> {
+
+        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 "<html><head>" +
+                    "<meta name='viewport' content='width=3000' />" +
+                    "  <script type='text/javascript'> " +
+                    "    window.addEventListener('load', function(event) { " +
+                    "       document.title = document.documentElement.clientWidth; " +
+                    "    }); " +
+                    "  </script> " +
+                    "</head>" +
+                    "<body> " +
+                    "  <div style='height:50px;'>test</div> " +
+                    "  <div id='testDiv' style='height:100%;'></div> " +
+                    "</body></html>";
+        }
+    }
+
     // 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(
index 1102806..1ad7934 100644 (file)
@@ -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);
index ecc29cb..c3bef64 100644 (file)
@@ -1,6 +1,7 @@
 include_rules = [
   "+content/public/browser",
   "+content/public/test",
+  "+media/base/android",
   "+ui/gfx",
   "+ui/shell_dialogs",
 
index 8db9713..253a070 100644 (file)
@@ -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 (file)
index 0000000..6d5ad72
--- /dev/null
@@ -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 <jni.h>
+
+#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<jlongArray> jarr = Java_AwAssets_openAsset(
+      env,
+      base::android::GetApplicationContext(),
+      base::android::ConvertUTF8ToJavaString(env, filename).Release());
+  std::vector<long> results;
+  base::android::JavaLongArrayToLongVector(env, jarr.obj(), &results);
+  DCHECK_EQ(3U, results.size());
+  *fd = static_cast<int>(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 (file)
index 0000000..229392c
--- /dev/null
@@ -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 <string>
+
+#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_
index cc5e6a3..4e857c9 100644 (file)
@@ -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));
index ddfeaf3..ffdbea3 100644 (file)
@@ -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 (file)
index 0000000..1b214da
--- /dev/null
@@ -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 <string>
+
+#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 (file)
index 0000000..b059c02
--- /dev/null
@@ -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 <string>
+
+#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 (file)
index 0000000..be519e5
--- /dev/null
@@ -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 <string>
+
+#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<AwMediaUrlInterceptor> 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
index 19c6251..8d7370e 100644 (file)
@@ -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);
 
index f9c42b1..f7aecfe 100644 (file)
@@ -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<std::string> file_path_str;
+  std::vector<std::string> 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<ui::SelectedFileInfo> 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) {
index f8c70d9..cdd6f1f 100644 (file)
@@ -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',
       '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',
index 7dd91e2..212b683 100644 (file)
@@ -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;
index e0d5402..089273b 100644 (file)
@@ -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 (file)
index 0000000..1e9e1a1
--- /dev/null
@@ -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.
index 1332f40..a3ed5e6 100644 (file)
 <translation id="1882897271359938046">نسخ إلى <ph name="DISPLAY_NAME"/></translation>
 <translation id="2727977024730340865">تمّ توصيل شاحن منخفض الطاقة. لذا قد لا تكون عملية شحن البطارية جديرة بالثقة.</translation>
 <translation id="3784455785234192852">قفل</translation>
-<translation id="2805756323405976993">اÙ\84تطبÙ\8aÙ\82ات</translation>
+<translation id="2805756323405976993">تطبيقات</translation>
 <translation id="1512064327686280138">إخفاق في عملية التنشيط</translation>
 <translation id="5097002363526479830">أخفق الاتصال بشبكة &quot;<ph name="NAME"/>&quot;: <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">‏تم إيقاف تشغيل Wi-Fi.</translation>
index 9a7dd44..5909986 100644 (file)
@@ -154,7 +154,7 @@ Pindutin ang Shift + Alt upang magpalit.</translation>
 <translation id="1882897271359938046">Nagmi-mirror sa <ph name="DISPLAY_NAME"/></translation>
 <translation id="2727977024730340865">Naka-saksak sa isang low-power charger. Maaaring hindi maging tiyak ang pag-charge ng baterya.</translation>
 <translation id="3784455785234192852">I-lock</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">Mga App</translation>
 <translation id="1512064327686280138">Pagkabigo ng pag-activate</translation>
 <translation id="5097002363526479830">Nabigong kumonekta sa network na '<ph name="NAME"/>': <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">Naka-off ang Wi-Fi.</translation>
index 31c6a5b..206d154 100644 (file)
@@ -154,7 +154,7 @@ Appuyez sur Maj + Alt pour en utiliser un autre.</translation>
 <translation id="1882897271359938046">Mise en miroir pour <ph name="DISPLAY_NAME"/></translation>
 <translation id="2727977024730340865">L'appareil est branché à un chargeur de faible puissance. Il se peut que la charge ne soit pas fiable.</translation>
 <translation id="3784455785234192852">Verrouiller</translation>
-<translation id="2805756323405976993">Google Apps</translation>
+<translation id="2805756323405976993">Applications</translation>
 <translation id="1512064327686280138">Échec de l'activation</translation>
 <translation id="5097002363526479830">Échec de la connexion au réseau &quot;<ph name="NAME"/>&quot; : <ph name="DETAILS"/>.</translation>
 <translation id="1850504506766569011">Le Wi-Fi est désactivé.</translation>
index 400ac4a..31db163 100644 (file)
 <translation id="1882897271359938046"><ph name="DISPLAY_NAME"/> પર પ્રતિબિંબિત થઈ રહ્યું છે</translation>
 <translation id="2727977024730340865">નિમ્ન-પાવર ચાર્જરમાં પ્લગ કરેલું છે. બૅટરી ચાર્જિંગ વિશ્વસનીય હશે નહીં.</translation>
 <translation id="3784455785234192852">લૉક</translation>
-<translation id="2805756323405976993">àª\8fપà«\8dલિàª\95à«\87શનà«\8dસ</translation>
+<translation id="2805756323405976993">એપ્સ</translation>
 <translation id="1512064327686280138">સક્રિયતા નિષ્ફળ</translation>
 <translation id="5097002363526479830">નેટવર્ક '<ph name="NAME"/>' થી કનેક્ટ કરવામાં નિષ્ફળ: <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">Wi-Fi બંધ છે.</translation>
index 6f87dc5..0e21d33 100644 (file)
@@ -154,7 +154,7 @@ Pritisnite Shift + Alt za promjenu.</translation>
 <translation id="1882897271359938046">Zrcaljenje na zaslon <ph name="DISPLAY_NAME"/></translation>
 <translation id="2727977024730340865">Uređaj je priključen na punjač male snage. Punjenje baterije možda nije pouzdano.</translation>
 <translation id="3784455785234192852">Zaključaj</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">Aplikacije</translation>
 <translation id="1512064327686280138">Neuspjela aktivacija</translation>
 <translation id="5097002363526479830">Neuspješno povezivanje s mrežom &quot;<ph name="NAME"/>&quot;: <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">Wi-Fi je isključen.</translation>
index 01709fc..f12b469 100644 (file)
@@ -154,7 +154,7 @@ Tekan Shift + Alt untuk beralih.</translation>
 <translation id="1882897271359938046">Mencerminkan ke <ph name="DISPLAY_NAME"/></translation>
 <translation id="2727977024730340865">Dipasang ke pengisi daya rendah. Pengisian daya baterai mungkin tidak dapat diandalkan.</translation>
 <translation id="3784455785234192852">Kunci</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">Apl</translation>
 <translation id="1512064327686280138">Kegagalan aktivasi</translation>
 <translation id="5097002363526479830">Gagal menyambung ke jaringan '<ph name="NAME"/>': <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">Wi-Fi dinonaktifkan.</translation>
index 15f2e04..20c13bd 100644 (file)
@@ -154,7 +154,7 @@ Premi Maiusc+Alt per cambiare metodo.</translation>
 <translation id="1882897271359938046">Mirroring su <ph name="DISPLAY_NAME"/></translation>
 <translation id="2727977024730340865">Collegato a un caricabatterie a basso consumo. La carica della batteria potrebbe non essere affidabile.</translation>
 <translation id="3784455785234192852">Blocca</translation>
-<translation id="2805756323405976993">Google Apps</translation>
+<translation id="2805756323405976993">App</translation>
 <translation id="1512064327686280138">Errore di attivazione</translation>
 <translation id="5097002363526479830">Connessione alla rete &quot;<ph name="NAME"/>&quot; non riuscita: <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">Wi-Fi non attivo.</translation>
index 7e8e6e5..1f9b0d4 100644 (file)
 <translation id="1882897271359938046">משקף אל <ph name="DISPLAY_NAME"/></translation>
 <translation id="2727977024730340865">מחובר למטען בעל מתח נמוך. ייתכן שטעינת הסוללה לא תהיה אמינה.</translation>
 <translation id="3784455785234192852">נעילה</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">אפליקציות</translation>
 <translation id="1512064327686280138">כשל בהפעלה</translation>
 <translation id="5097002363526479830">ההתחברות לרשת נכשלה '<ph name="NAME"/>': <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">‏Wi-Fi כבוי.</translation>
index 5879955..cd20d66 100644 (file)
 <translation id="1882897271359938046"><ph name="DISPLAY_NAME"/> ಗೆ ಪ್ರತಿಬಿಂಬಿಸುತ್ತಿದೆ</translation>
 <translation id="2727977024730340865">ಕಡಿಮೆ ವಿದ್ಯುತ್ ಚಾರ್ಜರ್‌ಗೆ ಪ್ಲಗ್ ಮಾಡಲಾಗಿದೆ. ಬ್ಯಾಟರಿ ಚಾರ್ಜಿಂಗ್ ವಿಶ್ವಾಸಾರ್ಹವಾಗಿಲ್ಲದಿರಬಹುದು.</translation>
 <translation id="3784455785234192852">ಲಾಕ್ ಮಾಡಿ</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">ಆಪ್ಸ್‌‌</translation>
 <translation id="1512064327686280138">ಸಕ್ರಿಯಗೊಳಿಸುವಿಕೆ ವಿಫಲವಾಗಿದೆ</translation>
 <translation id="5097002363526479830">'<ph name="NAME"/>' ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು ವಿಫಲವಾಗಿದೆ: <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">Wi-Fi ಆಫ್ ಮಾಡಲಾಗಿದೆ.</translation>
index 84f8ed4..2b767fd 100644 (file)
 <translation id="1882897271359938046"><ph name="DISPLAY_NAME"/>에 미러링</translation>
 <translation id="2727977024730340865">저출력 충전기에 연결되었습니다. 배터리 충전 상태가 불안정합니다.</translation>
 <translation id="3784455785234192852">잠금</translation>
-<translation id="2805756323405976993">ì\9d\91ì\9a©í\94\84ë¡\9cê·¸ë\9e¨</translation>
+<translation id="2805756323405976993">ì\95±</translation>
 <translation id="1512064327686280138">활성화 실패</translation>
 <translation id="5097002363526479830">'<ph name="NAME"/>' 네트워크에 연결하지 못했습니다: <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">Wi-Fi가 꺼져 있습니다.</translation>
index 53e17da..c99a16f 100644 (file)
@@ -154,7 +154,7 @@ Druk op Shift + Alt om te schakelen.</translation>
 <translation id="1882897271359938046">Spiegelen naar <ph name="DISPLAY_NAME"/></translation>
 <translation id="2727977024730340865">Aangesloten op een laag-vermogen-lader. Opladen van de batterij mogelijk niet betrouwbaar.</translation>
 <translation id="3784455785234192852">Vergrendelen</translation>
-<translation id="2805756323405976993">Google Apps</translation>
+<translation id="2805756323405976993">Apps</translation>
 <translation id="1512064327686280138">Activering mislukt</translation>
 <translation id="5097002363526479830">Kan geen verbinding maken met het netwerk '<ph name="NAME"/>': <ph name="DETAILS"/></translation>
 <translation id="1850504506766569011">Wifi is uitgeschakeld.</translation>
index 5d9ce4b..a759e8b 100644 (file)
@@ -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
index 3aa25ba..74497f7 100644 (file)
@@ -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<aura::Window> 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
 
index 74c74f4..b806b47 100644 (file)
@@ -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 "";
+    }
 }
index 6c7ac5b..3c06413 100644 (file)
@@ -167,6 +167,19 @@ void JavaIntArrayToIntVector(JNIEnv* env,
   env->ReleaseIntArrayElements(int_array, ints, JNI_ABORT);
 }
 
+void JavaLongArrayToLongVector(JNIEnv* env,
+                               jlongArray long_array,
+                               std::vector<long>* 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<long>(longs[i]));
+  }
+  env->ReleaseLongArrayElements(long_array, longs, JNI_ABORT);
+}
+
 void JavaFloatArrayToFloatVector(JNIEnv* env,
                                  jfloatArray float_array,
                                  std::vector<float>* out) {
index 9d9be67..66b9422 100644 (file)
@@ -73,6 +73,12 @@ BASE_EXPORT void JavaIntArrayToIntVector(
     jintArray int_array,
     std::vector<int>* out);
 
+// Replaces the content of |out| with the Java longs in |long_array|.
+BASE_EXPORT void JavaLongArrayToLongVector(
+    JNIEnv* env,
+    jlongArray long_array,
+    std::vector<long>* out);
+
 // Replaces the content of |out| with the Java floats in |float_array|.
 BASE_EXPORT void JavaFloatArrayToFloatVector(
     JNIEnv* env,
index 21c3995..7655927 100644 (file)
@@ -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),
index 5026e0e..b400841 100644 (file)
@@ -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
 
index 240043c..91a647d 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR=37
 MINOR=0
 BUILD=2062
-PATCH=76
+PATCH=94
index b472a54..e4345bb 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-hdpi/pageinfo_bad.png and b/src/chrome/android/java/res/drawable-hdpi/pageinfo_bad.png differ
index 9b7c9aa..ca9f695 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-hdpi/pageinfo_enterprise_managed.png and b/src/chrome/android/java/res/drawable-hdpi/pageinfo_enterprise_managed.png differ
index 232d62c..435573f 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-hdpi/pageinfo_good.png and b/src/chrome/android/java/res/drawable-hdpi/pageinfo_good.png differ
index 6a49f5b..708583d 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-hdpi/pageinfo_info.png and b/src/chrome/android/java/res/drawable-hdpi/pageinfo_info.png differ
index 3f28e6f..210700d 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-hdpi/pageinfo_warning_minor.png and b/src/chrome/android/java/res/drawable-hdpi/pageinfo_warning_minor.png differ
diff --git a/src/chrome/android/java/res/drawable-ldrtl-sw600dp-hdpi/edge_menu_bg.9.png b/src/chrome/android/java/res/drawable-ldrtl-sw600dp-hdpi/edge_menu_bg.9.png
new file mode 100644 (file)
index 0000000..8ea9405
Binary files /dev/null and b/src/chrome/android/java/res/drawable-ldrtl-sw600dp-hdpi/edge_menu_bg.9.png differ
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 (file)
index 0000000..c250998
Binary files /dev/null and b/src/chrome/android/java/res/drawable-ldrtl-sw600dp-mdpi/edge_menu_bg.9.png differ
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 (file)
index 0000000..4424cb2
Binary files /dev/null and b/src/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi/edge_menu_bg.9.png differ
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 (file)
index 0000000..e7c030d
Binary files /dev/null and b/src/chrome/android/java/res/drawable-ldrtl-sw600dp-xxhdpi/edge_menu_bg.9.png differ
index 8d133a2..e9cc63f 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-mdpi/pageinfo_bad.png and b/src/chrome/android/java/res/drawable-mdpi/pageinfo_bad.png differ
index 6c6a21c..a23e107 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-mdpi/pageinfo_enterprise_managed.png and b/src/chrome/android/java/res/drawable-mdpi/pageinfo_enterprise_managed.png differ
index 9a7cec7..bfe7357 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-mdpi/pageinfo_good.png and b/src/chrome/android/java/res/drawable-mdpi/pageinfo_good.png differ
index 57572b7..eacd1d0 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-mdpi/pageinfo_info.png and b/src/chrome/android/java/res/drawable-mdpi/pageinfo_info.png differ
index 2c6318b..a0efe75 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-mdpi/pageinfo_warning_minor.png and b/src/chrome/android/java/res/drawable-mdpi/pageinfo_warning_minor.png differ
diff --git a/src/chrome/android/java/res/drawable-sw600dp-hdpi/edge_menu_bg.9.png b/src/chrome/android/java/res/drawable-sw600dp-hdpi/edge_menu_bg.9.png
new file mode 100644 (file)
index 0000000..90c2274
Binary files /dev/null and b/src/chrome/android/java/res/drawable-sw600dp-hdpi/edge_menu_bg.9.png differ
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 (file)
index 0000000..ddc7409
Binary files /dev/null and b/src/chrome/android/java/res/drawable-sw600dp-mdpi/edge_menu_bg.9.png differ
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 (file)
index 0000000..4a3f514
Binary files /dev/null and b/src/chrome/android/java/res/drawable-sw600dp-xhdpi/edge_menu_bg.9.png differ
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 (file)
index 0000000..da8bc44
Binary files /dev/null and b/src/chrome/android/java/res/drawable-sw600dp-xxhdpi/edge_menu_bg.9.png differ
index 00d8f60..04a8b8d 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_bad.png and b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_bad.png differ
index c5fda4e..bd64cae 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_enterprise_managed.png and b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_enterprise_managed.png differ
index 4d3c7e2..4981f84 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_good.png and b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_good.png differ
index e61cc26..8396a96 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_info.png and b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_info.png differ
index f364e97..e03e9f2 100644 (file)
Binary files a/src/chrome/android/java/res/drawable-xhdpi/pageinfo_warning_minor.png and b/src/chrome/android/java/res/drawable-xhdpi/pageinfo_warning_minor.png differ
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 (file)
index 0000000..8a5eb20
Binary files /dev/null and b/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_bad.png differ
diff --git a/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_good.png b/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_good.png
new file mode 100644 (file)
index 0000000..b85c35f
Binary files /dev/null and b/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_good.png differ
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 (file)
index 0000000..f28543f
Binary files /dev/null and b/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_info.png differ
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 (file)
index 0000000..0a7fff1
Binary files /dev/null and b/src/chrome/android/java/res/drawable-xxhdpi/pageinfo_warning_minor.png differ
index 074844b..cb614ca 100644 (file)
@@ -1,30 +1,38 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+<!--
+   Copyright (c) 2013 The Chromium Authors. All rights reserved.
 
    Use of this source code is governed by a BSD-style license that can be
    found in the LICENSE file.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="horizontal"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:paddingTop="@dimen/certificate_viewer_padding"
-              android:paddingBottom="@dimen/certificate_viewer_padding">
-  <ImageView android:id="@+id/website_settings_icon"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content"
-             android:paddingStart="@dimen/certificate_viewer_padding"/>
-  <LinearLayout android:orientation="vertical"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:paddingStart="@dimen/certificate_viewer_padding"
-                android:paddingEnd="@dimen/certificate_viewer_padding">
-    <TextView android:id="@+id/website_settings_headline"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:textStyle="bold"/>
-    <TextView android:id="@+id/website_settings_description"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"/>
-  </LinearLayout>
-</LinearLayout>
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal" >
+
+    <ImageView
+        android:id="@+id/website_settings_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <LinearLayout
+        android:id="@+id/website_settings_text_layout"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:paddingStart="@dimen/certificate_viewer_padding_thin" >
+
+        <TextView
+            android:id="@+id/website_settings_headline"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingBottom="@dimen/certificate_viewer_padding_thin"
+            android:textStyle="bold" />
+
+        <TextView
+            android:id="@+id/website_settings_description"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+    </LinearLayout>
+
+</LinearLayout>
\ 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 (file)
index 0000000..d8fed33
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <!-- Menu Dimensions -->
+    <!-- Necessary to align the menu icon with the actual button. -->
+    <dimen name="menu_software_vertical_offset">-6dp</dimen>
+</resources>
\ No newline at end of file
index 06730b2..66bd267 100644 (file)
@@ -28,4 +28,7 @@
     <color name="app_banner_install_button_fg">#ffffff</color>
     <color name="app_banner_open_button_fg">#777777</color>
     <color name="app_banner_card_highlight">#33999999</color>
+
+    <!--  Website Settings Popup colors -->
+    <color name="website_settings_popup_text_link">#5595fe</color>
 </resources>
index e1b6b0a..72172f2 100644 (file)
@@ -6,7 +6,8 @@
 
 <resources>
     <!-- Certificate Viewer Dimensions -->
-    <dimen name="certificate_viewer_padding">20dp</dimen>
+    <dimen name="certificate_viewer_padding_wide">24dp</dimen>
+    <dimen name="certificate_viewer_padding_thin">16dp</dimen>
 
     <!-- Accessibility tab switcher -->
     <dimen name="accessibility_tab_height">65dp</dimen>
@@ -16,6 +17,7 @@
 
     <!-- Custom Menu dimensions -->
     <dimen name="menu_width">258dp</dimen>
+    <dimen name="menu_software_vertical_offset">0dp</dimen>
     <!-- The amount to fade the edges of the menu to indicate more content is available
          via scrolling. -->
     <dimen name="menu_vertical_fade_distance">15dp</dimen>
index c4660fc..fef7090 100644 (file)
@@ -56,7 +56,7 @@ class CertificateViewer implements OnItemSelectedListener {
         mViews = new ArrayList<LinearLayout>();
         mTitles = new ArrayList<String>();
         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.
index 7e43f06..d2f9e06 100644 (file)
@@ -250,13 +250,17 @@ class TtsPlatformImpl {
         mVoices = new ArrayList<TtsVoice>();
         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.
             }
         }
 
index 887ea4a..51b32a8 100644 (file)
@@ -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("<a href='#'>" + label + "</a>"));
+        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("<a href='#'>" + label + "</a>"));
-        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. */
index 6f7f573..15afde5 100644 (file)
@@ -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);
         }
     }
 
index f89dca7..8006249 100644 (file)
@@ -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 (file)
index 0000000..c9a3bde
--- /dev/null
@@ -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());
+    }
+}
index 476deb9..3499dd3 100644 (file)
                 <action android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
             </intent-filter>
         </receiver>
+        <meta-data android:name="org.chromium.content.browser.SMART_CLIP_PROVIDER"
+                   android:value="org.chromium.content.browser.SmartClipProvider" />
+
     </application>
 </manifest>
index 671c166..ba863fb 100644 (file)
 <translation id="7347751611463936647">‏لاستخدام هذه الإضافة، اكتب &quot;<ph name="EXTENSION_KEYWORD"/>&quot;، ثم TAB، ثم الأمر أو البحث.</translation>
 <translation id="878431691778285679">يبدو أنك تدير مستخدمًا من خلال هذا الاسم فعلاً.<ph name="LINE_BREAK"/>هل كنت تريد <ph name="BEGIN_LINK"/>الاستيراد <ph name="PROFILE_NAME"/> إلى هذا الجهاز<ph name="END_LINK"/>؟</translation>
 <translation id="2912905526406334195">يريد <ph name="HOST"/> استخدام الميكروفون.</translation>
-<translation id="2805756323405976993">اÙ\84تطبÙ\8aÙ\82ات</translation>
+<translation id="2805756323405976993">تطبيقات</translation>
 <translation id="5151511998946489774">تم التحقق من هوية موقع الويب هذا بواسطة <ph name="ISSUER"/> وهو قابل للتدقيق بشكل عام.</translation>
 <translation id="1608626060424371292">إزالة هذا المستخدم</translation>
 <translation id="2779552785085366231">‏يمكن إضافة هذه الصفحة إلى تطبيقات Launcher</translation>
index 071dbf0..41110fa 100644 (file)
@@ -2917,7 +2917,7 @@ Tiyaking hindi ka maglalantad ng anumang sensitibong impormasyon.</translation>
 <translation id="7347751611463936647">Upang gamitin ang extension na ito, i-type ang &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, pagkatapos ay ang TAB, pagkatapos ay ang iyong command o paghahanap.</translation>
 <translation id="878431691778285679">Mukhang pinamamahalaan mo na ang isang user sa pangalang iyan.<ph name="LINE_BREAK"/>Gusto mo bang <ph name="BEGIN_LINK"/>i-import si <ph name="PROFILE_NAME"/> sa device na ito<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195">Gustong  gamitin ng <ph name="HOST"/> ang iyong microphone.</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">Mga App</translation>
 <translation id="5151511998946489774">Ang pagkakakilanlan ng website na ito ay na-verify ni <ph name="ISSUER"/> at na-o-audit ng publiko.</translation>
 <translation id="1608626060424371292">Alisin ang user na ito</translation>
 <translation id="2779552785085366231">Maaaring idagdag ang page na ito sa App Launcher</translation>
index 7db02c4..11715bf 100644 (file)
@@ -2920,7 +2920,7 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
 <translation id="7347751611463936647">Pour utiliser cette extension, saisissez &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, TAB, puis votre commande ou votre recherche.</translation>
 <translation id="878431691778285679">Il semble que vous gérez déjà un utilisateur portant ce nom.<ph name="LINE_BREAK"/>Voulez-vous <ph name="BEGIN_LINK"/>importer <ph name="PROFILE_NAME"/> sur cet appareil<ph name="END_LINK"/> ?</translation>
 <translation id="2912905526406334195"><ph name="HOST"/> veut utiliser votre micro.</translation>
-<translation id="2805756323405976993">Google Apps</translation>
+<translation id="2805756323405976993">Applications</translation>
 <translation id="5151511998946489774">L'identité de ce site Web a été validée par <ph name="ISSUER"/>, et elle est vérifiable publiquement.</translation>
 <translation id="1608626060424371292">Supprimer cet utilisateur</translation>
 <translation id="2779552785085366231">Cette page peut être ajoutée au lanceur d'applications.</translation>
index 933e8eb..2d9dc8b 100644 (file)
 <translation id="7347751611463936647">આ એક્સ્ટેંશનનો ઉપયોગ કરવા, &quot;<ph name="EXTENSION_KEYWORD"/>&quot; ટાઇપ કરો, તે પછી TAB, તે પછી તમારો આદેશ અથવા શોધ.</translation>
 <translation id="878431691778285679">એવું લાગે છે કે તમે પહેલાંથી જ તે નામના વપરાશકર્તાનું સંચાલન કરી રહ્યાં છો.<ph name="LINE_BREAK"/>શું તમે <ph name="BEGIN_LINK"/>આ ઉપકરણ પર <ph name="PROFILE_NAME"/> આયાત કરવા માંગો છો<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195"><ph name="HOST"/> તમારા માઇક્રોફોનનો ઉપયોગ કરવા માગે છે.</translation>
-<translation id="2805756323405976993">àª\8fપà«\8dલિàª\95à«\87શનà«\8dસ</translation>
+<translation id="2805756323405976993">એપ્સ</translation>
 <translation id="5151511998946489774"><ph name="ISSUER"/> દ્વારા આ વેબસાઇટની ઓળખ ચકાસવામાં આવી છે અને તે સાર્વજનિક રૂપે ઓડિટેબલ છે.</translation>
 <translation id="1608626060424371292">આ વપરાશકર્તાને દૂર કરો</translation>
 <translation id="2779552785085366231">આ પૃષ્ઠ એપ લૉન્ચરમાં ઉમેરી શકાય છે</translation>
index 8279b6c..ac58918 100644 (file)
@@ -2884,7 +2884,7 @@ Ne otkrivajte nikakve osjetljive podatke.</translation>
 <translation id="7347751611463936647">Da biste upotrijebili to proširenje, upišite &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, zatim pritisnite TAB, a zatim svoju naredbu ili pretraživanje.</translation>
 <translation id="878431691778285679">Izgleda da već upravljate korisnikom pod tim imenom.<ph name="LINE_BREAK"/>Jeste li htjeli <ph name="BEGIN_LINK"/>uvesti korisnika <ph name="PROFILE_NAME"/> na ovaj uređaj<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195">Host <ph name="HOST"/> želi upotrijebiti vaš mikrofon.</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">Aplikacije</translation>
 <translation id="5151511998946489774">Identitet te web-lokacije potvrdio je izdavač <ph name="ISSUER"/> i može se javno nadzirati.</translation>
 <translation id="1608626060424371292">Ukloni tog korisnika</translation>
 <translation id="2779552785085366231">Tu stranicu možete dodati u Pokretač aplikacija</translation>
index 5495d64..60b68a4 100644 (file)
@@ -2894,7 +2894,7 @@ Pastikan Anda tidak mengekspos informasi penting apa pun.</translation>
 <translation id="7347751611463936647">Untuk menggunakan ekstensi ini, ketik &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, lalu TAB, kemudian perintah atau penelusuran Anda.</translation>
 <translation id="878431691778285679">Tampaknya Anda telah mengelola pengguna dengan nama tersebut.<ph name="LINE_BREAK"/>Apakah Anda ingin <ph name="BEGIN_LINK"/>mengimpor <ph name="PROFILE_NAME"/> ke perangkat ini<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195"><ph name="HOST"/> ingin menggunakan mikrofon Anda.</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">Apl</translation>
 <translation id="5151511998946489774">Identitas situs web ini telah diverifikasi oleh <ph name="ISSUER"/> dan dapat diaudit secara publik.</translation>
 <translation id="1608626060424371292">Hapus pengguna ini</translation>
 <translation id="2779552785085366231">Laman ini dapat ditambahkan ke Peluncur Aplikasi</translation>
@@ -3459,7 +3459,7 @@ dan tidak biasa. Bisa jadi penyerang berpura-pura menjadi <ph name="SITE"/>, ata
 <translation id="8353683614194668312">Aplikasi/ekstensi dapat:</translation>
 <translation id="1047956942837015229">Menghapus <ph name="COUNT"/> item...</translation>
 <translation id="1531961661616401172">Aktifkan Pemberitahuan Tersinkron eksperimental.</translation>
-<translation id="7361039089383199231">$1 byte</translation>
+<translation id="7361039089383199231">$1 bita</translation>
 <translation id="191688485499383649">Terjadi kesalahan tidak dikenal saat mencoba menyambung ke &quot;<ph name="DEVICE_NAME"/>&quot;.</translation>
 <translation id="7208594729785140450">Google Wallet tidak mendukung versi Chrome ini atau tidak mengenali kunci API Google Anda.</translation>
 <translation id="6874681241562738119">Kesalahan Masuk</translation>
@@ -4812,7 +4812,7 @@ Tekan sembarang tombol untuk melanjutkan penjelajahan.</translation>
 <translation id="4084682180776658562">Bookmark</translation>
 <translation id="8859057652521303089">Pilih bahasa Anda:</translation>
 <translation id="2632795170092344386">Hapus cookies serta data situs dan plugin lainnya saat Anda menutup browser</translation>
-<translation id="5941864346249299673">Jumlah byte yang terbaca di seluruh jaringan</translation>
+<translation id="5941864346249299673">Jumlah bita yang terbaca di seluruh jaringan</translation>
 <translation id="3030138564564344289">Coba ulang unduhan</translation>
 <translation id="2603463522847370204">Buka di &amp;jendela penyamaran</translation>
 <translation id="2951236788251446349">Ubur-ubur</translation>
index 2f82781..1676247 100644 (file)
@@ -2875,7 +2875,7 @@ Assicurati di non mostrare informazioni riservate.</translation>
 <translation id="7347751611463936647">Per utilizzare questa estensione, digita &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, quindi TAB, poi il tuo comando o la tua ricerca.</translation>
 <translation id="878431691778285679">Sembra che tu gestisca già un utente con il nome indicato.<ph name="LINE_BREAK"/>Volevi <ph name="BEGIN_LINK"/>importarlo<ph name="PROFILE_NAME"/> in questo dispositivo<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195"><ph name="HOST"/> vuole utilizzare il microfono.</translation>
-<translation id="2805756323405976993">Google Apps</translation>
+<translation id="2805756323405976993">App</translation>
 <translation id="5151511998946489774">L'identità di questo sito web è stata verificata da <ph name="ISSUER"/> e può essere controllata pubblicamente.</translation>
 <translation id="1608626060424371292">Rimuovi questo utente</translation>
 <translation id="2779552785085366231">Questa pagina può essere aggiunta ad Avvio applicazioni</translation>
index 36c1f74..342b5f8 100644 (file)
@@ -2882,7 +2882,7 @@ JavaScript ויישומי פלאגין.</translation>
 <translation id="7347751611463936647">‏כדי להשתמש בתוסף זה, הקלד &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, לאחר מכן הקש TAB ולאחר מכן הקלד את הפקודה או מונח החיפוש.</translation>
 <translation id="878431691778285679">נראה שאתה כבר מנהל משתמש עם השם הזה.<ph name="LINE_BREAK"/>האם רצית <ph name="BEGIN_LINK"/>לייבא את <ph name="PROFILE_NAME"/> אל המכשיר הזה<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195"><ph name="HOST"/> מעוניין להשתמש במיקרופון שלך.</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">אפליקציות</translation>
 <translation id="5151511998946489774">הזהות של האתר הזה אומתה על ידי <ph name="ISSUER"/>, והוא זמין לביקורת ציבורית.</translation>
 <translation id="1608626060424371292">הסר את המשתמש הזה</translation>
 <translation id="2779552785085366231">ניתן להוסיף דף זה למפעיל היישומים</translation>
index f7158b2..26ad58c 100644 (file)
 <translation id="7347751611463936647">ಈ ವಿಸ್ತರಣೆಯನ್ನು ಬಳಸಲು, &quot;<ph name="EXTENSION_KEYWORD"/>&quot; ಅನ್ನು ಟೈಪ್ ಮಾಡಿ, ನಂತರ  TAB, ನಂತರ ನಿಮ್ಮ ಆದೇಶ ಅಥವಾ ಹುಡುಕಾಟ‌ವನ್ನು ಟೈಪ್ ಮಾಡಿ.</translation>
 <translation id="878431691778285679">ಆ ಹೆಸರಿನ ಮೂಲಕ ನೀವು ಈಗಾಗಲೇ ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸುತ್ತಿರುವಂತೆ ತೋರುತ್ತಿದೆ.<ph name="LINE_BREAK"/>ನೀವು ಈ ಸಾಧನಕ್ಕೆ <ph name="BEGIN_LINK"/>ಆಮದು ಮಾಡಲು <ph name="PROFILE_NAME"/> ಬಯಸುವಿರಾ<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195">ನಿಮ್ಮ ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು <ph name="HOST"/> ಬಳಸಬೇಕೆಂದು ಬಯಸುತ್ತದೆ.</translation>
-<translation id="2805756323405976993">Apps</translation>
+<translation id="2805756323405976993">ಆಪ್ಸ್‌‌</translation>
 <translation id="5151511998946489774">ಈ ವೆಬ್‌ಸೈಟ್‌ ಗುರುತನ್ನು <ph name="ISSUER"/> ಮೂಲಕ ಪರಿಶೀಲಿಸಲಾಗಿದೆ ಮತ್ತು ಇದನ್ನು ಸಾರ್ವಜನಿಕವಾಗಿ ಪರಿಶೋಧಿಸಬಹುದಾಗಿದೆ.</translation>
 <translation id="1608626060424371292">ಈ ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಿ</translation>
 <translation id="2779552785085366231">ಈ ಪುಟವನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಲಾಂಚರ್‌ಗೆ ಸೇರಿಸಬಹುದಾಗಿದೆ</translation>
index 74ef97c..dd302ff 100644 (file)
@@ -2916,7 +2916,7 @@ http://support.google.com/chromebook/?p=tpm</translation>
 <translation id="7347751611463936647">이 확장 프로그램을 사용하려면 '<ph name="EXTENSION_KEYWORD"/>'(을)를 입력하고 TAB을 누른 다음 명령어 또는 검색어를 입력하세요.</translation>
 <translation id="878431691778285679">이미 해당 이름으로 사용자를 관리 중인 것 같습니다.<ph name="LINE_BREAK"/><ph name="BEGIN_LINK"/><ph name="PROFILE_NAME"/>을(를) 이 기기로 가져오시겠습니까<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195"><ph name="HOST"/>에서 사용자의 마이크를 사용하려고 합니다.</translation>
-<translation id="2805756323405976993">ì\9d\91ì\9a©í\94\84ë¡\9cê·¸ë\9e¨</translation>
+<translation id="2805756323405976993">ì\95±</translation>
 <translation id="5151511998946489774">이 웹사이트의 ID는 <ph name="ISSUER"/>에 의해 확인되었고 공개 감사가 가능합니다.</translation>
 <translation id="1608626060424371292">이 사용자 삭제</translation>
 <translation id="2779552785085366231">이 페이지를 앱 런처에 추가할 수 있습니다.</translation>
index e3c87ac..9753736 100644 (file)
@@ -2927,7 +2927,7 @@ Zorg ervoor dat je geen gevoelige informatie weergeeft.</translation>
 <translation id="7347751611463936647">Als je deze extensie wilt gebruiken, typ je '<ph name="EXTENSION_KEYWORD"/>', druk je op Tab en geef je je opdracht of zoekopdracht op.</translation>
 <translation id="878431691778285679">Het lijkt erop dat je al een gebruiker met die naam beheert.<ph name="LINE_BREAK"/>Wil je <ph name="BEGIN_LINK"/><ph name="PROFILE_NAME"/> importeren naar dit apparaat<ph name="END_LINK"/>?</translation>
 <translation id="2912905526406334195"><ph name="HOST"/> wil gebruikmaken van je microfoon.</translation>
-<translation id="2805756323405976993">Google Apps</translation>
+<translation id="2805756323405976993">Apps</translation>
 <translation id="5151511998946489774">De identiteit van deze website is geverifieerd door <ph name="ISSUER"/> en is openbaar controleerbaar.</translation>
 <translation id="1608626060424371292">Deze gebruiker verwijderen</translation>
 <translation id="2779552785085366231">Deze pagina kan worden toegevoegd aan de App Launcher</translation>
index 1567066..18df83e 100644 (file)
 <translation id="2220529011494928058">Пријави проблем</translation>
 <translation id="8475107630436748034">Експеримент са TLS/SSL упозорењем</translation>
 <translation id="7857823885309308051">Ово може да потраје један минут...</translation>
-<translation id="370665806235115550">Учитавање...</translation>
+<translation id="370665806235115550">Учитава се...</translation>
 <translation id="2580924999637585241">Укупно: <ph name="NUMBER_OF_SHEETS"/><ph name="SHEETS_LABEL"/></translation>
 <translation id="3810973564298564668">Промени</translation>
 <translation id="254416073296957292">&amp;Подешавања језика...</translation>
index 3fa98b7..5dd5147 100644 (file)
 <translation id="1556537182262721003">சுயவிவரத்தில் நீட்டிப்புக் கோப்பகத்தை நகர்த்த முடியவில்லை.</translation>
 <translation id="2946640296642327832">புளூடூத்தை இயக்கு</translation>
 <translation id="5866557323934807206">எதிர்கால வருகைகளுக்கு இந்த அமைப்புகளை அழி</translation>
-<translation id="126710816202626562">à®®à¯\86ாழிபà¯\86யரà¯\8dபà¯\8dபிறà¯\8dà®\95ான à®®à¯\86ாழி:</translation>
+<translation id="126710816202626562">à®®à¯\8aழிபà¯\86யரà¯\8dபà¯\8dபிறà¯\8dà®\95ான à®®à¯\8aழி:</translation>
 <translation id="1194381338562257973">சோதனை முறையிலான குறுகியகாலப் பயன்பாடுகளை இயக்கு.</translation>
 <translation id="5355351445385646029">பிரதிநிதியைத் தேர்ந்தெடுக்க Space ஐ அழுத்துக</translation>
 <translation id="5453029940327926427">தாவல்களை மூடுக</translation>
 <translation id="7211828883345145708">Chromium ஐப் பிழைத்திருத்துவதற்குப் பயன்படும் கூடுதல் விசைப்பலகைக் குறுக்குவழிகளை இயக்கும்.</translation>
 <translation id="8319414634934645341">நீட்டிக்கப்பட்ட விசைப் பயன்பாடு</translation>
 <translation id="6056710589053485679">இயல்பாக மீண்டும் ஏற்று</translation>
-<translation id="4563210852471260509">தà¯\86ாà®\9fà®\95à¯\8dà®\95 à®\89ளà¯\8dளà¯\80à®\9fà¯\8dà®\9fà¯\81 à®®à¯\86ாழி சீனம்</translation>
+<translation id="4563210852471260509">தà¯\86ாà®\9fà®\95à¯\8dà®\95 à®\89ளà¯\8dளà¯\80à®\9fà¯\8dà®\9fà¯\81 à®®à¯\8aழி சீனம்</translation>
 <translation id="2888807692577297075">&lt;b&gt;&quot;<ph name="SEARCH_STRING"/>&quot;&lt;/b&gt; உடன் பொருந்தும் உருப்படிகள் எதுவுமில்லை</translation>
 <translation id="3908501907586732282">நீட்டிப்பை இயக்கு</translation>
 <translation id="6897140037006041989">பயனர் முகவர்</translation>
 <translation id="1903219944620007795">உரை உள்ளீட்டுக்கு, ஒரு மொழியைத் தேர்ந்தெடுத்து கிடைக்கும் உள்ளீட்டு முறைகளைக் காண்க.</translation>
 <translation id="1850508293116537636">&amp;வலஞ்சுழியாகச் சுற்று</translation>
 <translation id="76113267417806263">ஆம், உறுதியாக உள்ளேன்</translation>
-<translation id="7209475358897642338">à®\89à®\99à¯\8dà®\95ளà¯\8d à®®à¯\86ாழி என்ன?</translation>
+<translation id="7209475358897642338">à®\89à®\99à¯\8dà®\95ளà¯\8d à®®à¯\8aழி என்ன?</translation>
 <translation id="140520891692800925"><ph name="PROFILE_DISPLAY_NAME"/> (கண்காணிக்கப்படும் பயனர்)</translation>
 <translation id="9149866541089851383">மாற்று...</translation>
 <translation id="8735794438432839558">உங்கள் Chromebook இல் உள்நுழைய, இணையத்துடன் இணையவும்.</translation>
index 892737a..5d06410 100644 (file)
 <translation id="4278390842282768270">允許</translation>
 <translation id="2074527029802029717">取消分頁固定</translation>
 <translation id="1533897085022183721">電池可使用時間低於 <ph name="MINUTES"/>。</translation>
-<translation id="7382160026931194400">已儲存的內容設定及搜尋引擎不會遭到清除,而這可能反映您的瀏覽習慣。</translation>
+<translation id="7382160026931194400">已儲存的|內容設定|和#搜尋引擎#資料不會被清除,而且可能會反映您的瀏覽習慣。</translation>
 <translation id="7503821294401948377">無法載入瀏覽器動作的圖示「<ph name="ICON"/>」。</translation>
 <translation id="4809190954660909198">新增帳單詳細資訊...</translation>
 <translation id="3942946088478181888">我需要進一步資訊</translation>
 <translation id="7943385054491506837">Colemak 美式配置</translation>
 <translation id="8203365863660628138">確認安裝</translation>
 <translation id="2533972581508214006">回報錯誤的警告</translation>
-</translationbundle>
\ No newline at end of file
+</translationbundle>
index 16aed52..4cae0f3 100644 (file)
@@ -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
index 955a91d..51c9571 100644 (file)
@@ -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();
 }
 
index 3dff8f1..50df660 100644 (file)
@@ -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());
 }
index 7a9fe67..a26939e 100644 (file)
@@ -150,6 +150,8 @@ class KioskAppManager : public KioskAppDataDelegate,
                                 Profile* profile,
                                 const extensions::Extension* app);
 
+  void RetryFailedAppDataFetch();
+
   void AddObserver(KioskAppManagerObserver* observer);
   void RemoveObserver(KioskAppManagerObserver* observer);
 
index 0179772..10c0aac 100644 (file)
@@ -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<int>(event.key_code());
   ext_event->alt_key = event.IsAltDown();
   ext_event->ctrl_key = event.IsControlDown();
index 494371f..a169cdb 100644 (file)
@@ -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");
index 172417d..06b7435 100644 (file)
@@ -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() {
index 2422262..6c7b795 100644 (file)
@@ -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<double>(sys);
     infos->at(i)->usage.user = static_cast<double>(user + nice);
     infos->at(i)->usage.idle = static_cast<double>(idle);
     infos->at(i)->usage.total = static_cast<double>(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;
 }
 
index 89d523b..d71fe01 100644 (file)
@@ -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();
 }
 
index fb8aafd..b11ac97 100644 (file)
@@ -38,6 +38,10 @@ class WebstoreDataFetcher : public base::SupportsWeakPtr<WebstoreDataFetcher>,
 
   void Start();
 
+  void set_max_auto_retries(int max_retries) {
+    max_auto_retries_ = max_retries;
+  }
+
  private:
   void OnJsonParseSuccess(scoped_ptr<base::Value> parsed_json);
   void OnJsonParseFailure(const std::string& error);
@@ -53,6 +57,10 @@ class WebstoreDataFetcher : public base::SupportsWeakPtr<WebstoreDataFetcher>,
   // For fetching webstore JSON data.
   scoped_ptr<net::URLFetcher> 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);
 };
 
index 38eb30c..e705b46 100644 (file)
@@ -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 --------------------------------------------------------
index 697ccad..5537712 100644 (file)
@@ -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);
index a6f8d9a..3a49fc0 100644 (file)
@@ -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
index 92638ae..11a682e 100644 (file)
@@ -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
index 6aa21cf..1a67836 100644 (file)
@@ -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;
index ba150cd..401eab3 100644 (file)
@@ -68,7 +68,7 @@
 }
 
 #hid-detection #hid-keyboard-pincode {
-  -webkit-padding-start: 40px;
+  -webkit-padding-start: 60px;
   padding-bottom: 15px;
   padding-top: 15px;
 }
index eb21576..889cf30 100644 (file)
@@ -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": {
index d20661e..dfc1e16 100644 (file)
@@ -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
+}
index ae20046..e2165b9 100644 (file)
@@ -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_;
 
index 1c0aabb..c5a35f7 100644 (file)
@@ -125,17 +125,15 @@ void WebsiteSettingsPopupAndroid::SetIdentityInfo(
 
     ScopedJavaLocalRef<jstring> 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<jstring> 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(),
index f8f08d6..5047f64 100644 (file)
@@ -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);
index ae9cf1b..4f0833b 100644 (file)
@@ -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);
   }
index cdd9e68..0498888 100644 (file)
@@ -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)
index a1eab10..5babef6 100644 (file)
@@ -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();
index 50295aa..4ab1f18 100644 (file)
@@ -37,14 +37,18 @@ const int kMaxAppIconSize = 160;
 
 }  // namespace
 
-KioskAppMenuHandler::KioskAppMenuHandler()
+KioskAppMenuHandler::KioskAppMenuHandler(
+    const scoped_refptr<NetworkStateInformer>& 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
index 2cd58ac..b1e887e 100644 (file)
@@ -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<NetworkStateInformer>& 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<KioskAppMenuHandler> weak_ptr_factory_;
 
   // True when WebUI is initialized. Otherwise don't allow calling JS functions.
   bool is_webui_initialized_;
 
+  scoped_refptr<NetworkStateInformer> network_state_informer_;
+
   DISALLOW_COPY_AND_ASSIGN(KioskAppMenuHandler);
 };
 
index 67dfa9a..8d55960 100644 (file)
@@ -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;
index 9ee7347..9665b1f 100644 (file)
@@ -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};
index 759b5c9..4637e9e 100644 (file)
@@ -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};
index af97838..32ba9af 100644 (file)
@@ -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};
index efb9c97..4026a0a 100644 (file)
@@ -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).
index 0429514..60897eb 100644 (file)
           اگر این خط‌مشی را تنظیم کرده باشید، کاربران نمی‌توانند آن را تغییر دهند یا لغو نمایند.
 
           چنانچه این خط‌مشی بدون تنظیم رها شده باشد، نشانگر موشواره بزرگ از ابتدا از کار افتاده است اما می‌تواند در هر زمان توسط کاربر به کار انداخته شود.</translation>
-<translation id="2633084400146331575">فعال کردن بازخورد صوتی</translation>
+<translation id="2633084400146331575">فعال کردن بازخورد گفتاری</translation>
 <translation id="687046793986382807">این خط‌مشی از <ph name="PRODUCT_NAME"/> نسخه ۳۵ کنار گذاشته شده است.
 
       اطلاعات حافظه به هر حال، بدون در نظر گرفتن مقدار گزینه، به صفحه گزارش داده خواهد شد، اما اندازه‌های گزارش شده 
index b703054..63d62ce 100644 (file)
 <translation id="6786747875388722282">Ekstensi</translation>
 <translation id="7132877481099023201">URL yang akan diberi akses ke perangkat perekam video tanpa peringatan</translation>
 <translation id="8947415621777543415">Laporkan lokasi perangkat</translation>
-<translation id="1655229863189977773">Setel ukuran cache disk dalam byte</translation>
+<translation id="1655229863189977773">Setel ukuran cache disk dalam bita</translation>
 <translation id="3358275192586364144">Mengaktifkan pengoptimalan WPAD pada <ph name="PRODUCT_NAME"/> 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.
       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.</translation>
 <translation id="6774533686631353488">Izinkan host Native Messaging tingkat pengguna (dipasang tanpa izin admin).</translation>
 <translation id="868187325500643455">Izinkan semua situs menjalankan plugin secara otomatis</translation>
-<translation id="7421483919690710988">Setel ukuran cache disk media dalam byte</translation>
+<translation id="7421483919690710988">Setel ukuran cache disk media dalam bita</translation>
 <translation id="5226033722357981948">Menentukan apakah pencari plugin harus dinonaktifkan</translation>
 <translation id="7234280155140786597">Nama hosting perpesanan asli yang dilarang (atau * untuk semua)</translation>
 <translation id="4890209226533226410">Menyetel jenis lup yang diaktifkan.
index 8ababa4..e456729 100644 (file)
@@ -64,7 +64,7 @@
 <translation id="337363190475750230">Онемогућен је</translation>
 <translation id="2367567093518048410">Ниво</translation>
 <translation id="7610193165460212391">Вредност је изван опсега <ph name="VALUE"/>.</translation>
-<translation id="370665806235115550">Учитавање...</translation>
+<translation id="370665806235115550">Учитава се...</translation>
 <translation id="2096368010154057602">Департман</translation>
 <translation id="4258748452823770588">Неисправан потпис</translation>
 <translation id="3024663005179499861">Погрешан тип смерница</translation>
index fc0af4c..1021550 100644 (file)
@@ -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<jobject> 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<jobject> obj = java_ref_.get(env);
   if (obj.is_null())
     return;
-  ScopedJavaLocalRef<jstring> jresult = ConvertUTF16ToJavaString(env, result);
+  ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
+  ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
+  ScopedJavaLocalRef<jobject> 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() {
index 3bb1291..462f3dc 100644 (file)
@@ -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
   // --------------------------------------------------------------------------
index c19173c..e5a0a68 100644 (file)
@@ -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());
index 5df9016..d0c0a69 100644 (file)
@@ -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<BrowserMediaPlayerManager*>(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<RenderWidgetHostViewAndroid*>(
+              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));
index 4c53388..5f3fae5 100644 (file)
@@ -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;
index bcf293d..dac0059 100644 (file)
@@ -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<jobject>& 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<jobject> 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);
index c1ed4b9..252ada8 100644 (file)
@@ -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 (file)
index 0000000..59f28cf
--- /dev/null
@@ -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 (file)
index 0000000..092c30d
--- /dev/null
@@ -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 (file)
index 0000000..c5be224
--- /dev/null
@@ -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 <string>
+#include <vector>
+
+#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<GestureTextSelector> selector_;
+  std::vector<std::string> 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
index 7409955..7316a40 100644 (file)
@@ -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<ui::MotionEvent> MotionEventAndroid::Clone() const {
   return scoped_ptr<MotionEvent>(new MotionEventAndroid(*this));
 }
index 0362b04..aa3e082 100644 (file)
@@ -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<MotionEvent> Clone() const OVERRIDE;
   virtual scoped_ptr<MotionEvent> 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.
index d1ff8a3..0d812b2 100644 (file)
@@ -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<ui::MotionEvent> MotionEventWeb::Clone() const {
   return scoped_ptr<MotionEvent>(new MotionEventWeb(event_));
 }
index f4ae258..06a2141 100644 (file)
@@ -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<MotionEvent> Clone() const OVERRIDE;
   virtual scoped_ptr<MotionEvent> Cancel() const OVERRIDE;
 
index d281bdf..eb638b0 100644 (file)
@@ -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;
index e883502..6f249d4 100644 (file)
@@ -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.
index f421735..ff24085 100644 (file)
@@ -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<WebContentsImpl*>(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) {
index 4707734..4d81add 100644 (file)
@@ -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_;
index fb8c0db..fbb5071 100644 (file)
@@ -62,6 +62,12 @@ ScopedJavaLocalRef<jstring> WebContentsAndroid::GetTitle(
                                                  web_contents_->GetTitle());
 }
 
+ScopedJavaLocalRef<jstring> 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();
 }
index eec6127..eda0235 100644 (file)
@@ -36,6 +36,8 @@ class CONTENT_EXPORT WebContentsAndroid
   // Methods called from Java
   base::android::ScopedJavaLocalRef<jstring> GetTitle(JNIEnv* env,
                                                       jobject obj) const;
+  base::android::ScopedJavaLocalRef<jstring> GetVisibleURL(JNIEnv* env,
+                                                           jobject obj) const;
   void Stop(JNIEnv* env, jobject obj);
 
  private:
index 4548f0b..2908a2f 100644 (file)
@@ -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:
index d12ba35..2a95e3f 100644 (file)
@@ -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.
index 33f796f..00f8ce0 100644 (file)
       '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',
index b2973f9..0ea623d 100644 (file)
@@ -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',
       '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',
       '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',
index d17648d..bb754ae 100644 (file)
         '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 (file)
index 0000000..cac71c1
--- /dev/null
@@ -0,0 +1,2 @@
+# DWrite specific changes
+per-file render_font_warmup_win.h=scottmg@chromium.org
index 7bdcefe..8a5a98a 100644 (file)
Binary files a/src/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png and b/src/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png differ
index 5258446..bc619f3 100644 (file)
Binary files a/src/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png and b/src/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png differ
index 40604f1..8f4dcb8 100644 (file)
Binary files a/src/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png and b/src/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png differ
diff --git a/src/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png b/src/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png
new file mode 100644 (file)
index 0000000..742206c
Binary files /dev/null and b/src/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png differ
index d1c8d0e..0bc4e39 100644 (file)
@@ -9,6 +9,10 @@ import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -25,7 +29,9 @@ import org.chromium.base.TraceEvent;
  * exposes the various {@link View} functionality to it.
  */
 public class ContentView extends FrameLayout
-        implements ContentViewCore.InternalAccessDelegate {
+        implements ContentViewCore.InternalAccessDelegate, SmartClipProvider {
+
+    private static final String TAG = "ContentView";
 
     protected final ContentViewCore mContentViewCore;
 
@@ -247,6 +253,38 @@ public class ContentView extends FrameLayout
         mContentViewCore.onVisibilityChanged(changedView, visibility);
     }
 
+    // Implements SmartClipProvider
+    @Override
+    public void extractSmartClipData(int x, int y, int width, int height) {
+        mContentViewCore.extractSmartClipData(x, y, width, height);
+    }
+
+    // Implements SmartClipProvider
+    @Override
+    public void setSmartClipResultHandler(final Handler resultHandler) {
+        if (resultHandler == null) {
+            mContentViewCore.setSmartClipDataListener(null);
+            return;
+        }
+        mContentViewCore.setSmartClipDataListener(new ContentViewCore.SmartClipDataListener() {
+            public void onSmartClipDataExtracted(String text, String html, Rect clipRect) {
+                Bundle bundle = new Bundle();
+                bundle.putString("url", mContentViewCore.getWebContents().getVisibleUrl());
+                bundle.putString("title", mContentViewCore.getWebContents().getTitle());
+                bundle.putParcelable("rect", clipRect);
+                bundle.putString("text", text);
+                bundle.putString("html", html);
+                try {
+                    Message msg = Message.obtain(resultHandler, 0);
+                    msg.setData(bundle);
+                    msg.sendToTarget();
+                } catch (Exception e) {
+                    Log.e(TAG, "Error calling handler for smart clip data: ", e);
+                }
+            }
+        });
+    }
+
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //              Start Implementation of ContentViewCore.InternalAccessDelegate               //
     ///////////////////////////////////////////////////////////////////////////////////////////////
index 733a993..1e80d5f 100644 (file)
@@ -10,6 +10,7 @@ import android.app.SearchManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
@@ -109,6 +110,15 @@ public class ContentViewCore
     // Length of the delay (in ms) before fading in handles after the last page movement.
     private static final int TEXT_HANDLE_FADE_IN_DELAY = 300;
 
+    // These values are obtained from Samsung.
+    // TODO(changwan): refactor SPen related code into a separate class. See
+    // http://crbug.com/398169.
+    private static final int SPEN_ACTION_DOWN = 211;
+    private static final int SPEN_ACTION_UP = 212;
+    private static final int SPEN_ACTION_MOVE = 213;
+    private static final int SPEN_ACTION_CANCEL = 214;
+    private static Boolean sIsSPenSupported;
+
     // If the embedder adds a JavaScript interface object that contains an indirect reference to
     // the ContentViewCore, then storing a strong ref to the interface object on the native
     // side would prevent garbage collection of the ContentViewCore (as that strong ref would
@@ -210,7 +220,7 @@ public class ContentViewCore
      * extractSmartClipData are available.
      */
     public interface SmartClipDataListener {
-        public void onSmartClipDataExtracted(String result);
+        public void onSmartClipDataExtracted(String text, String html, Rect clipRect);
     }
 
     private final Context mContext;
@@ -335,6 +345,10 @@ public class ContentViewCore
     private float mCurrentTouchOffsetX;
     private float mCurrentTouchOffsetY;
 
+    // Offsets for smart clip
+    private int mSmartClipOffsetX;
+    private int mSmartClipOffsetY;
+
     /**
      * Constructs a new ContentViewCore. Embedders must call initialize() after constructing
      * a ContentViewCore and before using it.
@@ -1093,6 +1107,55 @@ public class ContentViewCore
     // End FrameLayout overrides.
 
     /**
+     * TODO(changwan): refactor SPen related code into a separate class. See
+     * http://crbug.com/398169.
+     * @return Whether SPen is supported on the device.
+     */
+    public static boolean isSPenSupported(Context context) {
+        if (sIsSPenSupported == null)
+            sIsSPenSupported = detectSPenSupport(context);
+        return sIsSPenSupported.booleanValue();
+    }
+
+    private static boolean detectSPenSupport(Context context) {
+        if (!"SAMSUNG".equalsIgnoreCase(Build.MANUFACTURER))
+            return false;
+
+        final FeatureInfo[] infos = context.getPackageManager().getSystemAvailableFeatures();
+        for (FeatureInfo info : infos) {
+            if ("com.sec.feature.spen_usp".equalsIgnoreCase(info.name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Convert SPen event action into normal event action.
+     * TODO(changwan): refactor SPen related code into a separate class. See
+     * http://crbug.com/398169.
+     *
+     * @param eventActionMasked Input event action. It is assumed that it is masked as the values
+                                cannot be ORed.
+     * @return Event action after the conversion
+     */
+    public static int convertSPenEventAction(int eventActionMasked) {
+        // S-Pen support: convert to normal stylus event handling
+        switch (eventActionMasked) {
+            case SPEN_ACTION_DOWN:
+                return MotionEvent.ACTION_DOWN;
+            case SPEN_ACTION_UP:
+                return MotionEvent.ACTION_UP;
+            case SPEN_ACTION_MOVE:
+                return MotionEvent.ACTION_MOVE;
+            case SPEN_ACTION_CANCEL:
+                return MotionEvent.ACTION_CANCEL;
+            default:
+                return eventActionMasked;
+        }
+    }
+
+    /**
      * @see View#onTouchEvent(MotionEvent)
      */
     public boolean onTouchEvent(MotionEvent event) {
@@ -1100,7 +1163,10 @@ public class ContentViewCore
         try {
             cancelRequestToScrollFocusedEditableNodeIntoView();
 
-            final int eventAction = event.getActionMasked();
+            int eventAction = event.getActionMasked();
+
+            if (isSPenSupported(mContext))
+                eventAction = convertSPenEventAction(eventAction);
 
             // Only these actions have any effect on gesture detection.  Other
             // actions have no corresponding WebTouchEvent type and may confuse the
@@ -1132,7 +1198,10 @@ public class ContentViewCore
                     pointerCount > 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.
+     *
+     * <p>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);
index 63c829e..5b62432 100644 (file)
@@ -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<String,String> 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 (file)
index 0000000..346f217
--- /dev/null
@@ -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);
+}
index 3da256e..c481b10 100644 (file)
@@ -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);
 }
index c68ace6..5bd2dab 100644 (file)
@@ -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();
index 7eae2d6..a6adc96 100644 (file)
@@ -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<String,String> mHeaders = null;
         String mPath = null;
+        int mFd;
+        long mOffset;
+        long mLength;
 
         // Write these before tests to configure functionality
         SparseArray<String> 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<String, String> 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));
index 61d8b85..3de44ee 100644 (file)
@@ -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)
index b3105d0..b9a7ad4 100644 (file)
@@ -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
index 8a49e04..caa66af 100644 (file)
@@ -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
index d87b67c..caefc9d 100644 (file)
@@ -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<void(Status, const GURL&, const GURL&, bool)> 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<void(Status)> 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_;
 
index ffde792..41a7b89 100644 (file)
@@ -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_;
index f3e0bc0..88af474 100644 (file)
@@ -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));
 }
index 4bcb288..e8698c9 100644 (file)
@@ -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);
index a7e9401..33b1fc0 100644 (file)
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <limits>
 
+#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);
index 67d09e0..f20d0ae 100644 (file)
@@ -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<media::VideoFrame>& 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<StreamTextureFactory> 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<WebMediaPlayerAndroid> 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 (file)
index 0000000..90bbab2
--- /dev/null
@@ -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 <dwrite.h>
+
+#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<SC_HANDLE>(0xdeadbeef);
+}
+
+SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager,
+                                   const wchar_t* service_name,
+                                   DWORD access_mask) {
+  ::SetLastError(0);
+  return reinterpret_cast<SC_HANDLE>(0xdeadbabe);
+}
+
+BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) {
+  if (service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbabe) &&
+      service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbeef))
+    CHECK(false);
+  ::SetLastError(0);
+  return TRUE;
+}
+
+BOOL WINAPI StartServiceWPatch(SC_HANDLE service,
+                               DWORD args,
+                               const wchar_t** arg_vectors) {
+  if (service != reinterpret_cast<SC_HANDLE>(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<DWriteCreateFactoryProc>(
+          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<IUnknown**>(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<PROC**>(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
index 679da54..57d1920 100644 (file)
@@ -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 (file)
index 0000000..2087046
--- /dev/null
@@ -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 <dwrite.h>
+#include <string>
+#include <vector>
+#include <wrl/implements.h>
+#include <wrl/wrappers/corewrappers.h>
+
+#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<mswr::RuntimeClassFlags<mswr::ClassicCom>,
+                                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<IDWriteFontFileLoader> file_loader_;
+
+  std::vector<std::wstring> reg_fonts_;
+};
+
+mswr::ComPtr<FontCollectionLoader> g_font_loader;
+
+class FontFileStream
+    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
+                                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<BYTE const*>(memory_->data()) +
+                      static_cast<size_t>(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<base::MemoryMappedFile> memory_;
+};
+
+class FontFileLoader
+    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
+                                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<const UINT32*>(ref_key);
+    mswr::ComPtr<FontFileStream> font_stream;
+    HRESULT hr = mswr::MakeAndInitialize<FontFileStream>(&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<mswr::RuntimeClassFlags<mswr::ClassicCom>,
+                                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<IDWriteFactory> factory_;
+  mswr::ComPtr<IDWriteFontFile> current_file_;
+  mswr::ComPtr<IDWriteFontFileLoader> 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<FontFileEnumerator>(
+                         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<FontCollectionLoader>();
+  if (!g_font_loader) {
+    DCHECK(FALSE);
+    return E_FAIL;
+  }
+
+  CHECK(g_font_loader->LoadFontListFromRegistry());
+
+  g_font_loader->file_loader_ = mswr::Make<FontFileLoader>().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<base::FilePath::StringType> components;
+      path.GetComponents(&components);
+      if (components.size() == 1) {
+        reg_fonts_.push_back(value.c_str());
+      }
+    }
+  }
+  return true;
+}
+
+}  // namespace
+
+namespace content {
+
+mswr::ComPtr<IDWriteFontCollection> 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 (file)
index 0000000..a04901b
--- /dev/null
@@ -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_
index 3cd5a12..83f50e8 100644 (file)
@@ -95,6 +95,8 @@
                  android:permission="org.chromium.content_shell.permission.SANDBOX"
                  android:isolatedProcess="true"
                  android:exported="false" />
+        <meta-data android:name="org.chromium.content.browser.SMART_CLIP_PROVIDER"
+                   android:value="org.chromium.content.browser.SmartClipProvider" />
     </application>
 
     <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
index e27e82e..6f128f5 100644 (file)
@@ -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;
index 7b9c893..8db28cc 100644 (file)
@@ -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
index 02ac2f6..5a829e9 100644 (file)
@@ -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(
index bcd2dd4..991f2b5 100644 (file)
@@ -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"
+      ]
     }
   ]
 }
index 19fc47b..e0a0b42 100644 (file)
@@ -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<size_t>(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);
   }
 }
 
index 1539793..357352a 100644 (file)
@@ -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<uint32_t>(-1);
-  pa_buffer_attributes.minreq = params.GetBytesPerBuffer();
+  pa_buffer_attributes.minreq = params.GetBytesPerBuffer() / 2;
   pa_buffer_attributes.prebuf = static_cast<uint32_t>(-1);
   pa_buffer_attributes.tlength = params.GetBytesPerBuffer() * 3;
   pa_buffer_attributes.fragsize = static_cast<uint32_t>(-1);
index ecf8387..81d6798 100644 (file)
@@ -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);
index a5299d9..d575c27 100644 (file)
@@ -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);
index 9628aa1..6d0ad91 100644 (file)
@@ -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<jstring> j_url_string = ConvertUTF8ToJavaString(env, url);
-  ScopedJavaLocalRef<jstring> j_cookies = ConvertUTF8ToJavaString(
-      env, cookies_);
-  ScopedJavaLocalRef<jstring> 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<jstring> 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<jstring> j_cookies = ConvertUTF8ToJavaString(
+        env, cookies_);
+    ScopedJavaLocalRef<jstring> 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(
index f63d626..792ebc1 100644 (file)
@@ -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<MediaPlayerBridge> weak_factory_;
index 0b79f18..be84b08 100644 (file)
@@ -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;
index 075f9d0..72f204f 100644 (file)
@@ -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
index 604c195..09b031c 100644 (file)
@@ -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 (file)
index 0000000..e1db623
--- /dev/null
@@ -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 <string>
+
+#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_
index 62b39c1..f5b4fdd 100644 (file)
@@ -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() {
index d5cff8c..02682bb 100644 (file)
@@ -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<base::TimeDelta> buffered_ranges_;
 
   DecoderBufferQueue buffer_queue_;
index 71099e9..25497d1 100644 (file)
             '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',
index 7b57396..63bfb30 100644 (file)
@@ -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 (file)
index 0000000..50fc47e
--- /dev/null
@@ -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 (file)
index 0000000..b520061
--- /dev/null
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<link rel="import" href="resources/import-layout-with-pending-sheet.html">
+<p>PASS if this test didn't crash.</p>
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 (file)
index 0000000..366e415
--- /dev/null
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+setTimeout(function(){
+    document.querySelector("link").import.querySelector("p").scrollLeft;
+}, 0);
+</script>
+<p></p>
+<link rel="stylesheet" href="style.css">
index 68bf2f9..8eccef9 100644 (file)
@@ -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();
     }
 }
 
index 20b7363..90fc417 100644 (file)
@@ -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
index 40c773e..329412c 100644 (file)
@@ -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<LocalFrame> frame)
index 21955a2..76b0c49 100644 (file)
@@ -50,7 +50,8 @@ public:
     {
     }
 
-    String toString();
+    IntRect rect() const;
+    const String& clipData() const;
 
 private:
     bool m_isEmpty;
index 4993b76..5991c02 100644 (file)
@@ -313,6 +313,9 @@ public:
 
     PassRefPtr<WebCore::LocalFrame> 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;
index be30687..55b2276 100644 (file)
@@ -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);
index 45b0dfe..26dd7e3 100644 (file)
@@ -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;
index 6eed6fc..2c16122 100644 (file)
 #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 = Range::create(*startPosition.document(), startPosition, endPosition);
+    if (!range)
+        return;
+
+    clipHtml = createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
 }
 
 void WebViewImpl::hidePopups()
index 66ec102..9b42e4a 100644 (file)
@@ -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;
index d248761..31fbdaf 100644 (file)
@@ -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;
index 4d6dd81..af2752f 100644 (file)
@@ -1548,6 +1548,26 @@ TEST_F(WebViewTest, DispatchesFocusBlurOnViewToggle)
 
 TEST_F(WebViewTest, SmartClipData)
 {
+    static const char* kExpectedClipText = "\nPrice 10,000,000won";
+    static const char* kExpectedClipHtml =
+        "<div id=\"div4\" style=\"padding: 10px; margin: 10px; border: 2px "
+        "solid rgb(135, 206, 235); float: left; width: 190px; height: 30px; "
+        "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
+        "normal; font-variant: normal; font-weight: normal; letter-spacing: "
+        "normal; line-height: normal; orphans: auto; text-align: start; "
+        "text-indent: 0px; text-transform: none; white-space: normal; widows: "
+        "auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;\">Air "
+        "conditioner</div><div id=\"div5\" style=\"padding: 10px; margin: "
+        "10px; border: 2px solid rgb(135, 206, 235); float: left; width: "
+        "190px; height: 30px; color: rgb(0, 0, 0); font-family: myahem; "
+        "font-size: 8px; font-style: normal; font-variant: normal; "
+        "font-weight: normal; letter-spacing: normal; line-height: normal; "
+        "orphans: auto; text-align: start; text-indent: 0px; text-transform: "
+        "none; white-space: normal; widows: auto; word-spacing: 0px; "
+        "-webkit-text-stroke-width: 0px;\">Price 10,000,000won</div>";
+    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 {
index 3ea9d69..95c85a3 100644 (file)
@@ -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;
index 098baac..a0525bc 100644 (file)
@@ -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 ----------------------------------------------------------
 
index 5520c86..5cc2c14 100644 (file)
@@ -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 &registerString = TString("register(") + RegisterPrefix(type) + str(registerIndex) + ")";
 
index 7391ac5..0f0f94b 100644 (file)
@@ -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<Uri, Void, String[]> {
+        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);
index 87d25b1..5cf693d 100644 (file)
@@ -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);
index 11eeaa0..23e0b23 100644 (file)
@@ -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<aura::Window> 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 {
index c668609..ec3513a 100644 (file)
@@ -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<std::string, KeyboardCode>::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<KeyboardCode, std::string>::const_iterator it =
+        map_key_dom_.find(key_code);
+    return (it == map_key_dom_.end()) ? "" : it->second;
   }
 
  private:
-  std::map<std::string, KeyboardCode> map_;
+  std::map<std::string, KeyboardCode> map_dom_key_;
+  std::map<KeyboardCode, std::string> map_key_dom_;
 };
 
 base::LazyInstance<KeyCodeMap>::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
index 7d41b3f..a4cdf0d 100644 (file)
@@ -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_
index 26c4b1e..e4dba26 100644 (file)
@@ -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",
index 890708d..8f8e911 100644 (file)
         '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',
         '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',
index 985aa37..2d122fd 100644 (file)
 #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 {
index 3cf4235..b69a38f 100644 (file)
@@ -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<MotionEvent> Clone() const = 0;
   virtual scoped_ptr<MotionEvent> Cancel() const = 0;
index a5471f7..c7e744a 100644 (file)
@@ -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 {
 
index eda1606..326c710 100644 (file)
@@ -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 {
index 2bf4e9b..6eea922 100644 (file)
@@ -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<MotionEvent> MotionEventAura::Clone() const {
   return scoped_ptr<MotionEvent>(new MotionEventAura(pointer_count_,
                                                      last_touch_time_,
index 7ebf264..bf0a502 100644 (file)
@@ -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<MotionEvent> Clone() const OVERRIDE;
   virtual scoped_ptr<MotionEvent> Cancel() const OVERRIDE;
@@ -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<MotionEvent> MockMotionEvent::Clone() const {
   return scoped_ptr<MotionEvent>(new MockMotionEvent(*this));
 }
@@ -166,12 +190,14 @@ void MockMotionEvent::PressPoint(float x, float y) {
 
   DCHECK_LT(pointer_count, static_cast<size_t>(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
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 (file)
@@ -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<gfx::PointF>& 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<MotionEvent> Clone() const OVERRIDE;
   virtual scoped_ptr<MotionEvent> 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
index df38d30..593ac99 100644 (file)
@@ -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;
   }
 }
 
index 1965cc6..94fa5a4 100644 (file)
@@ -6860,8 +6860,8 @@ bool JSObject::DefineFastAccessor(Handle<JSObject> 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);
     }
index 1d8adfe..d6c5135 100644 (file)
@@ -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
index a953f4a..a5d61b4 100644 (file)
@@ -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),
index 241fde3..be6e501 100644 (file)
@@ -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;
index 0938474..af51ed2 100644 (file)
@@ -27,7 +27,7 @@
 <translation id="1930711995431081526">статус</translation>
 <translation id="658823671542763450">пређите на режим целог екрана</translation>
 <translation id="7720026100085573005">преостало време</translation>
-<translation id="370665806235115550">Учитавање...</translation>
+<translation id="370665806235115550">Учитава се...</translation>
 <translation id="2723001399770238859">аудио</translation>
 <translation id="6845533974506654842">притисни</translation>
 <translation id="8244226242650769279">мапа слике</translation>
index 1e50bdb..65b6c59 100644 (file)
@@ -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'
index 5fc5c3c..2bdd6d4 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR=9
 MINOR=37
-BUILD=195
+BUILD=197
 PATCH=0
index 27e29f9..ee32215 100644 (file)
@@ -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);
 }
 
index 97bc9fa..091652a 100644 (file)
@@ -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<SecurityPolicy> security_policy_;
+  // Remote debugging enabled or not for this Application
+  bool remote_debugging_enabled_;
   // WeakPtrFactory should be always declared the last.
   base::WeakPtrFactory<Application> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(Application);
index ab30ddc..603f938 100644 (file)
@@ -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<GURL>(
   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);
 }
index 09fd3b4..b020e31 100644 (file)
@@ -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<dbus::Response> 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()) {
index 88d9aa7..244d09f 100644 (file)
@@ -105,6 +105,8 @@ bool PackageInstaller::Install(const base::FilePath& path, std::string* id) {
   scoped_ptr<Package> package;
   if (!base::DirectoryExists(path)) {
     package = Package::Create(path);
+    if (!package->IsValid())
+      return false;
     package->Extract(&unpacked_dir);
     app_id = package->Id();
   } else {
index 8f69b2e..19116c2 100644 (file)
@@ -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<std::string> reference_set_;
   std::list<std::string> certificate_list_;
-  ReferenceHashMap reference_hash_map_;
 
   DISALLOW_COPY_AND_ASSIGN(SignatureData);
 };
index 3dc0586..a50b158 100644 (file)
@@ -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<std::string> 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>
-    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 <DigestMethod>
-    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 <DigestValue>
-    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;
 }
index 66b9f72..b04281e 100644 (file)
@@ -4,13 +4,16 @@
 
 #include "xwalk/application/common/installer/tizen/signature_validator.h"
 
+#include <set>
 #include <string>
 #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<SignatureFile> 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<std::string> 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;
index ffb4584..abe0ca7 100644 (file)
@@ -5,13 +5,7 @@
 #ifndef XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_SIGNATURE_VALIDATOR_H_
 #define XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_SIGNATURE_VALIDATOR_H_
 
-#include <set>
-#include <string>
-
 #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 (file)
index c26d4f9..0000000
+++ /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 <map>
-#include <string>
-
-namespace xwalk {
-namespace application {
-
-struct ReferenceData {
-  std::string transform_algorithm;
-  std::string digest_method;
-  std::string digest_value;
-};
-
-typedef std::map<std::string, ReferenceData> ReferenceHashMap;
-}  // namespace application
-}  // namespace xwalk
-
-#endif  // XWALK_APPLICATION_COMMON_SIGNATURE_TYPES_H_
index 66c77cf..57816d2 100644 (file)
@@ -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;
 }
index be469ac..0c4c436 100644 (file)
@@ -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<dbus::Bus> 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)
index d84106c..6bd9331 100644 (file)
@@ -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.
index 41ce248..6f44052 100644 (file)
@@ -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() {
index 2a44fb5..dad18a3 100644 (file)
@@ -747,6 +747,7 @@ public class XWalkViewInternal extends android.widget.FrameLayout {
      *
      * @hide
      */
+    @XWalkAPI
     public void setNetworkAvailable(boolean networkUp) {
         if (mContent == null) return;
         checkThreadSafety();
index 5a5646a..0d07705 100644 (file)
@@ -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<content::ZygoteForkDelegate>* delegates) {
 #if !defined(DISABLE_NACL)
index fea8351..268ad65 100644 (file)
@@ -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<content::ZygoteForkDelegate>* delegates) OVERRIDE;
 #endif
index 328a2a9..a1aa64a 100644 (file)
@@ -135,8 +135,12 @@ void XWalkDevToolsDelegate::EnumerateTargets(TargetCallback callback) {
   for (std::vector<RenderViewHost*>::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<Runtime*>(web_contents->GetDelegate());
+      if (runtime && runtime->remote_debugging_enabled()) {
+        targets.push_back(new Target(web_contents));
+      }
+    }
   }
   callback.Run(targets);
 }
index 929a474..4f8f9ba 100644 (file)
@@ -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(
index 51be3f3..5b48ab5 100644 (file)
@@ -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_;
 };
index 8f2ed01..450063c 100644 (file)
@@ -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 {
 
index bcbeb6f..47ce92e 100644 (file)
@@ -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 (file)
index 0000000..c2c5a18
--- /dev/null
@@ -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 (file)
index 0000000..fec6e3e
--- /dev/null
@@ -0,0 +1,19 @@
+<html>
+<head>
+<script>
+  function launchFullscreen(element) {
+    element.webkitRequestFullscreen();
+  }
+
+  function exitFullscreen() {
+    document.webkitExitFullscreen();
+  }
+</script>
+</head>
+<body>
+  <div>
+    <button id="enter_fullscreen" onclick="launchFullscreen(document.documentElement);">Launch Fullscreen</button>
+    <button id="exit_fullscreen" onclick="exitFullscreen();">Exit Fullscreen</button>
+  </div>
+</body>
+</html>
index d71a9e7..ee43528 100644 (file)
           '<(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',
             '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',