summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
authorjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-07-06 15:53:52 +0200
committerjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-07-06 15:53:52 +0200
commit941e54654eabed0a3568f7fefe424a45aa02eddb (patch)
tree49aa02b174c428962d99142d8061267bfcd79e69 /dom
parentad9ee72dcd7981bc47b3844a224d69fadfdfd8ef (diff)
parent0daa12376295d5d796256a116eb2a348a3a9273f (diff)
downloadUXP-941e54654eabed0a3568f7fefe424a45aa02eddb.tar
UXP-941e54654eabed0a3568f7fefe424a45aa02eddb.tar.gz
UXP-941e54654eabed0a3568f7fefe424a45aa02eddb.tar.lz
UXP-941e54654eabed0a3568f7fefe424a45aa02eddb.tar.xz
UXP-941e54654eabed0a3568f7fefe424a45aa02eddb.zip
Merge branch 'master' of https://github.com/MoonchildProductions/UXP into _testBranch_test_1
Diffstat (limited to 'dom')
-rw-r--r--dom/animation/Animation.cpp48
-rw-r--r--dom/animation/Animation.h10
-rw-r--r--dom/animation/AnimationEffectReadOnly.cpp18
-rw-r--r--dom/animation/ComputedTiming.h6
-rw-r--r--dom/animation/test/css-animations/file_event-dispatch.html252
-rw-r--r--dom/animation/test/css-animations/file_event-order.html160
-rw-r--r--dom/animation/test/css-animations/test_event-dispatch.html15
-rw-r--r--dom/animation/test/css-animations/test_event-order.html (renamed from dom/animation/test/css-transitions/test_csstransition-events.html)3
-rw-r--r--dom/animation/test/css-transitions/file_animation-cancel.html182
-rw-r--r--dom/animation/test/css-transitions/file_csstransition-events.html223
-rw-r--r--dom/animation/test/css-transitions/file_event-dispatch.html474
-rw-r--r--dom/animation/test/css-transitions/file_setting-effect.html9
-rw-r--r--dom/animation/test/css-transitions/test_event-dispatch.html14
-rw-r--r--dom/animation/test/mochitest.ini6
-rw-r--r--dom/apps/AppsUtils.jsm3
-rw-r--r--dom/audiochannel/AudioChannelService.cpp32
-rw-r--r--dom/audiochannel/AudioChannelService.h22
-rw-r--r--dom/base/DOMIntersectionObserver.cpp37
-rw-r--r--dom/base/DOMIntersectionObserver.h4
-rw-r--r--dom/base/Element.cpp69
-rw-r--r--dom/base/Element.h2
-rwxr-xr-xdom/base/File.cpp2
-rw-r--r--dom/base/FragmentOrElement.cpp9
-rw-r--r--dom/base/FragmentOrElement.h8
-rw-r--r--dom/base/IdleRequest.cpp119
-rw-r--r--dom/base/IdleRequest.h40
-rw-r--r--dom/base/Location.cpp41
-rw-r--r--dom/base/Navigator.cpp6
-rw-r--r--dom/base/ScreenOrientation.cpp2
-rw-r--r--dom/base/StructuredCloneHolder.cpp34
-rw-r--r--dom/base/Timeout.h8
-rw-r--r--dom/base/TimeoutHandler.cpp43
-rw-r--r--dom/base/TimeoutHandler.h50
-rw-r--r--dom/base/WebSocket.cpp8
-rwxr-xr-xdom/base/moz.build7
-rw-r--r--dom/base/nsContentPermissionHelper.cpp3
-rw-r--r--dom/base/nsContentPolicy.cpp6
-rw-r--r--dom/base/nsContentPolicyUtils.h1
-rw-r--r--dom/base/nsContentUtils.cpp12
-rw-r--r--dom/base/nsContentUtils.h9
-rw-r--r--dom/base/nsDOMNavigationTiming.cpp138
-rw-r--r--dom/base/nsDOMNavigationTiming.h125
-rw-r--r--dom/base/nsDocument.cpp40
-rw-r--r--dom/base/nsFrameMessageManager.cpp5
-rw-r--r--dom/base/nsGkAtomList.h5
-rw-r--r--dom/base/nsGlobalWindow.cpp514
-rw-r--r--dom/base/nsGlobalWindow.h51
-rw-r--r--dom/base/nsIContentPolicy.idl2
-rw-r--r--dom/base/nsIContentPolicyBase.idl16
-rw-r--r--dom/base/nsIDocument.h47
-rw-r--r--dom/base/nsINode.cpp24
-rw-r--r--dom/base/nsISelectionPrivate.idl2
-rw-r--r--dom/base/nsISimpleContentPolicy.idl2
-rw-r--r--dom/base/nsJSEnvironment.cpp109
-rw-r--r--dom/base/nsNodeUtils.cpp9
-rw-r--r--dom/base/nsPIDOMWindow.h20
-rw-r--r--dom/base/nsStructuredCloneContainer.cpp2
-rw-r--r--dom/base/test/bug704320.sjs6
-rw-r--r--dom/base/test/file_ipc_messagemanager_blob.html1
-rw-r--r--dom/base/test/file_simplecontentpolicy.js1
-rw-r--r--dom/base/test/mochitest.ini1
-rw-r--r--dom/base/test/referrerHelper.js3
-rw-r--r--dom/base/test/test_intersectionobservers.html59
-rw-r--r--dom/base/test/test_ipc_messagemanager_blob.html3
-rw-r--r--dom/base/test/test_x-frame-options.html6
-rw-r--r--dom/bindings/BindingUtils.cpp20
-rw-r--r--dom/bindings/Codegen.py14
-rw-r--r--dom/bindings/DOMJSProxyHandler.cpp4
-rw-r--r--dom/bindings/ErrorResult.h2
-rw-r--r--dom/broadcastchannel/BroadcastChannel.cpp6
-rw-r--r--dom/browser-element/mochitest/browserElementTestHelpers.js4
-rw-r--r--dom/browser-element/mochitest/browserElement_BrowserWindowResize.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_Close.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_ContextmenuEvents.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_CopyPaste.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_DataURI.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_Iconchange.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_Manifestchange.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_Metachange.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_Opensearch.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_PromptCheck.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_PromptConfirm.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_ScrollEvent.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_Titlechange.js1
-rw-r--r--dom/browser-element/mochitest/browserElement_TopBarrier.js1
-rw-r--r--dom/cache/Cache.cpp2
-rw-r--r--dom/cache/DBSchema.cpp3
-rw-r--r--dom/canvas/CanvasRenderingContext2D.cpp42
-rw-r--r--dom/canvas/CanvasRenderingContext2D.h9
-rw-r--r--dom/canvas/ImageBitmap.cpp11
-rw-r--r--dom/canvas/WebGLContext.cpp32
-rw-r--r--dom/canvas/WebGLContextDraw.cpp21
-rw-r--r--dom/canvas/test/webgl-mochitest/driver-info.js3
-rwxr-xr-xdom/console/Console.cpp5
-rw-r--r--dom/console/Console.h10
-rw-r--r--dom/downloads/DownloadsAPI.js517
-rw-r--r--dom/downloads/DownloadsAPI.jsm365
-rw-r--r--dom/downloads/DownloadsAPI.manifest6
-rw-r--r--dom/downloads/DownloadsIPC.jsm224
-rw-r--r--dom/downloads/moz.build21
-rw-r--r--dom/downloads/tests/clear_all_done_helper.js67
-rw-r--r--dom/downloads/tests/mochitest.ini15
-rw-r--r--dom/downloads/tests/serve_file.sjs170
-rw-r--r--dom/downloads/tests/test_downloads_bad_file.html93
-rw-r--r--dom/downloads/tests/test_downloads_basic.html128
-rw-r--r--dom/downloads/tests/test_downloads_large.html110
-rw-r--r--dom/downloads/tests/test_downloads_navigator_object.html75
-rw-r--r--dom/downloads/tests/test_downloads_pause_remove.html117
-rw-r--r--dom/downloads/tests/test_downloads_pause_resume.html121
-rw-r--r--dom/encoding/FallbackEncoding.cpp3
-rwxr-xr-xdom/events/Event.cpp42
-rw-r--r--dom/events/EventDispatcher.cpp5
-rw-r--r--dom/events/EventListenerManager.cpp42
-rw-r--r--dom/events/EventNameList.h30
-rw-r--r--dom/events/EventStateManager.cpp120
-rw-r--r--dom/events/EventStateManager.h10
-rw-r--r--dom/events/KeyNameList.h4
-rw-r--r--dom/events/PointerEvent.cpp14
-rw-r--r--dom/events/PointerEvent.h2
-rw-r--r--dom/events/TouchEvent.cpp2
-rw-r--r--dom/events/WheelHandlingHelper.cpp1
-rw-r--r--dom/events/moz.build5
-rw-r--r--dom/events/test/mochitest.ini1
-rw-r--r--dom/events/test/pointerevents/mochitest.ini17
-rw-r--r--dom/events/test/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html65
-rw-r--r--dom/events/test/pointerevents/test_bug1285128.html7
-rw-r--r--dom/events/test/pointerevents/test_bug1323158.html93
-rw-r--r--dom/events/test/pointerevents/test_pointerevent_capture_suppressing_mouse-manual.html3
-rw-r--r--dom/events/test/pointerevents/test_pointerevent_releasepointercapture_events_to_original_target-manual.html27
-rw-r--r--dom/events/test/pointerevents/test_pointerevent_setpointercapture_relatedtarget-manual.html4
-rw-r--r--dom/events/test/pointerevents/test_trigger_fullscreen_by_pointer_events.html57
-rw-r--r--dom/events/test/pointerevents/test_trigger_popup_by_pointer_events.html76
-rw-r--r--dom/events/test/test_bug1304044.html133
-rw-r--r--dom/events/test/test_eventTimeStamp.html36
-rw-r--r--dom/events/test/test_legacy_event.html21
-rw-r--r--dom/fetch/InternalHeaders.cpp58
-rw-r--r--dom/fetch/InternalHeaders.h31
-rw-r--r--dom/fetch/InternalRequest.cpp3
-rw-r--r--dom/fetch/InternalRequest.h2
-rw-r--r--dom/fetch/Request.cpp20
-rw-r--r--dom/fetch/Response.cpp8
-rw-r--r--dom/fetch/Response.h2
-rw-r--r--dom/filesystem/tests/test_webkitdirectory.html1
-rw-r--r--dom/geolocation/moz.build4
-rw-r--r--dom/geolocation/nsGeolocation.cpp13
-rw-r--r--dom/html/HTMLInputElement.cpp461
-rw-r--r--dom/html/HTMLInputElement.h96
-rw-r--r--dom/html/HTMLMediaElement.cpp47
-rw-r--r--dom/html/HTMLMediaElement.h12
-rw-r--r--dom/html/nsHTMLDocument.cpp18
-rw-r--r--dom/html/nsHTMLDocument.h1
-rw-r--r--dom/html/nsIFormControl.h6
-rw-r--r--dom/html/nsTextEditorState.cpp31
-rw-r--r--dom/html/nsTextEditorState.h2
-rw-r--r--dom/html/test/forms/mochitest.ini8
-rw-r--r--dom/html/test/forms/test_input_date_key_events.html228
-rw-r--r--dom/html/test/forms/test_input_datetime_focus_blur.html28
-rw-r--r--dom/html/test/forms/test_input_datetime_focus_blur_events.html90
-rw-r--r--dom/html/test/forms/test_input_datetime_input_change_events.html88
-rw-r--r--dom/html/test/forms/test_input_datetime_tabindex.html47
-rw-r--r--dom/html/test/forms/test_input_time_focus_blur_events.html82
-rw-r--r--dom/html/test/forms/test_input_types_pref.html48
-rw-r--r--dom/html/test/forms/test_input_typing_sanitization.html28
-rw-r--r--dom/html/test/forms/test_max_attribute.html47
-rw-r--r--dom/html/test/forms/test_min_attribute.html49
-rw-r--r--dom/html/test/forms/test_step_attribute.html102
-rw-r--r--dom/html/test/forms/test_stepup_stepdown.html174
-rw-r--r--dom/html/test/forms/test_valueAsDate_pref.html8
-rw-r--r--dom/html/test/forms/test_valueasdate_attribute.html108
-rw-r--r--dom/html/test/forms/test_valueasnumber_attribute.html123
-rw-r--r--dom/html/test/test_anchor_ping.html7
-rw-r--r--dom/html/test/test_bug558788-1.html5
-rw-r--r--dom/html/test/test_fullscreen-api-race.html4
-rw-r--r--dom/indexedDB/ActorsParent.cpp87
-rw-r--r--dom/indexedDB/IDBCursor.cpp10
-rw-r--r--dom/indexedDB/IDBCursor.h2
-rw-r--r--dom/indexedDB/IDBObjectStore.cpp28
-rw-r--r--dom/indexedDB/IDBObjectStore.h2
-rw-r--r--dom/indexedDB/IndexedDatabase.h4
-rw-r--r--dom/indexedDB/IndexedDatabaseInlines.h11
-rw-r--r--dom/indexedDB/IndexedDatabaseManager.cpp21
-rw-r--r--dom/indexedDB/IndexedDatabaseManager.h4
-rw-r--r--dom/indexedDB/Key.cpp6
-rw-r--r--dom/indexedDB/Key.h4
-rw-r--r--dom/indexedDB/moz.build3
-rw-r--r--dom/indexedDB/test/browser_forgetThisSite.js7
-rw-r--r--dom/indexedDB/test/unit/xpcshell-child-process.ini2
-rw-r--r--dom/indexedDB/test/unit/xpcshell-parent-process.ini1
-rw-r--r--dom/inputmethod/HardwareKeyHandler.cpp562
-rw-r--r--dom/inputmethod/HardwareKeyHandler.h224
-rw-r--r--dom/inputmethod/Keyboard.jsm16
-rw-r--r--dom/inputmethod/moz.build23
-rw-r--r--dom/inputmethod/nsIHardwareKeyHandler.idl142
-rw-r--r--dom/ipc/ContentChild.cpp330
-rw-r--r--dom/ipc/ContentChild.h36
-rw-r--r--dom/ipc/ContentParent.cpp373
-rw-r--r--dom/ipc/ContentParent.h36
-rw-r--r--dom/ipc/ContentProcess.cpp113
-rw-r--r--dom/ipc/ContentProcess.h8
-rw-r--r--dom/ipc/CrashReporterChild.cpp42
-rw-r--r--dom/ipc/CrashReporterChild.h32
-rw-r--r--dom/ipc/CrashReporterParent.cpp63
-rw-r--r--dom/ipc/CrashReporterParent.h70
-rw-r--r--dom/ipc/DatePickerParent.cpp87
-rw-r--r--dom/ipc/DatePickerParent.h61
-rw-r--r--dom/ipc/PBrowser.ipdl8
-rw-r--r--dom/ipc/PContent.ipdl17
-rw-r--r--dom/ipc/PCrashReporter.ipdl31
-rw-r--r--dom/ipc/PDatePicker.ipdl27
-rw-r--r--dom/ipc/StructuredCloneData.cpp4
-rw-r--r--dom/ipc/StructuredCloneData.h23
-rw-r--r--dom/ipc/TabChild.cpp16
-rw-r--r--dom/ipc/TabChild.h4
-rw-r--r--dom/ipc/TabContext.cpp7
-rw-r--r--dom/ipc/TabParent.cpp15
-rw-r--r--dom/ipc/TabParent.h4
-rw-r--r--dom/ipc/moz.build23
-rw-r--r--dom/ipc/tests/test_cpow_cookies.html3
-rw-r--r--dom/jsurl/nsJSProtocolHandler.cpp49
-rw-r--r--dom/locales/en-US/chrome/layout/HtmlForm.properties1
-rw-r--r--dom/locales/en-US/chrome/plugins.properties3
-rw-r--r--dom/locales/en-US/chrome/security/security.properties3
-rw-r--r--dom/media/AudioConverter.cpp8
-rw-r--r--dom/media/AudioStream.cpp4
-rw-r--r--dom/media/Benchmark.cpp2
-rw-r--r--dom/media/CubebUtils.cpp27
-rw-r--r--dom/media/CubebUtils.h3
-rwxr-xr-xdom/media/DOMMediaStream.cpp102
-rw-r--r--dom/media/DOMMediaStream.h11
-rw-r--r--dom/media/GraphDriver.cpp4
-rw-r--r--dom/media/MediaData.cpp53
-rw-r--r--dom/media/MediaDecoder.cpp14
-rw-r--r--dom/media/MediaDecoder.h6
-rw-r--r--dom/media/MediaDecoderStateMachine.cpp15
-rw-r--r--dom/media/MediaDecoderStateMachine.h5
-rw-r--r--dom/media/MediaManager.cpp25
-rw-r--r--dom/media/MediaPermissionGonk.cpp522
-rw-r--r--dom/media/MediaPermissionGonk.h39
-rw-r--r--dom/media/MediaStreamGraph.cpp4
-rw-r--r--dom/media/MediaStreamTrack.cpp12
-rw-r--r--dom/media/PeerConnection.js18
-rw-r--r--dom/media/android/AndroidMediaPluginHost.cpp12
-rw-r--r--dom/media/encoder/OpusTrackEncoder.cpp5
-rw-r--r--dom/media/encoder/TrackEncoder.cpp5
-rw-r--r--dom/media/encoder/fmp4_muxer/AMRBox.cpp84
-rw-r--r--dom/media/encoder/fmp4_muxer/AMRBox.h50
-rw-r--r--dom/media/encoder/fmp4_muxer/AVCBox.cpp87
-rw-r--r--dom/media/encoder/fmp4_muxer/AVCBox.h59
-rw-r--r--dom/media/encoder/fmp4_muxer/EVRCBox.cpp84
-rw-r--r--dom/media/encoder/fmp4_muxer/EVRCBox.h50
-rw-r--r--dom/media/encoder/fmp4_muxer/ISOControl.cpp415
-rw-r--r--dom/media/encoder/fmp4_muxer/ISOControl.h250
-rw-r--r--dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp1550
-rw-r--r--dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h781
-rw-r--r--dom/media/encoder/fmp4_muxer/ISOMediaWriter.cpp234
-rw-r--r--dom/media/encoder/fmp4_muxer/ISOMediaWriter.h108
-rw-r--r--dom/media/encoder/fmp4_muxer/ISOTrackMetadata.h131
-rw-r--r--dom/media/encoder/fmp4_muxer/MP4ESDS.cpp138
-rw-r--r--dom/media/encoder/fmp4_muxer/MP4ESDS.h87
-rw-r--r--dom/media/encoder/fmp4_muxer/MuxerOperation.h57
-rw-r--r--dom/media/encoder/fmp4_muxer/moz.build22
-rw-r--r--dom/media/encoder/moz.build13
-rw-r--r--dom/media/gmp/GMPChild.cpp146
-rw-r--r--dom/media/gmp/GMPChild.h7
-rw-r--r--dom/media/gmp/GMPLoader.cpp13
-rw-r--r--dom/media/gmp/GMPLoader.h17
-rw-r--r--dom/media/gmp/GMPParent.cpp29
-rw-r--r--dom/media/gmp/GMPParent.h3
-rw-r--r--dom/media/gmp/GMPProcessParent.cpp34
-rw-r--r--dom/media/gmp/GMPService.cpp11
-rw-r--r--dom/media/gmp/GMPServiceParent.cpp16
-rw-r--r--dom/media/gmp/PGMP.ipdl3
-rw-r--r--dom/media/gmp/rlz/GMPDeviceBinding.cpp8
-rw-r--r--dom/media/gmp/rlz/moz.build7
-rw-r--r--dom/media/ipc/VideoDecoderChild.cpp1
-rw-r--r--dom/media/ipc/VideoDecoderManagerParent.cpp2
-rw-r--r--dom/media/mediasink/DecodedStream.cpp11
-rw-r--r--dom/media/mediasink/OutputStreamManager.cpp75
-rw-r--r--dom/media/mediasink/OutputStreamManager.h35
-rw-r--r--dom/media/mediasource/ContainerParser.cpp6
-rw-r--r--dom/media/moz.build13
-rw-r--r--dom/media/ogg/OggCodecState.cpp19
-rw-r--r--dom/media/ogg/OggWriter.cpp5
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp6
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp15
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp4
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp4
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/COPYING.LGPLv2.1504
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/avcodec.h6146
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/avfft.h118
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/vaapi.h86
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/vdpau.h176
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/version.h137
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/attributes.h167
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/avconfig.h6
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/avutil.h365
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/buffer.h291
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/channel_layout.h232
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/common.h560
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/cpu.h130
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/dict.h200
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/error.h126
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/frame.h893
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/hwcontext.h584
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/intfloat.h77
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/log.h362
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/macros.h50
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/mathematics.h242
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/mem.h700
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/pixfmt.h529
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/rational.h214
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/samplefmt.h272
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/version.h139
-rw-r--r--dom/media/platforms/ffmpeg/ffmpeg58/moz.build (renamed from dom/speakermanager/moz.build)26
-rw-r--r--dom/media/platforms/ffmpeg/moz.build1
-rw-r--r--dom/media/platforms/gonk/GonkAudioDecoderManager.cpp268
-rw-r--r--dom/media/platforms/gonk/GonkAudioDecoderManager.h59
-rw-r--r--dom/media/platforms/gonk/GonkDecoderModule.cpp63
-rw-r--r--dom/media/platforms/gonk/GonkDecoderModule.h37
-rw-r--r--dom/media/platforms/gonk/GonkMediaDataDecoder.cpp385
-rw-r--r--dom/media/platforms/gonk/GonkMediaDataDecoder.h214
-rw-r--r--dom/media/platforms/gonk/GonkVideoDecoderManager.cpp772
-rw-r--r--dom/media/platforms/gonk/GonkVideoDecoderManager.h149
-rw-r--r--dom/media/platforms/gonk/moz.build39
-rw-r--r--dom/media/platforms/moz.build4
-rw-r--r--dom/media/platforms/omx/GonkOmxPlatformLayer.cpp667
-rw-r--r--dom/media/platforms/omx/GonkOmxPlatformLayer.h205
-rw-r--r--dom/media/platforms/omx/OmxPlatformLayer.cpp5
-rw-r--r--dom/media/platforms/omx/moz.build23
-rw-r--r--dom/media/platforms/wmf/DXVA2Manager.cpp9
-rw-r--r--dom/media/standalone/moz.build2
-rw-r--r--dom/media/systemservices/CamerasChild.cpp15
-rw-r--r--dom/media/systemservices/CamerasChild.h11
-rw-r--r--dom/media/systemservices/MediaSystemResourceService.cpp17
-rw-r--r--dom/media/systemservices/moz.build10
-rw-r--r--dom/media/webrtc/MediaEngine.h5
-rw-r--r--dom/media/webrtc/MediaEngineCameraVideoSource.cpp2
-rw-r--r--dom/media/webrtc/MediaEngineDefault.cpp2
-rw-r--r--dom/media/webrtc/MediaEngineWebRTC.cpp2
-rw-r--r--dom/media/webrtc/MediaEngineWebRTCAudio.cpp4
-rw-r--r--dom/moz.build12
-rw-r--r--dom/network/EthernetManager.js655
-rw-r--r--dom/network/EthernetManager.manifest2
-rw-r--r--dom/network/NetUtils.cpp200
-rw-r--r--dom/network/NetUtils.h75
-rw-r--r--dom/network/NetworkStatsDB.jsm1285
-rw-r--r--dom/network/NetworkStatsManager.js388
-rw-r--r--dom/network/NetworkStatsManager.manifest14
-rw-r--r--dom/network/NetworkStatsService.jsm1171
-rw-r--r--dom/network/NetworkStatsServiceProxy.js90
-rw-r--r--dom/network/NetworkStatsServiceProxy.manifest2
-rw-r--r--dom/network/TCPSocket.cpp72
-rw-r--r--dom/network/TCPSocket.h17
-rw-r--r--dom/network/interfaces/moz.build6
-rw-r--r--dom/network/interfaces/nsIEthernetManager.idl137
-rw-r--r--dom/network/interfaces/nsINetworkStatsServiceProxy.idl64
-rw-r--r--dom/network/moz.build22
-rw-r--r--dom/notification/DesktopNotification.h4
-rw-r--r--dom/notification/Notification.cpp6
-rwxr-xr-xdom/performance/Performance.cpp53
-rw-r--r--dom/performance/Performance.h36
-rw-r--r--dom/performance/PerformanceEntry.h21
-rw-r--r--dom/performance/PerformanceMainThread.cpp99
-rw-r--r--dom/performance/PerformanceMainThread.h21
-rw-r--r--dom/performance/PerformanceNavigationTiming.cpp97
-rw-r--r--dom/performance/PerformanceNavigationTiming.h71
-rw-r--r--dom/performance/PerformanceObserver.cpp14
-rw-r--r--dom/performance/PerformanceObserverEntryList.cpp15
-rw-r--r--dom/performance/PerformanceResourceTiming.cpp50
-rw-r--r--dom/performance/PerformanceResourceTiming.h12
-rw-r--r--dom/performance/PerformanceService.cpp46
-rw-r--r--dom/performance/PerformanceService.h48
-rwxr-xr-xdom/performance/PerformanceTiming.cpp71
-rwxr-xr-xdom/performance/PerformanceTiming.h18
-rw-r--r--dom/performance/PerformanceWorker.cpp35
-rw-r--r--dom/performance/PerformanceWorker.h14
-rw-r--r--dom/performance/moz.build4
-rw-r--r--dom/performance/tests/mochitest.ini3
-rw-r--r--dom/performance/tests/performance_observer.html74
-rw-r--r--dom/performance/tests/test_performance_observer.html52
-rw-r--r--dom/performance/tests/test_performance_user_timing.js21
-rw-r--r--dom/performance/tests/test_timeOrigin.html68
-rw-r--r--dom/performance/tests/test_worker_observer.html13
-rw-r--r--dom/performance/tests/worker_performance_observer.html32
-rw-r--r--dom/permission/tests/mochitest.ini1
-rw-r--r--dom/plugins/base/PluginPRLibrary.cpp6
-rw-r--r--dom/plugins/base/PluginPRLibrary.h2
-rw-r--r--dom/plugins/base/nsNPAPIPlugin.cpp1
-rw-r--r--dom/plugins/base/nsPluginInstanceOwner.cpp28
-rw-r--r--dom/plugins/base/nsPluginStreamListenerPeer.cpp18
-rw-r--r--dom/plugins/base/nsPluginTags.cpp25
-rw-r--r--dom/plugins/base/nsPluginTags.h1
-rw-r--r--dom/plugins/ipc/PPluginModule.ipdl15
-rw-r--r--dom/plugins/ipc/PluginLibrary.h2
-rw-r--r--dom/plugins/ipc/PluginModuleChild.cpp68
-rw-r--r--dom/plugins/ipc/PluginModuleChild.h19
-rwxr-xr-xdom/plugins/ipc/PluginModuleParent.cpp202
-rw-r--r--dom/plugins/ipc/PluginModuleParent.h50
-rw-r--r--dom/plugins/ipc/PluginProcessChild.cpp10
-rw-r--r--dom/plugins/ipc/PluginProcessParent.cpp85
-rw-r--r--dom/plugins/ipc/moz.build6
-rw-r--r--dom/plugins/test/mochitest/test_bug813906.html22
-rw-r--r--dom/plugins/test/mochitest/test_pluginstream_err.html8
-rw-r--r--dom/plugins/test/unit/xpcshell.ini1
-rw-r--r--dom/presentation/PresentationSessionInfo.cpp49
-rw-r--r--dom/presentation/provider/PresentationDeviceProviderModule.cpp5
-rw-r--r--dom/promise/Promise.cpp27
-rw-r--r--dom/promise/Promise.h19
-rw-r--r--dom/quota/StorageManager.cpp2
-rw-r--r--dom/secureelement/SEUtils.jsm116
-rw-r--r--dom/secureelement/gonk/ACEService.js139
-rw-r--r--dom/secureelement/gonk/ACEService.manifest2
-rw-r--r--dom/secureelement/gonk/GPAccessRulesManager.js436
-rw-r--r--dom/secureelement/gonk/GPAccessRulesManager.manifest2
-rw-r--r--dom/secureelement/gonk/SecureElement.js514
-rw-r--r--dom/secureelement/gonk/SecureElement.manifest18
-rw-r--r--dom/secureelement/gonk/UiccConnector.js360
-rw-r--r--dom/secureelement/gonk/UiccConnector.manifest17
-rw-r--r--dom/secureelement/gonk/gp_consts.js62
-rw-r--r--dom/secureelement/gonk/nsIAccessControlEnforcer.idl32
-rw-r--r--dom/secureelement/gonk/nsIAccessRulesManager.idl50
-rw-r--r--dom/secureelement/gonk/nsISecureElementConnector.idl124
-rw-r--r--dom/secureelement/gonk/se_consts.js68
-rw-r--r--dom/secureelement/moz.build24
-rw-r--r--dom/security/nsCSPContext.cpp22
-rw-r--r--dom/security/nsCSPService.cpp5
-rw-r--r--dom/security/nsCSPUtils.cpp3
-rw-r--r--dom/security/nsContentSecurityManager.cpp229
-rw-r--r--dom/security/nsContentSecurityManager.h2
-rw-r--r--dom/security/nsMixedContentBlocker.cpp198
-rw-r--r--dom/security/nsMixedContentBlocker.h35
-rw-r--r--dom/security/test/csp/file_frame_ancestors_ro.html1
-rw-r--r--dom/security/test/csp/file_frame_ancestors_ro.html^headers^1
-rw-r--r--dom/security/test/csp/file_nonce_redirector.sjs25
-rw-r--r--dom/security/test/csp/file_nonce_redirects.html23
-rw-r--r--dom/security/test/csp/mochitest.ini6
-rw-r--r--dom/security/test/csp/test_frame_ancestors_ro.html69
-rw-r--r--dom/security/test/csp/test_nonce_redirects.html47
-rw-r--r--dom/security/test/csp/test_referrerdirective.html2
-rw-r--r--dom/security/test/general/browser.ini14
-rw-r--r--dom/security/test/general/browser_test_data_download.js37
-rw-r--r--dom/security/test/general/browser_test_data_text_csv.js37
-rw-r--r--dom/security/test/general/browser_test_toplevel_data_navigations.js54
-rw-r--r--dom/security/test/general/browser_test_view_image_data_navigation.js30
-rw-r--r--dom/security/test/general/file_block_toplevel_data_navigation.html14
-rw-r--r--dom/security/test/general/file_block_toplevel_data_navigation2.html29
-rw-r--r--dom/security/test/general/file_block_toplevel_data_navigation3.html13
-rw-r--r--dom/security/test/general/file_block_toplevel_data_redirect.sjs14
-rw-r--r--dom/security/test/general/file_data_download.html14
-rw-r--r--dom/security/test/general/file_data_text_csv.html14
-rw-r--r--dom/security/test/general/file_toplevel_data_meta_redirect.html10
-rw-r--r--dom/security/test/general/file_toplevel_data_navigations.sjs14
-rw-r--r--dom/security/test/general/file_view_image_data_navigation.html12
-rw-r--r--dom/security/test/general/mochitest.ini12
-rw-r--r--dom/security/test/general/test_allow_opening_data_json.html39
-rw-r--r--dom/security/test/general/test_allow_opening_data_pdf.html41
-rw-r--r--dom/security/test/general/test_block_toplevel_data_img_navigation.html53
-rw-r--r--dom/security/test/general/test_block_toplevel_data_navigation.html86
-rw-r--r--dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html1
-rw-r--r--dom/security/test/hsts/browser.ini19
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_allow_active.js24
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_allow_display.js24
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_block_active.js24
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_block_active_css.js24
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_block_active_with_redir_same.js24
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_block_display.js24
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_cache-timeout.js36
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_hsts_after_mixed.js24
-rw-r--r--dom/security/test/hsts/browser_hsts-priming_no-duplicates.js30
-rw-r--r--dom/security/test/hsts/file_1x1.pngbin17811 -> 0 bytes
-rw-r--r--dom/security/test/hsts/file_priming-top.html84
-rw-r--r--dom/security/test/hsts/file_priming.js4
-rw-r--r--dom/security/test/hsts/file_stylesheet.css0
-rw-r--r--dom/security/test/hsts/file_testserver.sjs66
-rw-r--r--dom/security/test/hsts/head.js308
-rw-r--r--dom/security/test/mixedcontentblocker/test_main.html3
-rw-r--r--dom/security/test/moz.build2
-rw-r--r--dom/settings/SettingsService.js358
-rw-r--r--dom/settings/SettingsService.manifest5
-rw-r--r--dom/settings/moz.build6
-rw-r--r--dom/settings/tests/chrome.ini6
-rw-r--r--dom/settings/tests/test_settings_service.js138
-rw-r--r--dom/settings/tests/test_settings_service.xul19
-rw-r--r--dom/settings/tests/test_settings_service_callback.js47
-rw-r--r--dom/settings/tests/test_settings_service_callback.xul19
-rw-r--r--dom/speakermanager/SpeakerManager.cpp217
-rw-r--r--dom/speakermanager/SpeakerManager.h66
-rw-r--r--dom/speakermanager/SpeakerManagerService.cpp224
-rw-r--r--dom/speakermanager/SpeakerManagerService.h79
-rw-r--r--dom/speakermanager/SpeakerManagerServiceChild.cpp121
-rw-r--r--dom/speakermanager/SpeakerManagerServiceChild.h44
-rw-r--r--dom/speakermanager/tests/mochitest.ini3
-rw-r--r--dom/speakermanager/tests/test_speakermanager.html53
-rw-r--r--dom/svg/SVGClipPathElement.cpp7
-rw-r--r--dom/svg/SVGClipPathElement.h4
-rw-r--r--dom/svg/SVGTextContentElement.h1
-rw-r--r--dom/system/OSFileConstants.cpp11
-rw-r--r--dom/system/gonk/AudioChannelManager.cpp181
-rw-r--r--dom/system/gonk/AudioChannelManager.h87
-rw-r--r--dom/system/gonk/AudioManager.cpp1412
-rw-r--r--dom/system/gonk/AudioManager.h180
-rw-r--r--dom/system/gonk/AutoMounter.cpp1496
-rw-r--r--dom/system/gonk/AutoMounter.h101
-rw-r--r--dom/system/gonk/AutoMounterSetting.cpp284
-rw-r--r--dom/system/gonk/AutoMounterSetting.h38
-rw-r--r--dom/system/gonk/DataCallInterfaceService.js276
-rw-r--r--dom/system/gonk/DataCallInterfaceService.manifest6
-rw-r--r--dom/system/gonk/DataCallManager.js1726
-rw-r--r--dom/system/gonk/DataCallManager.manifest4
-rw-r--r--dom/system/gonk/GeolocationUtil.cpp28
-rw-r--r--dom/system/gonk/GeolocationUtil.h13
-rw-r--r--dom/system/gonk/GonkGPSGeolocationProvider.cpp706
-rw-r--r--dom/system/gonk/GonkGPSGeolocationProvider.h103
-rw-r--r--dom/system/gonk/MozMtpCommon.h56
-rw-r--r--dom/system/gonk/MozMtpDatabase.cpp1542
-rw-r--r--dom/system/gonk/MozMtpDatabase.h288
-rw-r--r--dom/system/gonk/MozMtpServer.cpp263
-rw-r--r--dom/system/gonk/MozMtpServer.h61
-rw-r--r--dom/system/gonk/MozMtpStorage.cpp135
-rw-r--r--dom/system/gonk/MozMtpStorage.h47
-rw-r--r--dom/system/gonk/NetIdManager.cpp68
-rw-r--r--dom/system/gonk/NetIdManager.h45
-rw-r--r--dom/system/gonk/NetworkInterfaceListService.js110
-rw-r--r--dom/system/gonk/NetworkInterfaceListService.manifest17
-rw-r--r--dom/system/gonk/NetworkManager.js1219
-rw-r--r--dom/system/gonk/NetworkManager.manifest3
-rw-r--r--dom/system/gonk/NetworkService.js862
-rw-r--r--dom/system/gonk/NetworkService.manifest3
-rw-r--r--dom/system/gonk/NetworkUtils.cpp2973
-rw-r--r--dom/system/gonk/NetworkUtils.h498
-rw-r--r--dom/system/gonk/NetworkWorker.cpp271
-rw-r--r--dom/system/gonk/NetworkWorker.h37
-rw-r--r--dom/system/gonk/OpenFileFinder.cpp251
-rw-r--r--dom/system/gonk/OpenFileFinder.h63
-rw-r--r--dom/system/gonk/RILSystemMessenger.jsm338
-rw-r--r--dom/system/gonk/RILSystemMessengerHelper.js169
-rw-r--r--dom/system/gonk/RILSystemMessengerHelper.manifest6
-rw-r--r--dom/system/gonk/RadioInterfaceLayer.js1324
-rw-r--r--dom/system/gonk/RadioInterfaceLayer.manifest18
-rw-r--r--dom/system/gonk/SystemProperty.cpp98
-rw-r--r--dom/system/gonk/SystemProperty.h39
-rw-r--r--dom/system/gonk/SystemWorkerManager.cpp214
-rw-r--r--dom/system/gonk/SystemWorkerManager.h75
-rw-r--r--dom/system/gonk/TetheringService.js891
-rw-r--r--dom/system/gonk/TetheringService.manifest4
-rw-r--r--dom/system/gonk/TimeZoneSettingObserver.cpp239
-rw-r--r--dom/system/gonk/TimeZoneSettingObserver.h20
-rw-r--r--dom/system/gonk/Volume.cpp596
-rw-r--r--dom/system/gonk/Volume.h157
-rw-r--r--dom/system/gonk/VolumeCommand.cpp85
-rw-r--r--dom/system/gonk/VolumeCommand.h204
-rw-r--r--dom/system/gonk/VolumeManager.cpp591
-rw-r--r--dom/system/gonk/VolumeManager.h192
-rw-r--r--dom/system/gonk/VolumeManagerLog.h27
-rw-r--r--dom/system/gonk/VolumeServiceIOThread.cpp82
-rw-r--r--dom/system/gonk/VolumeServiceIOThread.h49
-rw-r--r--dom/system/gonk/VolumeServiceTest.cpp202
-rw-r--r--dom/system/gonk/VolumeServiceTest.h19
-rw-r--r--dom/system/gonk/android_audio/AudioSystem.h1134
-rw-r--r--dom/system/gonk/android_audio/AudioTrack.h489
-rw-r--r--dom/system/gonk/android_audio/EffectApi.h798
-rw-r--r--dom/system/gonk/android_audio/IAudioFlinger.h184
-rw-r--r--dom/system/gonk/android_audio/IAudioFlingerClient.h55
-rw-r--r--dom/system/gonk/android_audio/IAudioRecord.h68
-rw-r--r--dom/system/gonk/android_audio/IAudioTrack.h89
-rw-r--r--dom/system/gonk/android_audio/IEffect.h60
-rw-r--r--dom/system/gonk/android_audio/IEffectClient.h54
-rw-r--r--dom/system/gonk/moz.build107
-rw-r--r--dom/system/gonk/mozstumbler/MozStumbler.cpp426
-rw-r--r--dom/system/gonk/mozstumbler/MozStumbler.h47
-rw-r--r--dom/system/gonk/mozstumbler/StumblerLogging.cpp13
-rw-r--r--dom/system/gonk/mozstumbler/StumblerLogging.h18
-rw-r--r--dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp151
-rw-r--r--dom/system/gonk/mozstumbler/UploadStumbleRunnable.h46
-rw-r--r--dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp321
-rw-r--r--dom/system/gonk/mozstumbler/WriteStumbleOnThread.h91
-rw-r--r--dom/system/gonk/nsIAudioManager.idl58
-rw-r--r--dom/system/gonk/nsIDataCallInterfaceService.idl268
-rw-r--r--dom/system/gonk/nsIDataCallManager.idl81
-rw-r--r--dom/system/gonk/nsIGonkDataCallInterfaceService.idl18
-rw-r--r--dom/system/gonk/nsINetworkInterface.idl108
-rw-r--r--dom/system/gonk/nsINetworkInterfaceListService.idl40
-rw-r--r--dom/system/gonk/nsINetworkManager.idl135
-rw-r--r--dom/system/gonk/nsINetworkService.idl619
-rw-r--r--dom/system/gonk/nsINetworkWorker.idl18
-rw-r--r--dom/system/gonk/nsIRadioInterfaceLayer.idl53
-rw-r--r--dom/system/gonk/nsISystemWorkerManager.idl16
-rw-r--r--dom/system/gonk/nsITetheringService.idl39
-rw-r--r--dom/system/gonk/nsIVolume.idl114
-rw-r--r--dom/system/gonk/nsIVolumeMountLock.idl12
-rw-r--r--dom/system/gonk/nsIVolumeService.idl36
-rw-r--r--dom/system/gonk/nsIVolumeStat.idl12
-rw-r--r--dom/system/gonk/nsIWorkerHolder.idl11
-rw-r--r--dom/system/gonk/nsVolume.cpp467
-rw-r--r--dom/system/gonk/nsVolume.h114
-rw-r--r--dom/system/gonk/nsVolumeMountLock.cpp171
-rw-r--r--dom/system/gonk/nsVolumeMountLock.h56
-rw-r--r--dom/system/gonk/nsVolumeService.cpp553
-rw-r--r--dom/system/gonk/nsVolumeService.h78
-rw-r--r--dom/system/gonk/nsVolumeStat.cpp33
-rw-r--r--dom/system/gonk/nsVolumeStat.h33
-rw-r--r--dom/system/gonk/ril_consts.js3338
-rw-r--r--dom/system/gonk/ril_worker.js15206
-rw-r--r--dom/system/gonk/ril_worker_buf_object.js168
-rw-r--r--dom/system/gonk/ril_worker_telephony_request_queue.js157
-rw-r--r--dom/system/gonk/systemlibs.js201
-rw-r--r--dom/system/gonk/tests/header_helpers.js217
-rw-r--r--dom/system/gonk/tests/marionette/head.js345
-rw-r--r--dom/system/gonk/tests/marionette/manifest.ini19
-rw-r--r--dom/system/gonk/tests/marionette/ril_jshint/README.md9
-rw-r--r--dom/system/gonk/tests/marionette/ril_jshint/jshint.js11096
-rw-r--r--dom/system/gonk/tests/marionette/ril_jshint/jshintrc118
-rw-r--r--dom/system/gonk/tests/marionette/test_all_network_info.js106
-rw-r--r--dom/system/gonk/tests/marionette/test_data_connection.js70
-rw-r--r--dom/system/gonk/tests/marionette/test_data_connection_proxy.js99
-rw-r--r--dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js43
-rw-r--r--dom/system/gonk/tests/marionette/test_fakevolume.js25
-rw-r--r--dom/system/gonk/tests/marionette/test_geolocation.js117
-rw-r--r--dom/system/gonk/tests/marionette/test_multiple_data_connection.js89
-rw-r--r--dom/system/gonk/tests/marionette/test_network_active_changed.js52
-rw-r--r--dom/system/gonk/tests/marionette/test_network_interface_list_service.js95
-rw-r--r--dom/system/gonk/tests/marionette/test_network_interface_mtu.js100
-rw-r--r--dom/system/gonk/tests/marionette/test_ril_code_quality.py371
-rw-r--r--dom/system/gonk/tests/marionette/test_screen_state.js47
-rw-r--r--dom/system/gonk/tests/marionette/test_timezone_changes.js135
-rw-r--r--dom/system/gonk/tests/test_ril_system_messenger.js1187
-rw-r--r--dom/system/gonk/tests/test_ril_worker_barring_password.js61
-rw-r--r--dom/system/gonk/tests/test_ril_worker_buf.js187
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js234
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js470
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cellbroadcast_gsm.js230
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cellbroadcast_umts.js105
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cf.js126
-rw-r--r--dom/system/gonk/tests/test_ril_worker_clip.js59
-rw-r--r--dom/system/gonk/tests/test_ril_worker_clir.js122
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cw.js104
-rw-r--r--dom/system/gonk/tests/test_ril_worker_ecm.js168
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js87
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_CardLock.js282
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_CardState.js210
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js79
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js1042
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js173
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js652
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js1080
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js326
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js771
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js1648
-rw-r--r--dom/system/gonk/tests/test_ril_worker_ruim.js328
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms.js273
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_cdma.js298
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_cdmapduhelper.js210
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_gsmpduhelper.js282
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_nl_tables.js77
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_segment_info.js115
-rw-r--r--dom/system/gonk/tests/test_ril_worker_smsc_address.js112
-rw-r--r--dom/system/gonk/tests/test_ril_worker_ssn.js104
-rw-r--r--dom/system/gonk/tests/test_ril_worker_stk.js1698
-rw-r--r--dom/system/gonk/tests/test_ril_worker_voiceprivacy.js94
-rw-r--r--dom/system/gonk/tests/xpcshell.ini43
-rw-r--r--dom/system/gonk/worker_buf.js623
-rw-r--r--dom/system/moz.build2
-rw-r--r--dom/tests/mochitest/bugs/test_resize_move_windows.html5
-rw-r--r--dom/tests/mochitest/fetch/test_fetch_cors.js4
-rw-r--r--dom/tests/mochitest/fetch/test_headers_common.js10
-rw-r--r--dom/tests/mochitest/fetch/test_request.js13
-rw-r--r--dom/tests/mochitest/general/test_interfaces.html8
-rw-r--r--dom/tethering/TetheringManager.js92
-rw-r--r--dom/tethering/TetheringManager.manifest4
-rw-r--r--dom/tethering/moz.build12
-rw-r--r--dom/tethering/tests/marionette/head.js768
-rw-r--r--dom/tethering/tests/marionette/manifest.ini7
-rw-r--r--dom/tethering/tests/marionette/test_wifi_tethering_dun.js37
-rw-r--r--dom/tethering/tests/marionette/test_wifi_tethering_enabled.js12
-rw-r--r--dom/url/URL.cpp60
-rw-r--r--dom/url/tests/test_url.html12
-rw-r--r--dom/webidl/CanvasRenderingContext2D.webidl3
-rw-r--r--dom/webidl/Document.webidl6
-rw-r--r--dom/webidl/EventHandler.webidl9
-rw-r--r--dom/webidl/HTMLDocument.webidl4
-rw-r--r--dom/webidl/HTMLInputElement.webidl19
-rw-r--r--dom/webidl/MozApplicationEvent.webidl16
-rw-r--r--dom/webidl/MozNetworkStats.webidl73
-rw-r--r--dom/webidl/MozNetworkStatsAlarm.webidl13
-rw-r--r--dom/webidl/MozNetworkStatsData.webidl12
-rw-r--r--dom/webidl/MozNetworkStatsInterface.webidl26
-rw-r--r--dom/webidl/MozNetworkStatsManager.webidl96
-rw-r--r--dom/webidl/MozSpeakerManager.webidl18
-rw-r--r--dom/webidl/MozWifiCapabilities.webidl46
-rw-r--r--dom/webidl/MozWifiConnectionInfoEvent.webidl43
-rw-r--r--dom/webidl/MozWifiManager.webidl347
-rw-r--r--dom/webidl/MozWifiP2pManager.webidl147
-rw-r--r--dom/webidl/MozWifiP2pStatusChangeEvent.webidl20
-rw-r--r--dom/webidl/MozWifiStationInfoEvent.webidl19
-rw-r--r--dom/webidl/MozWifiStatusChangeEvent.webidl27
-rw-r--r--dom/webidl/Performance.webidl3
-rw-r--r--dom/webidl/PerformanceNavigationTiming.webidl33
-rw-r--r--dom/webidl/PerformanceObserver.webidl1
-rw-r--r--dom/webidl/PerformanceResourceTiming.webidl8
-rw-r--r--dom/webidl/PerformanceTiming.webidl6
-rw-r--r--dom/webidl/PointerEvent.webidl4
-rw-r--r--dom/webidl/Response.webidl2
-rw-r--r--dom/webidl/Selection.webidl3
-rw-r--r--dom/webidl/Window.webidl8
-rw-r--r--dom/webidl/moz.build36
-rw-r--r--dom/wifi/DOMWifiManager.js543
-rw-r--r--dom/wifi/DOMWifiManager.manifest18
-rw-r--r--dom/wifi/DOMWifiP2pManager.js328
-rw-r--r--dom/wifi/DOMWifiP2pManager.manifest6
-rw-r--r--dom/wifi/StateMachine.jsm205
-rw-r--r--dom/wifi/WifiCertService.cpp536
-rw-r--r--dom/wifi/WifiCertService.h40
-rw-r--r--dom/wifi/WifiCommand.jsm594
-rw-r--r--dom/wifi/WifiHotspotUtils.cpp188
-rw-r--r--dom/wifi/WifiHotspotUtils.h46
-rw-r--r--dom/wifi/WifiNetUtil.jsm154
-rw-r--r--dom/wifi/WifiP2pManager.jsm1649
-rw-r--r--dom/wifi/WifiP2pWorkerObserver.jsm319
-rw-r--r--dom/wifi/WifiProxyService.cpp357
-rw-r--r--dom/wifi/WifiProxyService.h49
-rw-r--r--dom/wifi/WifiUtils.cpp521
-rw-r--r--dom/wifi/WifiUtils.h107
-rw-r--r--dom/wifi/WifiWorker.h9
-rw-r--r--dom/wifi/WifiWorker.js3928
-rw-r--r--dom/wifi/WifiWorker.manifest1
-rw-r--r--dom/wifi/moz.build41
-rw-r--r--dom/wifi/nsIWifi.idl60
-rw-r--r--dom/wifi/nsIWifiCertService.idl54
-rw-r--r--dom/wifi/nsIWifiService.idl22
-rw-r--r--dom/wifi/test/marionette/head.js1486
-rw-r--r--dom/wifi/test/marionette/manifest.ini22
-rw-r--r--dom/wifi/test/marionette/test_wifi_associate.js35
-rw-r--r--dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_PEAP.js623
-rw-r--r--dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_TLS.js622
-rw-r--r--dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_TTLS.js623
-rw-r--r--dom/wifi/test/marionette/test_wifi_associate_wo_connect.js55
-rw-r--r--dom/wifi/test/marionette/test_wifi_auto_connect.js44
-rw-r--r--dom/wifi/test/marionette/test_wifi_enable.js11
-rw-r--r--dom/wifi/test/marionette/test_wifi_enable_api.js13
-rw-r--r--dom/wifi/test/marionette/test_wifi_manage_pkcs12_certificate.js338
-rw-r--r--dom/wifi/test/marionette/test_wifi_manage_server_certificate.js106
-rw-r--r--dom/wifi/test/marionette/test_wifi_manage_user_certificate.js34
-rw-r--r--dom/wifi/test/marionette/test_wifi_scan.js43
-rw-r--r--dom/wifi/test/marionette/test_wifi_static_ip.js65
-rw-r--r--dom/wifi/test/marionette/test_wifi_tethering_wifi_active.js74
-rw-r--r--dom/wifi/test/marionette/test_wifi_tethering_wifi_disabled.js11
-rw-r--r--dom/wifi/test/marionette/test_wifi_tethering_wifi_inactive.js21
-rw-r--r--dom/workers/RuntimeService.cpp15
-rw-r--r--dom/workers/ScriptLoader.cpp14
-rw-r--r--dom/workers/ServiceWorkerEvents.cpp14
-rw-r--r--dom/workers/ServiceWorkerPrivate.cpp45
-rw-r--r--dom/workers/ServiceWorkerPrivate.h1
-rw-r--r--dom/workers/WorkerNavigator.cpp2
-rw-r--r--dom/workers/WorkerPrivate.cpp24
-rw-r--r--dom/workers/WorkerPrivate.h29
-rw-r--r--dom/workers/WorkerRunnable.cpp13
-rw-r--r--dom/workers/WorkerRunnable.h9
-rw-r--r--dom/workers/test/serviceworkers/chrome.ini3
-rw-r--r--dom/workers/test/serviceworkers/fetch_event_worker.js23
-rw-r--r--dom/workers/test/serviceworkers/test_devtools_serviceworker_interception.html168
-rw-r--r--dom/workers/test/serviceworkers/test_serviceworker_interfaces.js6
-rw-r--r--dom/workers/test/test_worker_interfaces.js6
-rw-r--r--dom/xbl/nsXBLBinding.cpp12
-rw-r--r--dom/xhr/XMLHttpRequestMainThread.cpp69
-rw-r--r--dom/xhr/XMLHttpRequestMainThread.h5
-rw-r--r--dom/xhr/XMLHttpRequestWorker.cpp50
-rw-r--r--dom/xhr/XMLHttpRequestWorker.h7
-rw-r--r--dom/xhr/tests/mochitest.ini7
-rw-r--r--dom/xslt/xpath/txXPCOMExtensionFunction.cpp2
-rw-r--r--dom/xslt/xslt/txFormatNumberFunctionCall.cpp6
771 files changed, 20300 insertions, 114660 deletions
diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp
index 6dd583ed1..f4d29376c 100644
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -230,6 +230,10 @@ Animation::SetTimelineNoUpdate(AnimationTimeline* aTimeline)
return;
}
+ StickyTimeDuration activeTime = mEffect
+ ? mEffect->GetComputedTiming().mActiveTime
+ : StickyTimeDuration();
+
RefPtr<AnimationTimeline> oldTimeline = mTimeline;
if (oldTimeline) {
oldTimeline->RemoveAnimation(this);
@@ -240,6 +244,9 @@ Animation::SetTimelineNoUpdate(AnimationTimeline* aTimeline)
mHoldTime.SetNull();
}
+ if (!aTimeline) {
+ MaybeQueueCancelEvent(activeTime);
+ }
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
}
@@ -582,8 +589,10 @@ Animation::Tick()
// during the *previous* tick of the refresh driver, it can still be
// ahead of the *current* timeline time when we are using the
// vsync timer so we need to clamp it to the timeline time.
- mPendingReadyTime.SetValue(std::min(mTimeline->GetCurrentTime().Value(),
- mPendingReadyTime.Value()));
+ TimeDuration currentTime = mTimeline->GetCurrentTime().Value();
+ if (currentTime < mPendingReadyTime.Value()) {
+ mPendingReadyTime.SetValue(currentTime);
+ }
FinishPendingAt(mPendingReadyTime.Value());
mPendingReadyTime.SetNull();
}
@@ -722,8 +731,10 @@ TimeStamp
Animation::ElapsedTimeToTimeStamp(
const StickyTimeDuration& aElapsedTime) const
{
- return AnimationTimeToTimeStamp(aElapsedTime +
- mEffect->SpecifiedTiming().mDelay);
+ TimeDuration delay = mEffect
+ ? mEffect->SpecifiedTiming().mDelay
+ : TimeDuration();
+ return AnimationTimeToTimeStamp(aElapsedTime + delay);
}
@@ -771,14 +782,28 @@ Animation::CancelNoUpdate()
DispatchPlaybackEvent(NS_LITERAL_STRING("cancel"));
+ StickyTimeDuration activeTime = mEffect
+ ? mEffect->GetComputedTiming().mActiveTime
+ : StickyTimeDuration();
+
mHoldTime.SetNull();
mStartTime.SetNull();
- UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
-
if (mTimeline) {
mTimeline->RemoveAnimation(this);
}
+ MaybeQueueCancelEvent(activeTime);
+
+ // When an animation is cancelled it no longer needs further ticks from the
+ // timeline. However, if we queued a cancel event and this was the last
+ // animation attached to the timeline, the timeline will stop observing the
+ // refresh driver and there may be no subsequent refresh driver tick for
+ // dispatching the queued event.
+ //
+ // By calling UpdateTiming *after* removing ourselves from our timeline, we
+ // ensure the timeline will register with the refresh driver for at least one
+ // more tick.
+ UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
}
void
@@ -819,6 +844,17 @@ Animation::HasLowerCompositeOrderThan(const Animation& aOther) const
return thisTransition->HasLowerCompositeOrderThan(*otherTransition);
}
if (thisTransition || otherTransition) {
+ // Cancelled transitions no longer have an owning element. To be strictly
+ // correct we should store a strong reference to the owning element
+ // so that if we arrive here while sorting cancel events, we can sort
+ // them in the correct order.
+ //
+ // However, given that cancel events are almost always queued
+ // synchronously in some deterministic manner, we can be fairly sure
+ // that cancel events will be dispatched in a deterministic order
+ // (which is our only hard requirement until specs say otherwise).
+ // Furthermore, we only reach here when we have events with equal
+ // timestamps so this is an edge case we can probably ignore for now.
return thisTransition;
}
}
diff --git a/dom/animation/Animation.h b/dom/animation/Animation.h
index c59d7d6ce..3263b30c4 100644
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -326,6 +326,16 @@ public:
void NotifyEffectTimingUpdated();
+ /**
+ * Used by subclasses to synchronously queue a cancel event in situations
+ * where the Animation may have been cancelled.
+ *
+ * We need to do this synchronously because after a CSS animation/transition
+ * is canceled, it will be released by its owning element and may not still
+ * exist when we would normally go to queue events on the next tick.
+ */
+ virtual void MaybeQueueCancelEvent(StickyTimeDuration aActiveTime) {};
+
protected:
void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime);
void SilentlySetPlaybackRate(double aPlaybackRate);
diff --git a/dom/animation/AnimationEffectReadOnly.cpp b/dom/animation/AnimationEffectReadOnly.cpp
index aff28a37b..bf2e2197d 100644
--- a/dom/animation/AnimationEffectReadOnly.cpp
+++ b/dom/animation/AnimationEffectReadOnly.cpp
@@ -127,10 +127,6 @@ AnimationEffectReadOnly::GetComputedTimingAt(
}
const TimeDuration& localTime = aLocalTime.Value();
- // Calculate the time within the active interval.
- // https://w3c.github.io/web-animations/#active-time
- StickyTimeDuration activeTime;
-
StickyTimeDuration beforeActiveBoundary =
std::max(std::min(StickyTimeDuration(aTiming.mDelay), result.mEndTime),
zeroDuration);
@@ -148,7 +144,7 @@ AnimationEffectReadOnly::GetComputedTimingAt(
// The animation isn't active or filling at this time.
return result;
}
- activeTime =
+ result.mActiveTime =
std::max(std::min(StickyTimeDuration(localTime - aTiming.mDelay),
result.mActiveDuration),
zeroDuration);
@@ -159,13 +155,14 @@ AnimationEffectReadOnly::GetComputedTimingAt(
// The animation isn't active or filling at this time.
return result;
}
- activeTime = std::max(StickyTimeDuration(localTime - aTiming.mDelay),
- zeroDuration);
+ result.mActiveTime
+ = std::max(StickyTimeDuration(localTime - aTiming.mDelay),
+ zeroDuration);
} else {
MOZ_ASSERT(result.mActiveDuration != zeroDuration,
"How can we be in the middle of a zero-duration interval?");
result.mPhase = ComputedTiming::AnimationPhase::Active;
- activeTime = localTime - aTiming.mDelay;
+ result.mActiveTime = localTime - aTiming.mDelay;
}
// Convert active time to a multiple of iterations.
@@ -176,7 +173,7 @@ AnimationEffectReadOnly::GetComputedTimingAt(
? 0.0
: result.mIterations;
} else {
- overallProgress = activeTime / result.mDuration;
+ overallProgress = result.mActiveTime / result.mDuration;
}
// Factor in iteration start offset.
@@ -208,7 +205,8 @@ AnimationEffectReadOnly::GetComputedTimingAt(
if (result.mPhase == ComputedTiming::AnimationPhase::After &&
progress == 0.0 &&
result.mIterations != 0.0 &&
- (activeTime != zeroDuration || result.mDuration == zeroDuration)) {
+ (result.mActiveTime != zeroDuration ||
+ result.mDuration == zeroDuration)) {
// The only way we can be in the after phase with a progress of zero and
// a current iteration of zero, is if we have a zero iteration count or
// were clipped using a negative end delay--both of which we should have
diff --git a/dom/animation/ComputedTiming.h b/dom/animation/ComputedTiming.h
index 4a98e3933..b1c6674a5 100644
--- a/dom/animation/ComputedTiming.h
+++ b/dom/animation/ComputedTiming.h
@@ -29,6 +29,8 @@ struct ComputedTiming
// Will equal StickyTimeDuration::Forever() if the animation repeats
// indefinitely.
StickyTimeDuration mActiveDuration;
+ // The time within the active interval.
+ StickyTimeDuration mActiveTime;
// The effect end time in local time (i.e. an offset from the effect's
// start time). Will equal StickyTimeDuration::Forever() if the animation
// plays indefinitely.
@@ -62,12 +64,12 @@ struct ComputedTiming
}
enum class AnimationPhase {
- Null, // Not sampled (null sample time)
+ Idle, // Not sampled (null sample time)
Before, // Sampled prior to the start of the active interval
Active, // Sampled within the active interval
After // Sampled after (or at) the end of the active interval
};
- AnimationPhase mPhase = AnimationPhase::Null;
+ AnimationPhase mPhase = AnimationPhase::Idle;
ComputedTimingFunction::BeforeFlag mBeforeFlag =
ComputedTimingFunction::BeforeFlag::Unset;
diff --git a/dom/animation/test/css-animations/file_event-dispatch.html b/dom/animation/test/css-animations/file_event-dispatch.html
new file mode 100644
index 000000000..266205bc3
--- /dev/null
+++ b/dom/animation/test/css-animations/file_event-dispatch.html
@@ -0,0 +1,252 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Tests for CSS animation event dispatch</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/#event-dispatch"/>
+<script src="../testcommon.js"></script>
+<style>
+ @keyframes anim {
+ from { margin-left: 0px; }
+ to { margin-left: 100px; }
+ }
+</style>
+<body>
+<script>
+'use strict';
+
+/**
+ * Helper class to record the elapsedTime member of each event.
+ * The EventWatcher class in testharness.js allows us to wait on
+ * multiple events in a certain order but only records the event
+ * parameters of the most recent event.
+ */
+function AnimationEventHandler(target) {
+ this.target = target;
+ this.target.onanimationstart = function(evt) {
+ this.animationstart = evt.elapsedTime;
+ }.bind(this);
+ this.target.onanimationiteration = function(evt) {
+ this.animationiteration = evt.elapsedTime;
+ }.bind(this);
+ this.target.onanimationend = function(evt) {
+ this.animationend = evt.elapsedTime;
+ }.bind(this);
+}
+AnimationEventHandler.prototype.clear = function() {
+ this.animationstart = undefined;
+ this.animationiteration = undefined;
+ this.animationend = undefined;
+}
+
+function setupAnimation(t, animationStyle) {
+ var div = addDiv(t, { style: "animation: " + animationStyle });
+ var watcher = new EventWatcher(t, div, [ 'animationstart',
+ 'animationiteration',
+ 'animationend' ]);
+ var handler = new AnimationEventHandler(div);
+ var animation = div.getAnimations()[0];
+
+ return [animation, watcher, handler, div];
+}
+
+promise_test(function(t) {
+ // Add 1ms delay to ensure that the delay is not included in the elapsedTime.
+ const [animation, watcher] = setupAnimation(t, 'anim 100s 1ms');
+
+ return watcher.wait_for('animationstart').then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Idle -> Active');
+
+promise_test(function(t) {
+ const [animation, watcher, handler] = setupAnimation(t, 'anim 100s');
+
+ // Seek to After phase.
+ animation.finish();
+ return watcher.wait_for([ 'animationstart',
+ 'animationend' ]).then(function() {
+ assert_equals(handler.animationstart, 0.0);
+ assert_equals(handler.animationend, 100);
+ });
+}, 'Idle -> After');
+
+promise_test(function(t) {
+ const [animation, watcher, handler] =
+ setupAnimation(t, 'anim 100s 100s paused');
+
+ return animation.ready.then(function() {
+ // Seek to Active phase.
+ animation.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for('animationstart');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Before -> Active');
+
+promise_test(function(t) {
+ const [animation, watcher, handler] =
+ setupAnimation(t, 'anim 100s 100s paused');
+
+ return animation.ready.then(function() {
+ // Seek to After phase.
+ animation.finish();
+ return watcher.wait_for([ 'animationstart', 'animationend' ]);
+ }).then(function(evt) {
+ assert_equals(handler.animationstart, 0.0);
+ assert_equals(handler.animationend, 100.0);
+ });
+}, 'Before -> After');
+
+promise_test(function(t) {
+ const [animation, watcher, handler] =
+ setupAnimation(t, 'anim 100s 100s paused');
+
+ // Seek to Active phase.
+ animation.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for('animationstart').then(function() {
+ // Seek to Before phase.
+ animation.currentTime = 0;
+ return watcher.wait_for('animationend');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Active -> Before');
+
+promise_test(function(t) {
+ const [animation, watcher, handler] = setupAnimation(t, 'anim 100s paused');
+
+ return watcher.wait_for('animationstart').then(function(evt) {
+ // Seek to After phase.
+ animation.finish();
+ return watcher.wait_for('animationend');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 100.0);
+ });
+}, 'Active -> After');
+
+promise_test(function(t) {
+ const [animation, watcher, handler] =
+ setupAnimation(t, 'anim 100s 100s paused');
+
+ // Seek to After phase.
+ animation.finish();
+ return watcher.wait_for([ 'animationstart',
+ 'animationend' ]).then(function() {
+ // Seek to Before phase.
+ animation.currentTime = 0;
+ handler.clear();
+ return watcher.wait_for([ 'animationstart', 'animationend' ]);
+ }).then(function() {
+ assert_equals(handler.animationstart, 100.0);
+ assert_equals(handler.animationend, 0.0);
+ });
+}, 'After -> Before');
+
+promise_test(function(t) {
+ const [animation, watcher, handler] =
+ setupAnimation(t, 'anim 100s 100s paused');
+
+ // Seek to After phase.
+ animation.finish();
+ return watcher.wait_for([ 'animationstart',
+ 'animationend' ]).then(function() {
+ // Seek to Active phase.
+ animation.currentTime = 100 * MS_PER_SEC;
+ handler.clear();
+ return watcher.wait_for('animationstart');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 100.0);
+ });
+}, 'After -> Active');
+
+promise_test(function(t) {
+ const [animation, watcher, handler]
+ = setupAnimation(t, 'anim 100s 100s 3 paused');
+
+ return animation.ready.then(function() {
+ // Seek to iteration 0 (no animationiteration event should be dispatched)
+ animation.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for('animationstart');
+ }).then(function(evt) {
+ // Seek to iteration 2
+ animation.currentTime = 300 * MS_PER_SEC;
+ handler.clear();
+ return watcher.wait_for('animationiteration');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 200);
+ // Seek to After phase (no animationiteration event should be dispatched)
+ animation.currentTime = 400 * MS_PER_SEC;
+ return watcher.wait_for('animationend');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 300);
+ });
+}, 'Active -> Active (forwards)');
+
+promise_test(function(t) {
+ const [animation, watcher, handler] = setupAnimation(t, 'anim 100s 100s 3');
+
+ // Seek to After phase.
+ animation.finish();
+ return watcher.wait_for([ 'animationstart',
+ 'animationend' ]).then(function() {
+ // Seek to iteration 2 (no animationiteration event should be dispatched)
+ animation.pause();
+ animation.currentTime = 300 * MS_PER_SEC;
+ return watcher.wait_for('animationstart');
+ }).then(function() {
+ // Seek to mid of iteration 0 phase.
+ animation.currentTime = 200 * MS_PER_SEC;
+ return watcher.wait_for('animationiteration');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 200.0);
+ // Seek to before phase (no animationiteration event should be dispatched)
+ animation.currentTime = 0;
+ return watcher.wait_for('animationend');
+ });
+}, 'Active -> Active (backwards)');
+
+promise_test(function(t) {
+ const [animation, watcher, handler, div] =
+ setupAnimation(t, 'anim 100s paused');
+ return watcher.wait_for('animationstart').then(function(evt) {
+ // Seek to Idle phase.
+ div.style.display = 'none';
+ flushComputedStyle(div);
+
+ // FIXME: bug 1302648: Add test for animationcancel event here.
+
+ // Restart this animation.
+ div.style.display = '';
+ return watcher.wait_for('animationstart');
+ });
+}, 'Active -> Idle -> Active: animationstart is fired by restarting animation');
+
+promise_test(function(t) {
+ const [animation, watcher, handler, div] =
+ setupAnimation(t, 'anim 100s 100s 2 paused');
+
+ // Make After.
+ animation.finish();
+ return watcher.wait_for([ 'animationstart',
+ 'animationend' ]).then(function(evt) {
+ animation.playbackRate = -1;
+ return watcher.wait_for('animationstart');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 200);
+ // Seek to 1st iteration
+ animation.currentTime = 200 * MS_PER_SEC - 1;
+ return watcher.wait_for('animationiteration');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 100);
+ // Seek to before
+ animation.currentTime = 100 * MS_PER_SEC - 1;
+ return watcher.wait_for('animationend');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0);
+ assert_equals(animation.playState, 'running'); // delay
+ });
+}, 'Negative playbackRate sanity test(Before -> Active -> Before)');
+
+done();
+</script>
+</body>
+</html>
diff --git a/dom/animation/test/css-animations/file_event-order.html b/dom/animation/test/css-animations/file_event-order.html
new file mode 100644
index 000000000..da78b6541
--- /dev/null
+++ b/dom/animation/test/css-animations/file_event-order.html
@@ -0,0 +1,160 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Tests for CSS animation event order</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/#event-dispatch"/>
+<script src="../testcommon.js"></script>
+<style>
+ @keyframes anim {
+ from { margin-left: 0px; }
+ to { margin-left: 100px; }
+ }
+</style>
+<body>
+<script type='text/javascript'>
+'use strict';
+
+/**
+ * Asserts that the set of actual and received events match.
+ * @param actualEvents An array of the received AnimationEvent objects.
+ * @param expectedEvents A series of array objects representing the expected
+ * events, each having the form:
+ * [ event type, target element, elapsed time ]
+ */
+function checkEvents(actualEvents, ...expectedEvents) {
+ assert_equals(actualEvents.length, expectedEvents.length,
+ `Number of actual events (${actualEvents.length}: \
+${actualEvents.map(event => event.type).join(', ')}) should match expected \
+events (${expectedEvents.map(event => event.type).join(', ')})`);
+
+ actualEvents.forEach((actualEvent, i) => {
+ assert_equals(expectedEvents[i][0], actualEvent.type,
+ 'Event type should match');
+ assert_equals(expectedEvents[i][1], actualEvent.target,
+ 'Event target should match');
+ assert_equals(expectedEvents[i][2], actualEvent.elapsedTime,
+ 'Event\'s elapsed time should match');
+ });
+}
+
+function setupAnimation(t, animationStyle, receiveEvents) {
+ const div = addDiv(t, { style: "animation: " + animationStyle });
+ const watcher = new EventWatcher(t, div, [ 'animationstart',
+ 'animationiteration',
+ 'animationend' ]);
+
+ ['start', 'iteration', 'end'].forEach(name => {
+ div['onanimation' + name] = function(evt) {
+ receiveEvents.push({ type: evt.type,
+ target: evt.target,
+ elapsedTime: evt.elapsedTime });
+ }.bind(this);
+ });
+
+ const animation = div.getAnimations()[0];
+
+ return [animation, watcher, div];
+}
+
+promise_test(function(t) {
+ let events = [];
+ const [animation1, watcher1, div1] =
+ setupAnimation(t, 'anim 100s 2 paused', events);
+ const [animation2, watcher2, div2] =
+ setupAnimation(t, 'anim 100s 2 paused', events);
+
+ return Promise.all([ watcher1.wait_for('animationstart'),
+ watcher2.wait_for('animationstart') ]).then(function() {
+ checkEvents(events, ['animationstart', div1, 0],
+ ['animationstart', div2, 0]);
+
+ events.length = 0; // Clear received event array
+
+ animation1.currentTime = 100 * MS_PER_SEC;
+ animation2.currentTime = 100 * MS_PER_SEC;
+ return Promise.all([ watcher1.wait_for('animationiteration'),
+ watcher2.wait_for('animationiteration') ]);
+ }).then(function() {
+ checkEvents(events, ['animationiteration', div1, 100],
+ ['animationiteration', div2, 100]);
+
+ events.length = 0; // Clear received event array
+
+ animation1.finish();
+ animation2.finish();
+
+ return Promise.all([ watcher1.wait_for('animationend'),
+ watcher2.wait_for('animationend') ]);
+ }).then(function() {
+ checkEvents(events, ['animationend', div1, 200],
+ ['animationend', div2, 200]);
+ });
+}, 'Test same events are ordered by elements.');
+
+promise_test(function(t) {
+ let events = [];
+ const [animation1, watcher1, div1] =
+ setupAnimation(t, 'anim 200s 400s', events);
+ const [animation2, watcher2, div2] =
+ setupAnimation(t, 'anim 300s 2', events);
+
+ return watcher2.wait_for('animationstart').then(function(evt) {
+ animation1.currentTime = 400 * MS_PER_SEC;
+ animation2.currentTime = 400 * MS_PER_SEC;
+
+ events.length = 0; // Clear received event array
+
+ return Promise.all([ watcher1.wait_for('animationstart'),
+ watcher2.wait_for('animationiteration') ]);
+ }).then(function() {
+ checkEvents(events, ['animationiteration', div2, 300],
+ ['animationstart', div1, 0]);
+ });
+}, 'Test start and iteration events are ordered by time.');
+
+promise_test(function(t) {
+ let events = [];
+ const [animation1, watcher1, div1] =
+ setupAnimation(t, 'anim 150s', events);
+ const [animation2, watcher2, div2] =
+ setupAnimation(t, 'anim 100s 2', events);
+
+ return Promise.all([ watcher1.wait_for('animationstart'),
+ watcher2.wait_for('animationstart') ]).then(function() {
+ animation1.currentTime = 150 * MS_PER_SEC;
+ animation2.currentTime = 150 * MS_PER_SEC;
+
+ events.length = 0; // Clear received event array
+
+ return Promise.all([ watcher1.wait_for('animationend'),
+ watcher2.wait_for('animationiteration') ]);
+ }).then(function() {
+ checkEvents(events, ['animationiteration', div2, 100],
+ ['animationend', div1, 150]);
+ });
+}, 'Test iteration and end events are ordered by time.');
+
+promise_test(function(t) {
+ let events = [];
+ const [animation1, watcher1, div1] =
+ setupAnimation(t, 'anim 100s 100s', events);
+ const [animation2, watcher2, div2] =
+ setupAnimation(t, 'anim 100s 2', events);
+
+ animation1.finish();
+ animation2.finish();
+
+ return Promise.all([ watcher1.wait_for([ 'animationstart',
+ 'animationend' ]),
+ watcher2.wait_for([ 'animationstart',
+ 'animationend' ]) ]).then(function() {
+ checkEvents(events, ['animationstart', div2, 0],
+ ['animationstart', div1, 0],
+ ['animationend', div1, 100],
+ ['animationend', div2, 200]);
+ });
+}, 'Test start and end events are sorted correctly when fired simultaneously');
+
+done();
+</script>
+</body>
+</html>
diff --git a/dom/animation/test/css-animations/test_event-dispatch.html b/dom/animation/test/css-animations/test_event-dispatch.html
new file mode 100644
index 000000000..de3be0301
--- /dev/null
+++ b/dom/animation/test/css-animations/test_event-dispatch.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+'use strict';
+setup({explicit_done: true});
+SpecialPowers.pushPrefEnv(
+ { "set": [["dom.animations-api.core.enabled", true]]},
+ function() {
+ window.open("file_event-dispatch.html");
+ });
+</script>
+</html>
diff --git a/dom/animation/test/css-transitions/test_csstransition-events.html b/dom/animation/test/css-animations/test_event-order.html
index 92559ad67..57f1f3876 100644
--- a/dom/animation/test/css-transitions/test_csstransition-events.html
+++ b/dom/animation/test/css-animations/test_event-order.html
@@ -9,6 +9,7 @@ setup({explicit_done: true});
SpecialPowers.pushPrefEnv(
{ "set": [["dom.animations-api.core.enabled", true]]},
function() {
- window.open("file_csstransition-events.html");
+ window.open("file_event-order.html");
});
</script>
+</html>
diff --git a/dom/animation/test/css-transitions/file_animation-cancel.html b/dom/animation/test/css-transitions/file_animation-cancel.html
index 6094b383f..71f02fb11 100644
--- a/dom/animation/test/css-transitions/file_animation-cancel.html
+++ b/dom/animation/test/css-transitions/file_animation-cancel.html
@@ -11,13 +11,12 @@ promise_test(function(t) {
div.style.transition = 'margin-left 100s';
div.style.marginLeft = '1000px';
- flushComputedStyle(div);
- var animation = div.getAnimations()[0];
- return animation.ready.then(waitForFrame).then(function() {
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(waitForFrame).then(function() {
assert_not_equals(getComputedStyle(div).marginLeft, '1000px',
'transform style is animated before cancelling');
- animation.cancel();
+ transition.cancel();
assert_equals(getComputedStyle(div).marginLeft, div.style.marginLeft,
'transform style is no longer animated after cancelling');
});
@@ -29,45 +28,21 @@ promise_test(function(t) {
div.style.transition = 'margin-left 100s';
div.style.marginLeft = '1000px';
- flushComputedStyle(div);
-
- div.addEventListener('transitionend', function() {
- assert_unreached('Got unexpected end event on cancelled transition');
- });
-
- var animation = div.getAnimations()[0];
- return animation.ready.then(function() {
- // Seek to just before the end then cancel
- animation.currentTime = 99.9 * 1000;
- animation.cancel();
- // Then wait a couple of frames and check that no event was dispatched
- return waitForAnimationFrames(2);
- });
-}, 'Cancelled CSS transitions do not dispatch events');
-
-promise_test(function(t) {
- var div = addDiv(t, { style: 'margin-left: 0px' });
- flushComputedStyle(div);
-
- div.style.transition = 'margin-left 100s';
- div.style.marginLeft = '1000px';
- flushComputedStyle(div);
-
- var animation = div.getAnimations()[0];
- return animation.ready.then(function() {
- animation.cancel();
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(function() {
+ transition.cancel();
assert_equals(getComputedStyle(div).marginLeft, '1000px',
'margin-left style is not animated after cancelling');
- animation.play();
+ transition.play();
assert_equals(getComputedStyle(div).marginLeft, '0px',
'margin-left style is animated after re-starting transition');
- return animation.ready;
+ return transition.ready;
}).then(function() {
- assert_equals(animation.playState, 'running',
+ assert_equals(transition.playState, 'running',
'Transition succeeds in running after being re-started');
});
-}, 'After cancelling a transition, it can still be re-used');
+}, 'After canceling a transition, it can still be re-used');
promise_test(function(t) {
var div = addDiv(t, { style: 'margin-left: 0px' });
@@ -75,20 +50,19 @@ promise_test(function(t) {
div.style.transition = 'margin-left 100s';
div.style.marginLeft = '1000px';
- flushComputedStyle(div);
- var animation = div.getAnimations()[0];
- return animation.ready.then(function() {
- animation.finish();
- animation.cancel();
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(function() {
+ transition.finish();
+ transition.cancel();
assert_equals(getComputedStyle(div).marginLeft, '1000px',
'margin-left style is not animated after cancelling');
- animation.play();
+ transition.play();
assert_equals(getComputedStyle(div).marginLeft, '0px',
'margin-left style is animated after re-starting transition');
- return animation.ready;
+ return transition.ready;
}).then(function() {
- assert_equals(animation.playState, 'running',
+ assert_equals(transition.playState, 'running',
'Transition succeeds in running after being re-started');
});
}, 'After cancelling a finished transition, it can still be re-used');
@@ -99,10 +73,9 @@ test(function(t) {
div.style.transition = 'margin-left 100s';
div.style.marginLeft = '1000px';
- flushComputedStyle(div);
- var animation = div.getAnimations()[0];
- animation.cancel();
+ var transition = div.getAnimations()[0];
+ transition.cancel();
assert_equals(getComputedStyle(div).marginLeft, '1000px',
'margin-left style is not animated after cancelling');
@@ -113,7 +86,7 @@ test(function(t) {
assert_equals(getComputedStyle(div).marginLeft, '1000px',
'margin-left style is still not animated after updating'
+ ' transition-duration');
- assert_equals(animation.playState, 'idle',
+ assert_equals(transition.playState, 'idle',
'Transition is still idle after updating transition-duration');
}, 'After cancelling a transition, updating transition properties doesn\'t make'
+ ' it live again');
@@ -124,15 +97,14 @@ promise_test(function(t) {
div.style.transition = 'margin-left 100s';
div.style.marginLeft = '1000px';
- flushComputedStyle(div);
- var animation = div.getAnimations()[0];
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'running');
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(function() {
+ assert_equals(transition.playState, 'running');
div.style.display = 'none';
return waitForFrame();
}).then(function() {
- assert_equals(animation.playState, 'idle');
+ assert_equals(transition.playState, 'idle');
assert_equals(getComputedStyle(div).marginLeft, '1000px');
});
}, 'Setting display:none on an element cancels its transitions');
@@ -147,19 +119,115 @@ promise_test(function(t) {
childDiv.style.transition = 'margin-left 100s';
childDiv.style.marginLeft = '1000px';
- flushComputedStyle(childDiv);
- var animation = childDiv.getAnimations()[0];
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'running');
+ var transition = childDiv.getAnimations()[0];
+ return transition.ready.then(function() {
+ assert_equals(transition.playState, 'running');
parentDiv.style.display = 'none';
return waitForFrame();
}).then(function() {
- assert_equals(animation.playState, 'idle');
+ assert_equals(transition.playState, 'idle');
assert_equals(getComputedStyle(childDiv).marginLeft, '1000px');
});
}, 'Setting display:none cancels transitions on a child element');
+promise_test(function(t) {
+ var div = addDiv(t, { style: 'margin-left: 0px' });
+ flushComputedStyle(div);
+
+ div.style.transition = 'margin-left 100s';
+ div.style.marginLeft = '1000px';
+
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(function() {
+ assert_equals(transition.playState, 'running');
+ // Set an unrecognized property value
+ div.style.transitionProperty = 'none';
+ flushComputedStyle(div);
+ return waitForFrame();
+ }).then(function() {
+ assert_equals(transition.playState, 'idle');
+ assert_equals(getComputedStyle(div).marginLeft, '1000px');
+ });
+}, 'Removing a property from transition-property cancels transitions on that '+
+ 'property');
+
+promise_test(function(t) {
+ var div = addDiv(t, { style: 'margin-left: 0px' });
+ flushComputedStyle(div);
+
+ div.style.transition = 'margin-left 100s';
+ div.style.marginLeft = '1000px';
+
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(function() {
+ assert_equals(transition.playState, 'running');
+ div.style.transition = 'margin-top 10s -10s'; // combined duration is zero
+ flushComputedStyle(div);
+ return waitForFrame();
+ }).then(function() {
+ assert_equals(transition.playState, 'idle');
+ assert_equals(getComputedStyle(div).marginLeft, '1000px');
+ });
+}, 'Setting zero combined duration');
+
+promise_test(function(t) {
+ var div = addDiv(t, { style: 'margin-left: 0px' });
+ flushComputedStyle(div);
+
+ div.style.transition = 'margin-left 100s';
+ div.style.marginLeft = '1000px';
+
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(function() {
+ assert_equals(transition.playState, 'running');
+ div.style.marginLeft = '2000px';
+ flushComputedStyle(div);
+ return waitForFrame();
+ }).then(function() {
+ assert_equals(transition.playState, 'idle');
+ });
+}, 'Changing style to another interpolable value cancels the original ' +
+ 'transition');
+
+promise_test(function(t) {
+ var div = addDiv(t, { style: 'margin-left: 0px' });
+ flushComputedStyle(div);
+
+ div.style.transition = 'margin-left 100s';
+ div.style.marginLeft = '1000px';
+
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(function() {
+ assert_equals(transition.playState, 'running');
+ div.style.marginLeft = 'auto';
+ flushComputedStyle(div);
+ return waitForFrame();
+ }).then(function() {
+ assert_equals(div.getAnimations().length, 0,
+ 'There should be no transitions');
+ assert_equals(transition.playState, 'idle');
+ });
+}, 'An after-change style value can\'t be interpolated');
+
+promise_test(function(t) {
+ var div = addDiv(t, { style: 'margin-left: 0px' });
+ flushComputedStyle(div);
+
+ div.style.transition = 'margin-left 100s';
+ div.style.marginLeft = '1000px';
+
+ var transition = div.getAnimations()[0];
+ return transition.ready.then(function() {
+ assert_equals(transition.playState, 'running');
+ div.style.marginLeft = '0px';
+ flushComputedStyle(div);
+ return waitForFrame();
+ }).then(function() {
+ assert_equals(transition.playState, 'idle');
+ });
+}, 'Reversing a running transition cancels the original transition');
+
done();
</script>
</body>
diff --git a/dom/animation/test/css-transitions/file_csstransition-events.html b/dom/animation/test/css-transitions/file_csstransition-events.html
deleted file mode 100644
index 5011bc130..000000000
--- a/dom/animation/test/css-transitions/file_csstransition-events.html
+++ /dev/null
@@ -1,223 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>Tests for CSS-Transition events</title>
-<link rel="help" href="https://drafts.csswg.org/css-transitions-2/#transition-events">
-<script src="../testcommon.js"></script>
-<body>
-<script>
-'use strict';
-
-/**
- * Helper class to record the elapsedTime member of each event.
- * The EventWatcher class in testharness.js allows us to wait on
- * multiple events in a certain order but only records the event
- * parameters of the most recent event.
- */
-function TransitionEventHandler(target) {
- this.target = target;
- this.target.ontransitionrun = function(evt) {
- this.transitionrun = evt.elapsedTime;
- }.bind(this);
- this.target.ontransitionstart = function(evt) {
- this.transitionstart = evt.elapsedTime;
- }.bind(this);
- this.target.ontransitionend = function(evt) {
- this.transitionend = evt.elapsedTime;
- }.bind(this);
-}
-
-TransitionEventHandler.prototype.clear = function() {
- this.transitionrun = undefined;
- this.transitionstart = undefined;
- this.transitionend = undefined;
-};
-
-function setupTransition(t, transitionStyle) {
- var div, watcher, handler, transition;
- transitionStyle = transitionStyle || 'transition: margin-left 100s 100s';
- div = addDiv(t, { style: transitionStyle });
- watcher = new EventWatcher(t, div, [ 'transitionrun',
- 'transitionstart',
- 'transitionend' ]);
- handler = new TransitionEventHandler(div);
- flushComputedStyle(div);
-
- div.style.marginLeft = '100px';
- flushComputedStyle(div);
-
- transition = div.getAnimations()[0];
-
- return [transition, watcher, handler];
-}
-
-// On the next frame (i.e. when events are queued), whether or not the
-// transition is still pending depends on the implementation.
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- return watcher.wait_for('transitionrun').then(function(evt) {
- assert_equals(evt.elapsedTime, 0.0);
- });
-}, 'Idle -> Pending or Before');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- // Force the transition to leave the idle phase
- transition.startTime = document.timeline.currentTime;
- return watcher.wait_for('transitionrun').then(function(evt) {
- assert_equals(evt.elapsedTime, 0.0);
- });
-}, 'Idle -> Before');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- // Seek to Active phase.
- transition.currentTime = 100 * MS_PER_SEC;
- transition.pause();
- return watcher.wait_for([ 'transitionrun',
- 'transitionstart' ]).then(function(evt) {
- assert_equals(handler.transitionrun, 0.0);
- assert_equals(handler.transitionstart, 0.0);
- });
-}, 'Idle or Pending -> Active');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- // Seek to After phase.
- transition.finish();
- return watcher.wait_for([ 'transitionrun',
- 'transitionstart',
- 'transitionend' ]).then(function(evt) {
- assert_equals(handler.transitionrun, 0.0);
- assert_equals(handler.transitionstart, 0.0);
- assert_equals(handler.transitionend, 100.0);
- });
-}, 'Idle or Pending -> After');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
-
- return Promise.all([ watcher.wait_for('transitionrun'),
- transition.ready ]).then(function() {
- transition.currentTime = 100 * MS_PER_SEC;
- return watcher.wait_for('transitionstart');
- }).then(function() {
- assert_equals(handler.transitionstart, 0.0);
- });
-}, 'Before -> Active');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- return Promise.all([ watcher.wait_for('transitionrun'),
- transition.ready ]).then(function() {
- // Seek to After phase.
- transition.currentTime = 200 * MS_PER_SEC;
- return watcher.wait_for([ 'transitionstart', 'transitionend' ]);
- }).then(function(evt) {
- assert_equals(handler.transitionstart, 0.0);
- assert_equals(handler.transitionend, 100.0);
- });
-}, 'Before -> After');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- // Seek to Active phase.
- transition.currentTime = 100 * MS_PER_SEC;
- return watcher.wait_for([ 'transitionrun',
- 'transitionstart' ]).then(function(evt) {
- // Seek to Before phase.
- transition.currentTime = 0;
- return watcher.wait_for('transitionend');
- }).then(function(evt) {
- assert_equals(evt.elapsedTime, 0.0);
- });
-}, 'Active -> Before');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- // Seek to Active phase.
- transition.currentTime = 100 * MS_PER_SEC;
- return watcher.wait_for([ 'transitionrun',
- 'transitionstart' ]).then(function(evt) {
- // Seek to After phase.
- transition.currentTime = 200 * MS_PER_SEC;
- return watcher.wait_for('transitionend');
- }).then(function(evt) {
- assert_equals(evt.elapsedTime, 100.0);
- });
-}, 'Active -> After');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- // Seek to After phase.
- transition.finish();
- return watcher.wait_for([ 'transitionrun',
- 'transitionstart',
- 'transitionend' ]).then(function(evt) {
- // Seek to Before phase.
- transition.currentTime = 0;
- return watcher.wait_for([ 'transitionstart', 'transitionend' ]);
- }).then(function(evt) {
- assert_equals(handler.transitionstart, 100.0);
- assert_equals(handler.transitionend, 0.0);
- });
-}, 'After -> Before');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
- // Seek to After phase.
- transition.finish();
- return watcher.wait_for([ 'transitionrun',
- 'transitionstart',
- 'transitionend' ]).then(function(evt) {
- // Seek to Active phase.
- transition.currentTime = 100 * MS_PER_SEC;
- return watcher.wait_for('transitionstart');
- }).then(function(evt) {
- assert_equals(evt.elapsedTime, 100.0);
- });
-}, 'After -> Active');
-
-promise_test(function(t) {
- var [transition, watcher, handler] =
- setupTransition(t, 'transition: margin-left 100s -50s');
-
- return watcher.wait_for([ 'transitionrun',
- 'transitionstart' ]).then(function() {
- assert_equals(handler.transitionrun, 50.0);
- assert_equals(handler.transitionstart, 50.0);
- transition.finish();
- return watcher.wait_for('transitionend');
- }).then(function(evt) {
- assert_equals(evt.elapsedTime, 100.0);
- });
-}, 'Calculating the interval start and end time with negative start delay.');
-
-promise_test(function(t) {
- var [transition, watcher, handler] = setupTransition(t);
-
- return watcher.wait_for('transitionrun').then(function(evt) {
- // We can't set the end delay via generated effect timing.
- // Because CSS-Transition use the AnimationEffectTimingReadOnly.
- transition.effect = new KeyframeEffect(handler.target,
- { marginleft: [ '0px', '100px' ]},
- { duration: 100 * MS_PER_SEC,
- endDelay: -50 * MS_PER_SEC });
- // Seek to Before and play.
- transition.cancel();
- transition.play();
- return watcher.wait_for('transitionstart');
- }).then(function() {
- assert_equals(handler.transitionstart, 0.0);
-
- // Seek to After phase.
- transition.finish();
- return watcher.wait_for('transitionend');
- }).then(function(evt) {
- assert_equals(evt.elapsedTime, 50.0);
- });
-}, 'Calculating the interval start and end time with negative end delay.');
-
-done();
-</script>
-</body>
-</html>
diff --git a/dom/animation/test/css-transitions/file_event-dispatch.html b/dom/animation/test/css-transitions/file_event-dispatch.html
new file mode 100644
index 000000000..7140cda36
--- /dev/null
+++ b/dom/animation/test/css-transitions/file_event-dispatch.html
@@ -0,0 +1,474 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Tests for CSS-Transition events</title>
+<link rel="help" href="https://drafts.csswg.org/css-transitions-2/#transition-events">
+<script src="../testcommon.js"></script>
+<body>
+<script>
+'use strict';
+
+/**
+ * Helper class to record the elapsedTime member of each event.
+ * The EventWatcher class in testharness.js allows us to wait on
+ * multiple events in a certain order but only records the event
+ * parameters of the most recent event.
+ */
+function TransitionEventHandler(target) {
+ this.target = target;
+ this.target.ontransitionrun = function(evt) {
+ this.transitionrun = evt.elapsedTime;
+ }.bind(this);
+ this.target.ontransitionstart = function(evt) {
+ this.transitionstart = evt.elapsedTime;
+ }.bind(this);
+ this.target.ontransitionend = function(evt) {
+ this.transitionend = evt.elapsedTime;
+ }.bind(this);
+ this.target.ontransitioncancel = function(evt) {
+ this.transitioncancel = evt.elapsedTime;
+ }.bind(this);
+}
+
+TransitionEventHandler.prototype.clear = function() {
+ this.transitionrun = undefined;
+ this.transitionstart = undefined;
+ this.transitionend = undefined;
+ this.transitioncancel = undefined;
+};
+
+function setupTransition(t, transitionStyle) {
+ var div = addDiv(t, { style: 'transition: ' + transitionStyle });
+ var watcher = new EventWatcher(t, div, [ 'transitionrun',
+ 'transitionstart',
+ 'transitionend',
+ 'transitioncancel' ]);
+ flushComputedStyle(div);
+
+ div.style.marginLeft = '100px';
+ var transition = div.getAnimations()[0];
+
+ return [transition, watcher, div];
+}
+
+// On the next frame (i.e. when events are queued), whether or not the
+// transition is still pending depends on the implementation.
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s 100s');
+ return watcher.wait_for('transitionrun').then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Idle -> Pending or Before');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s 100s');
+ // Force the transition to leave the idle phase
+ transition.startTime = document.timeline.currentTime;
+ return watcher.wait_for('transitionrun').then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Idle -> Before');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+ var handler = new TransitionEventHandler(div);
+
+ // Seek to Active phase.
+ transition.currentTime = 100 * MS_PER_SEC;
+ transition.pause();
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ assert_equals(handler.transitionrun, 0.0);
+ assert_equals(handler.transitionstart, 0.0);
+ });
+}, 'Idle or Pending -> Active');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+ var handler = new TransitionEventHandler(div);
+
+ // Seek to After phase.
+ transition.finish();
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart',
+ 'transitionend' ]).then(function(evt) {
+ assert_equals(handler.transitionrun, 0.0);
+ assert_equals(handler.transitionstart, 0.0);
+ assert_equals(handler.transitionend, 100.0);
+ });
+}, 'Idle or Pending -> After');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+
+ return Promise.all([ watcher.wait_for('transitionrun'),
+ transition.ready ]).then(function() {
+ // Make idle
+ div.style.display = 'none';
+ flushComputedStyle(div);
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Before -> Idle (display: none)');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s 100s');
+
+ return Promise.all([ watcher.wait_for('transitionrun'),
+ transition.ready ]).then(function() {
+ // Make idle
+ transition.timeline = null;
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Before -> Idle (Animation.timeline = null)');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s 100s');
+
+ return Promise.all([ watcher.wait_for('transitionrun'),
+ transition.ready ]).then(function() {
+ transition.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for('transitionstart');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Before -> Active');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+ var handler = new TransitionEventHandler(div);
+
+ return Promise.all([ watcher.wait_for('transitionrun'),
+ transition.ready ]).then(function() {
+ // Seek to After phase.
+ transition.currentTime = 200 * MS_PER_SEC;
+ return watcher.wait_for([ 'transitionstart', 'transitionend' ]);
+ }).then(function(evt) {
+ assert_equals(handler.transitionstart, 0.0);
+ assert_equals(handler.transitionend, 100.0);
+ });
+}, 'Before -> After');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s');
+
+ // Seek to Active start position.
+ transition.pause();
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Make idle
+ div.style.display = 'none';
+ flushComputedStyle(div);
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Active -> Idle, no delay (display: none)');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s');
+
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Make idle
+ transition.currentTime = 0;
+ transition.timeline = null;
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Active -> Idle, no delay (Animation.timeline = null)');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+ // Pause so the currentTime is fixed and we can accurately compare the event
+ // time in transition cancel events.
+ transition.pause();
+
+ // Seek to Active phase.
+ transition.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Make idle
+ div.style.display = 'none';
+ flushComputedStyle(div);
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Active -> Idle, with positive delay (display: none)');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s 100s');
+
+ // Seek to Active phase.
+ transition.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Make idle
+ transition.currentTime = 100 * MS_PER_SEC;
+ transition.timeline = null;
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Active -> Idle, with positive delay (Animation.timeline = null)');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s -50s');
+
+ // Pause so the currentTime is fixed and we can accurately compare the event
+ // time in transition cancel events.
+ transition.pause();
+
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Make idle
+ div.style.display = 'none';
+ flushComputedStyle(div);
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 50.0);
+ });
+}, 'Active -> Idle, with negative delay (display: none)');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s -50s');
+
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Make idle
+ transition.currentTime = 50 * MS_PER_SEC;
+ transition.timeline = null;
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Active -> Idle, with negative delay (Animation.timeline = null)');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s 100s');
+ // Seek to Active phase.
+ transition.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Seek to Before phase.
+ transition.currentTime = 0;
+ return watcher.wait_for('transitionend');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 0.0);
+ });
+}, 'Active -> Before');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s 100s');
+ // Seek to Active phase.
+ transition.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Seek to After phase.
+ transition.currentTime = 200 * MS_PER_SEC;
+ return watcher.wait_for('transitionend');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 100.0);
+ });
+}, 'Active -> After');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+ var handler = new TransitionEventHandler(div);
+
+ // Seek to After phase.
+ transition.finish();
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart',
+ 'transitionend' ]).then(function(evt) {
+ // Seek to Before phase.
+ transition.currentTime = 0;
+ return watcher.wait_for([ 'transitionstart', 'transitionend' ]);
+ }).then(function(evt) {
+ assert_equals(handler.transitionstart, 100.0);
+ assert_equals(handler.transitionend, 0.0);
+ });
+}, 'After -> Before');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s 100s');
+ // Seek to After phase.
+ transition.finish();
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart',
+ 'transitionend' ]).then(function(evt) {
+ // Seek to Active phase.
+ transition.currentTime = 100 * MS_PER_SEC;
+ return watcher.wait_for('transitionstart');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 100.0);
+ });
+}, 'After -> Active');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s -50s');
+ var handler = new TransitionEventHandler(div);
+
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function() {
+ assert_equals(handler.transitionrun, 50.0);
+ assert_equals(handler.transitionstart, 50.0);
+ transition.finish();
+ return watcher.wait_for('transitionend');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 100.0);
+ });
+}, 'Calculating the interval start and end time with negative start delay.');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+ var handler = new TransitionEventHandler(div);
+
+ return watcher.wait_for('transitionrun').then(function(evt) {
+ // We can't set the end delay via generated effect timing.
+ // Because CSS-Transition use the AnimationEffectTimingReadOnly.
+ transition.effect = new KeyframeEffect(div,
+ { marginleft: [ '0px', '100px' ]},
+ { duration: 100 * MS_PER_SEC,
+ endDelay: -50 * MS_PER_SEC });
+ // Seek to Before and play.
+ transition.cancel();
+ transition.play();
+ return watcher.wait_for([ 'transitioncancel',
+ 'transitionrun',
+ 'transitionstart' ]);
+ }).then(function() {
+ assert_equals(handler.transitionstart, 0.0);
+
+ // Seek to After phase.
+ transition.finish();
+ return watcher.wait_for('transitionend');
+ }).then(function(evt) {
+ assert_equals(evt.elapsedTime, 50.0);
+ });
+}, 'Calculating the interval start and end time with negative end delay.');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+
+ return watcher.wait_for('transitionrun').then(function() {
+ // Make idle
+ div.style.display = 'none';
+ flushComputedStyle(div);
+ return watcher.wait_for('transitioncancel');
+ }).then(function() {
+ transition.cancel();
+ // Then wait a couple of frames and check that no event was dispatched
+ return waitForAnimationFrames(2);
+ });
+}, 'Call Animation.cancel after cancelling transition.');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+
+ return watcher.wait_for('transitionrun').then(function(evt) {
+ // Make idle
+ div.style.display = 'none';
+ flushComputedStyle(div);
+ transition.play();
+ watcher.wait_for([ 'transitioncancel',
+ 'transitionrun',
+ 'transitionstart' ]);
+ });
+}, 'Restart transition after cancelling transition immediately');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s 100s');
+
+ return watcher.wait_for('transitionrun').then(function(evt) {
+ // Make idle
+ div.style.display = 'none';
+ flushComputedStyle(div);
+ transition.play();
+ transition.cancel();
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ // Then wait a couple of frames and check that no event was dispatched
+ return waitForAnimationFrames(2);
+ });
+}, 'Call Animation.cancel after restarting transition immediately');
+
+promise_test(function(t) {
+ var [transition, watcher] =
+ setupTransition(t, 'margin-left 100s');
+
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ // Make idle
+ transition.timeline = null;
+ return watcher.wait_for('transitioncancel');
+ }).then(function(evt) {
+ transition.timeline = document.timeline;
+ transition.play();
+
+ return watcher.wait_for(['transitionrun', 'transitionstart']);
+ });
+}, 'Set timeline and play transition after clear the timeline');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s');
+
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function() {
+ transition.cancel();
+ return watcher.wait_for('transitioncancel');
+ }).then(function() {
+ // Make After phase
+ transition.effect = null;
+
+ // Then wait a couple of frames and check that no event was dispatched
+ return waitForAnimationFrames(2);
+ });
+}, 'Set null target effect after cancel the transition');
+
+promise_test(function(t) {
+ var [transition, watcher, div] =
+ setupTransition(t, 'margin-left 100s');
+
+ return watcher.wait_for([ 'transitionrun',
+ 'transitionstart' ]).then(function(evt) {
+ transition.effect = null;
+ return watcher.wait_for('transitionend');
+ }).then(function(evt) {
+ transition.cancel();
+ return watcher.wait_for('transitioncancel');
+ });
+}, 'Cancel the transition after clearing the target effect');
+
+done();
+</script>
+</body>
+</html>
diff --git a/dom/animation/test/css-transitions/file_setting-effect.html b/dom/animation/test/css-transitions/file_setting-effect.html
index c61877194..81279ea55 100644
--- a/dom/animation/test/css-transitions/file_setting-effect.html
+++ b/dom/animation/test/css-transitions/file_setting-effect.html
@@ -7,6 +7,8 @@
promise_test(function(t) {
var div = addDiv(t);
+ var watcher = new EventWatcher(t, div, [ 'transitionend',
+ 'transitioncancel' ]);
div.style.left = '0px';
div.style.transition = 'left 100s';
@@ -20,11 +22,14 @@ promise_test(function(t) {
assert_equals(transition.transitionProperty, 'left');
assert_equals(transition.playState, 'finished');
assert_equals(window.getComputedStyle(div).left, '100px');
+ return watcher.wait_for('transitionend');
});
}, 'Test for removing a transition effect');
promise_test(function(t) {
var div = addDiv(t);
+ var watcher = new EventWatcher(t, div, [ 'transitionend',
+ 'transitioncancel' ]);
div.style.left = '0px';
div.style.transition = 'left 100s';
@@ -46,6 +51,8 @@ promise_test(function(t) {
promise_test(function(t) {
var div = addDiv(t);
+ var watcher = new EventWatcher(t, div, [ 'transitionend',
+ 'transitioncancel' ]);
div.style.left = '0px';
div.style.width = '0px';
@@ -65,6 +72,8 @@ promise_test(function(t) {
promise_test(function(t) {
var div = addDiv(t);
+ var watcher = new EventWatcher(t, div, [ 'transitionend',
+ 'transitioncancel' ]);
div.style.left = '0px';
div.style.width = '0px';
diff --git a/dom/animation/test/css-transitions/test_event-dispatch.html b/dom/animation/test/css-transitions/test_event-dispatch.html
new file mode 100644
index 000000000..c90431cd1
--- /dev/null
+++ b/dom/animation/test/css-transitions/test_event-dispatch.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+'use strict';
+setup({explicit_done: true});
+SpecialPowers.pushPrefEnv(
+ { "set": [["dom.animations-api.core.enabled", true]]},
+ function() {
+ window.open("file_event-dispatch.html");
+ });
+</script>
diff --git a/dom/animation/test/mochitest.ini b/dom/animation/test/mochitest.ini
index feb424518..db6dffada 100644
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -19,6 +19,8 @@ support-files =
css-animations/file_document-get-animations.html
css-animations/file_effect-target.html
css-animations/file_element-get-animations.html
+ css-animations/file_event-dispatch.html
+ css-animations/file_event-order.html
css-animations/file_keyframeeffect-getkeyframes.html
css-animations/file_pseudoElement-get-animations.html
css-transitions/file_animation-cancel.html
@@ -32,6 +34,7 @@ support-files =
css-transitions/file_document-get-animations.html
css-transitions/file_effect-target.html
css-transitions/file_element-get-animations.html
+ css-transitions/file_event-dispatch.html
css-transitions/file_keyframeeffect-getkeyframes.html
css-transitions/file_pseudoElement-get-animations.html
css-transitions/file_setting-effect.html
@@ -72,6 +75,8 @@ support-files =
[css-animations/test_document-get-animations.html]
[css-animations/test_effect-target.html]
[css-animations/test_element-get-animations.html]
+[css-animations/test_event-dispatch.html]
+[css-animations/test_event-order.html]
[css-animations/test_keyframeeffect-getkeyframes.html]
[css-animations/test_pseudoElement-get-animations.html]
[css-transitions/test_animation-cancel.html]
@@ -85,6 +90,7 @@ support-files =
[css-transitions/test_document-get-animations.html]
[css-transitions/test_effect-target.html]
[css-transitions/test_element-get-animations.html]
+[css-transitions/test_event-dispatch.html]
[css-transitions/test_keyframeeffect-getkeyframes.html]
[css-transitions/test_pseudoElement-get-animations.html]
[css-transitions/test_setting-effect.html]
diff --git a/dom/apps/AppsUtils.jsm b/dom/apps/AppsUtils.jsm
index 3ca3f8552..2bd6a4133 100644
--- a/dom/apps/AppsUtils.jsm
+++ b/dom/apps/AppsUtils.jsm
@@ -312,9 +312,6 @@ this.AppsUtils = {
// Instead, we check if the app is installed under /system/b2g
let isCoreApp = false;
-#ifdef MOZ_WIDGET_GONK
- isCoreApp = app.basePath == this.getCoreAppsBasePath();
-#endif
debug(app.basePath + " isCoreApp: " + isCoreApp);
return { "path": app.basePath + "/" + app.id,
diff --git a/dom/audiochannel/AudioChannelService.cpp b/dom/audiochannel/AudioChannelService.cpp
index 87cde41e9..db6f2037b 100644
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -27,11 +27,6 @@
#include "nsServiceManagerUtils.h"
#include "mozilla/dom/SettingChangeNotificationBinding.h"
-#ifdef MOZ_WIDGET_GONK
-#include "nsJSUtils.h"
-#include "SpeakerManagerService.h"
-#endif
-
#include "mozilla/Preferences.h"
using namespace mozilla;
@@ -237,20 +232,12 @@ AudioChannelService::Shutdown()
if (IsParentProcess()) {
obs->RemoveObserver(gAudioChannelService, "ipc:content-shutdown");
-
-#ifdef MOZ_WIDGET_GONK
- // To monitor the volume settings based on audio channel.
- obs->RemoveObserver(gAudioChannelService, "mozsettings-changed");
-#endif
}
}
gAudioChannelService->mWindows.Clear();
gAudioChannelService->mPlayingChildren.Clear();
gAudioChannelService->mTabParents.Clear();
-#ifdef MOZ_WIDGET_GONK
- gAudioChannelService->mSpeakerManager.Clear();
-#endif
gAudioChannelService = nullptr;
}
@@ -284,11 +271,6 @@ AudioChannelService::AudioChannelService()
obs->AddObserver(this, "outer-window-destroyed", false);
if (IsParentProcess()) {
obs->AddObserver(this, "ipc:content-shutdown", false);
-
-#ifdef MOZ_WIDGET_GONK
- // To monitor the volume settings based on audio channel.
- obs->AddObserver(this, "mozsettings-changed", false);
-#endif
}
}
@@ -342,13 +324,6 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
RefPtr<AudioChannelAgent> kungFuDeathGrip(aAgent);
winData->RemoveAgent(aAgent);
-#ifdef MOZ_WIDGET_GONK
- bool active = AnyAudioChannelIsActive();
- for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) {
- mSpeakerManager[i]->SetAudioChannelActive(active);
- }
-#endif
-
MaybeSendStatusUpdate();
}
@@ -573,13 +548,6 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic,
iter.GetNext()->WindowVolumeChanged();
}
}
-
-#ifdef MOZ_WIDGET_GONK
- bool active = AnyAudioChannelIsActive();
- for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) {
- mSpeakerManager[i]->SetAudioChannelActive(active);
- }
-#endif
} else if (!strcmp(aTopic, "ipc:content-shutdown")) {
nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
if (!props) {
diff --git a/dom/audiochannel/AudioChannelService.h b/dom/audiochannel/AudioChannelService.h
index b16832b5f..7d3de8a46 100644
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -25,10 +25,6 @@ struct PRLogModuleInfo;
namespace mozilla {
namespace dom {
-#ifdef MOZ_WIDGET_GONK
-class SpeakerManagerService;
-#endif
-
class TabParent;
#define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::EndGuard_
@@ -189,20 +185,6 @@ public:
uint64_t aInnerWindowID,
bool aCapture);
-#ifdef MOZ_WIDGET_GONK
- void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager)
- {
- if (!mSpeakerManager.Contains(aSpeakerManager)) {
- mSpeakerManager.AppendElement(aSpeakerManager);
- }
- }
-
- void UnregisterSpeakerManager(SpeakerManagerService* aSpeakerManager)
- {
- mSpeakerManager.RemoveElement(aSpeakerManager);
- }
-#endif
-
static const nsAttrValue::EnumTable* GetAudioChannelTable();
static AudioChannel GetAudioChannel(const nsAString& aString);
static AudioChannel GetDefaultAudioChannel();
@@ -347,10 +329,6 @@ private:
nsTObserverArray<nsAutoPtr<AudioChannelChildStatus>> mPlayingChildren;
-#ifdef MOZ_WIDGET_GONK
- nsTArray<SpeakerManagerService*> mSpeakerManager;
-#endif
-
// Raw pointers because TabParents must unregister themselves.
nsTArray<TabParent*> mTabParents;
diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp
index 169c3fe7a..e39abf1a6 100644
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -47,6 +47,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueuedEntries)
+ tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver)
@@ -184,9 +185,10 @@ DOMIntersectionObserver::Connect()
if (mConnected) {
return;
}
+ mConnected = true;
+
nsIDocument* document = mOwner->GetExtantDoc();
document->AddIntersectionObserver(this);
- mConnected = true;
}
void
@@ -202,7 +204,9 @@ DOMIntersectionObserver::Disconnect()
mObservationTargets.Clear();
if (mOwner) {
nsIDocument* document = mOwner->GetExtantDoc();
- document->RemoveIntersectionObserver(this);
+ if (document) {
+ document->RemoveIntersectionObserver(this);
+ }
}
mConnected = false;
}
@@ -248,6 +252,12 @@ EdgeInclusiveIntersection(const nsRect& aRect, const nsRect& aOtherRect)
return Some(nsRect(left, top, right - left, bottom - top));
}
+enum class BrowsingContextInfo {
+ SimilarOriginBrowsingContext,
+ DifferentOriginBrowsingContext,
+ UnknownBrowsingContext
+};
+
void
DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time)
{
@@ -359,11 +369,22 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
}
}
- nsRect rootIntersectionRect = rootRect;
- bool isInSimilarOriginBrowsingContext = rootFrame && targetFrame &&
- CheckSimilarOrigin(root, target);
+ nsRect rootIntersectionRect;
+ BrowsingContextInfo isInSimilarOriginBrowsingContext =
+ BrowsingContextInfo::UnknownBrowsingContext;
+
+ if (rootFrame && targetFrame) {
+ rootIntersectionRect = rootRect;
+ }
+
+ if (root && target) {
+ isInSimilarOriginBrowsingContext = CheckSimilarOrigin(root, target) ?
+ BrowsingContextInfo::SimilarOriginBrowsingContext :
+ BrowsingContextInfo::DifferentOriginBrowsingContext;
+ }
- if (isInSimilarOriginBrowsingContext) {
+ if (isInSimilarOriginBrowsingContext ==
+ BrowsingContextInfo::SimilarOriginBrowsingContext) {
rootIntersectionRect.Inflate(rootMargin);
}
@@ -413,7 +434,9 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
if (target->UpdateIntersectionObservation(this, threshold)) {
QueueIntersectionObserverEntry(
target, time,
- isInSimilarOriginBrowsingContext ? Some(rootIntersectionRect) : Nothing(),
+ isInSimilarOriginBrowsingContext ==
+ BrowsingContextInfo::DifferentOriginBrowsingContext ?
+ Nothing() : Some(rootIntersectionRect),
targetRect, intersectionRect, intersectionRatio
);
}
diff --git a/dom/base/DOMIntersectionObserver.h b/dom/base/DOMIntersectionObserver.h
index 3eb10ad38..8144fc5c5 100644
--- a/dom/base/DOMIntersectionObserver.h
+++ b/dom/base/DOMIntersectionObserver.h
@@ -101,9 +101,7 @@ protected:
class DOMIntersectionObserver final : public nsISupports,
public nsWrapperCache
{
- virtual ~DOMIntersectionObserver() {
- Disconnect();
- }
+ virtual ~DOMIntersectionObserver() { }
public:
DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 9ced64c0d..52d06b0f8 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -183,6 +183,12 @@ Element::DoGetClasses() const
NS_IMETHODIMP
Element::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
+ if (aIID.Equals(NS_GET_IID(Element))) {
+ NS_ADDREF_THIS();
+ *aInstancePtr = this;
+ return NS_OK;
+ }
+
NS_ASSERTION(aInstancePtr,
"QueryInterface requires a non-NULL destination!");
nsresult rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr);
@@ -1838,6 +1844,24 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
SetParentIsContent(false);
}
+#ifdef DEBUG
+ // If we can get access to the PresContext, then we sanity-check that
+ // we're not leaving behind a pointer to ourselves as the PresContext's
+ // cached provider of the viewport's scrollbar styles.
+ if (document) {
+ nsIPresShell* presShell = document->GetShell();
+ if (presShell) {
+ nsPresContext* presContext = presShell->GetPresContext();
+ if (presContext) {
+ MOZ_ASSERT(this !=
+ presContext->GetViewportScrollbarStylesOverrideNode(),
+ "Leaving behind a raw pointer to this node (as having "
+ "propagated scrollbar styles) - that's dangerous...");
+ }
+ }
+ }
+#endif
+
// Ensure that CSS transitions don't continue on an element at a
// different place in the tree (even if reinserted before next
// animation refresh).
@@ -3888,44 +3912,55 @@ Element::ClearDataset()
slots->mDataset = nullptr;
}
-nsTArray<Element::nsDOMSlots::IntersectionObserverRegistration>*
+nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>*
Element::RegisteredIntersectionObservers()
{
nsDOMSlots* slots = DOMSlots();
return &slots->mRegisteredIntersectionObservers;
}
+enum nsPreviousIntersectionThreshold {
+ eUninitialized = -2,
+ eNonIntersecting = -1
+};
+
void
Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{
- RegisteredIntersectionObservers()->AppendElement(
- nsDOMSlots::IntersectionObserverRegistration { aObserver, -1 });
+ nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
+ RegisteredIntersectionObservers();
+ if (observers->Contains(aObserver)) {
+ return;
+ }
+
+ // Value can be:
+ // -2: Makes sure next calculated threshold always differs, leading to a
+ // notification task being scheduled.
+ // -1: Non-intersecting.
+ // >= 0: Intersecting, valid index of aObserver->mThresholds.
+ RegisteredIntersectionObservers()->Put(aObserver, eUninitialized);
}
void
Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{
- nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers =
+ nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
RegisteredIntersectionObservers();
- for (uint32_t i = 0; i < observers->Length(); ++i) {
- nsDOMSlots::IntersectionObserverRegistration reg = observers->ElementAt(i);
- if (reg.observer == aObserver) {
- observers->RemoveElementAt(i);
- break;
- }
- }
+ observers->Remove(aObserver);
}
bool
Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
{
- nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers =
+ nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
RegisteredIntersectionObservers();
- for (auto& reg : *observers) {
- if (reg.observer == aObserver && reg.previousThreshold != aThreshold) {
- reg.previousThreshold = aThreshold;
- return true;
- }
+ if (!observers->Contains(aObserver)) {
+ return false;
+ }
+ int32_t previousThreshold = observers->Get(aObserver);
+ if (previousThreshold != aThreshold) {
+ observers->Put(aObserver, aThreshold);
+ return true;
}
return false;
}
diff --git a/dom/base/Element.h b/dom/base/Element.h
index cf1d197e2..049984d1b 100644
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -1380,7 +1380,7 @@ protected:
nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
- nsTArray<nsDOMSlots::IntersectionObserverRegistration>* RegisteredIntersectionObservers();
+ nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* RegisteredIntersectionObservers();
private:
/**
diff --git a/dom/base/File.cpp b/dom/base/File.cpp
index 8602a3064..7d86dfe8a 100755
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -912,7 +912,7 @@ BlobImplFile::GetType(nsAString& aType)
new GetTypeRunnable(workerPrivate, this);
ErrorResult rv;
- runnable->Dispatch(rv);
+ runnable->Dispatch(Terminating, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
}
diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
index 79f6cff51..fde983e7c 100644
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -608,6 +608,7 @@ FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL)
mLabelsList = nullptr;
mCustomElementData = nullptr;
mClassList = nullptr;
+ mRegisteredIntersectionObservers.Clear();
}
size_t
@@ -1359,6 +1360,13 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
{
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) {
+ if (tmp->IsElement()) {
+ Element* elem = tmp->AsElement();
+ for (auto iter = slots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ DOMIntersectionObserver* observer = iter.Key();
+ observer->UnlinkTarget(*elem);
+ }
+ }
slots->Unlink(tmp->IsXULElement());
}
}
@@ -1937,7 +1945,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN(FragmentOrElement)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(FragmentOrElement)
- NS_INTERFACE_MAP_ENTRY(Element)
NS_INTERFACE_MAP_ENTRY(nsIContent)
NS_INTERFACE_MAP_ENTRY(nsINode)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
diff --git a/dom/base/FragmentOrElement.h b/dom/base/FragmentOrElement.h
index 1cd8033bb..7c74e9cd4 100644
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -21,6 +21,7 @@
#include "nsIWeakReference.h" // base class
#include "nsNodeUtils.h" // class member nsNodeUtils::CloneNodeImpl
#include "nsIHTMLCollection.h"
+#include "nsDataHashtable.h"
class ContentUnbinder;
class nsContentList;
@@ -353,12 +354,7 @@ public:
/**
* Registered Intersection Observers on the element.
*/
- struct IntersectionObserverRegistration {
- DOMIntersectionObserver* observer;
- int32_t previousThreshold;
- };
-
- nsTArray<IntersectionObserverRegistration> mRegisteredIntersectionObservers;
+ nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t> mRegisteredIntersectionObservers;
};
protected:
diff --git a/dom/base/IdleRequest.cpp b/dom/base/IdleRequest.cpp
index 26190f98b..fb3983d37 100644
--- a/dom/base/IdleRequest.cpp
+++ b/dom/base/IdleRequest.cpp
@@ -9,7 +9,6 @@
#include "mozilla/Function.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/IdleDeadline.h"
-#include "mozilla/dom/Performance.h"
#include "mozilla/dom/PerformanceTiming.h"
#include "mozilla/dom/WindowBinding.h"
#include "nsComponentManagerUtils.h"
@@ -20,138 +19,56 @@
namespace mozilla {
namespace dom {
-IdleRequest::IdleRequest(JSContext* aCx, nsPIDOMWindowInner* aWindow,
- IdleRequestCallback& aCallback, uint32_t aHandle)
- : mWindow(aWindow)
- , mCallback(&aCallback)
+IdleRequest::IdleRequest(IdleRequestCallback* aCallback, uint32_t aHandle)
+ : mCallback(aCallback)
, mHandle(aHandle)
, mTimeoutHandle(Nothing())
{
- MOZ_ASSERT(aWindow);
-
- // Get the calling location.
- nsJSUtils::GetCallingLocation(aCx, mFileName, &mLineNo, &mColumn);
+ MOZ_DIAGNOSTIC_ASSERT(mCallback);
}
IdleRequest::~IdleRequest()
{
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequest)
+NS_IMPL_CYCLE_COLLECTION(IdleRequest, mCallback)
NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequest)
NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequest)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequest)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequest)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequest)
- NS_INTERFACE_MAP_ENTRY(nsIRunnable)
- NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)
- NS_INTERFACE_MAP_ENTRY(nsIIncrementalRunnable)
- NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimeoutHandler)
NS_INTERFACE_MAP_END
-nsresult
-IdleRequest::SetTimeout(uint32_t aTimeout)
-{
- int32_t handle;
- nsresult rv = nsGlobalWindow::Cast(mWindow)->SetTimeoutOrInterval(
- this, aTimeout, false, Timeout::Reason::eIdleCallbackTimeout, &handle);
- mTimeoutHandle = Some(handle);
-
- return rv;
-}
-
-nsresult
-IdleRequest::Run()
-{
- if (mCallback) {
- RunIdleRequestCallback(false);
- }
-
- return NS_OK;
-}
-
-nsresult
-IdleRequest::Cancel()
+void
+IdleRequest::SetTimeoutHandle(int32_t aHandle)
{
- mCallback = nullptr;
- CancelTimeout();
- if (isInList()) {
- remove();
- }
- Release();
-
- return NS_OK;
+ mTimeoutHandle = Some(aHandle);
}
-void
-IdleRequest::SetDeadline(TimeStamp aDeadline)
+uint32_t
+IdleRequest::GetTimeoutHandle() const
{
- mozilla::dom::Performance* perf = mWindow->GetPerformance();
- mDeadline =
- perf ? perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline) : 0.0;
+ MOZ_DIAGNOSTIC_ASSERT(mTimeoutHandle.isSome());
+ return mTimeoutHandle.value();
}
nsresult
-IdleRequest::RunIdleRequestCallback(bool aDidTimeout)
+IdleRequest::IdleRun(nsPIDOMWindowInner* aWindow,
+ DOMHighResTimeStamp aDeadline,
+ bool aDidTimeout)
{
MOZ_ASSERT(NS_IsMainThread());
+ MOZ_DIAGNOSTIC_ASSERT(mCallback);
- if (!aDidTimeout) {
- CancelTimeout();
- }
-
- remove();
ErrorResult error;
RefPtr<IdleDeadline> deadline =
- new IdleDeadline(mWindow, aDidTimeout, mDeadline);
+ new IdleDeadline(aWindow, aDidTimeout, aDeadline);
mCallback->Call(*deadline, error, "requestIdleCallback handler");
- mCallback = nullptr;
- Release();
+ mCallback = nullptr;
+ error.SuppressException();
return error.StealNSResult();
}
-void
-IdleRequest::CancelTimeout()
-{
- if (mTimeoutHandle.isSome()) {
- nsGlobalWindow::Cast(mWindow)->ClearTimeoutOrInterval(
- mTimeoutHandle.value(), Timeout::Reason::eIdleCallbackTimeout);
- }
-}
-
-nsresult
-IdleRequest::Call()
-{
- SetDeadline(TimeStamp::Now());
- return RunIdleRequestCallback(true);
-}
-
-void
-IdleRequest::GetLocation(const char** aFileName, uint32_t* aLineNo,
- uint32_t* aColumn)
-{
- *aFileName = mFileName.get();
- *aLineNo = mLineNo;
- *aColumn = mColumn;
-}
-
-void
-IdleRequest::MarkForCC()
-{
- mCallback->MarkForCC();
-}
-
} // namespace dom
} // namespace mozilla
diff --git a/dom/base/IdleRequest.h b/dom/base/IdleRequest.h
index cb234430a..acf56f852 100644
--- a/dom/base/IdleRequest.h
+++ b/dom/base/IdleRequest.h
@@ -12,7 +12,6 @@
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsDOMNavigationTiming.h"
-#include "nsITimeoutHandler.h"
class nsPIDOMWindowInner;
@@ -21,28 +20,19 @@ namespace dom {
class IdleRequestCallback;
-class IdleRequest final : public nsITimeoutHandler
- , public nsIRunnable
- , public nsICancelableRunnable
- , public nsIIncrementalRunnable
- , public LinkedListElement<IdleRequest>
+class IdleRequest final : public nsISupports,
+ public LinkedListElement<IdleRequest>
{
public:
- IdleRequest(JSContext* aCx, nsPIDOMWindowInner* aWindow,
- IdleRequestCallback& aCallback, uint32_t aHandle);
+ IdleRequest(IdleRequestCallback* aCallback, uint32_t aHandle);
- virtual nsresult Call() override;
- virtual void GetLocation(const char** aFileName, uint32_t* aLineNo,
- uint32_t* aColumn) override;
- virtual void MarkForCC() override;
+ nsresult IdleRun(nsPIDOMWindowInner* aWindow,
+ DOMHighResTimeStamp aDeadline,
+ bool aDidTimeout);
- nsresult SetTimeout(uint32_t aTimout);
- nsresult RunIdleRequestCallback(bool aDidTimeout);
- void CancelTimeout();
-
- NS_DECL_NSIRUNNABLE;
- virtual nsresult Cancel() override;
- virtual void SetDeadline(mozilla::TimeStamp aDeadline) override;
+ void SetTimeoutHandle(int32_t aHandle);
+ bool HasTimeout() const { return mTimeoutHandle.isSome(); }
+ uint32_t GetTimeoutHandle() const;
uint32_t Handle() const
{
@@ -50,22 +40,14 @@ public:
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequest, nsITimeoutHandler)
+ NS_DECL_CYCLE_COLLECTION_CLASS(IdleRequest)
private:
~IdleRequest();
- // filename, line number and JS language version string of the
- // caller of setTimeout()
- nsCString mFileName;
- uint32_t mLineNo;
- uint32_t mColumn;
-
- nsCOMPtr<nsPIDOMWindowInner> mWindow;
RefPtr<IdleRequestCallback> mCallback;
- uint32_t mHandle;
+ const uint32_t mHandle;
mozilla::Maybe<int32_t> mTimeoutHandle;
- DOMHighResTimeStamp mDeadline;
};
} // namespace dom
diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp
index e3b614931..7b3722f09 100644
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -393,6 +393,10 @@ Location::GetHost(nsAString& aHost)
NS_IMETHODIMP
Location::SetHost(const nsAString& aHost)
{
+ if (aHost.IsEmpty()) {
+ return NS_OK; // Ignore empty string
+ }
+
nsCOMPtr<nsIURI> uri;
nsresult rv = GetWritableURI(getter_AddRefs(uri));
if (NS_WARN_IF(NS_FAILED(rv) || !uri)) {
@@ -424,6 +428,10 @@ Location::GetHostname(nsAString& aHostname)
NS_IMETHODIMP
Location::SetHostname(const nsAString& aHostname)
{
+ if (aHostname.IsEmpty()) {
+ return NS_OK; // Ignore empty string
+ }
+
nsCOMPtr<nsIURI> uri;
nsresult rv = GetWritableURI(getter_AddRefs(uri));
if (NS_WARN_IF(NS_FAILED(rv) || !uri)) {
@@ -507,6 +515,10 @@ nsresult
Location::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
bool aReplace)
{
+ if (aHref.IsEmpty()) {
+ return NS_OK; // Ignore empty string
+ }
+
nsresult result;
nsCOMPtr<nsIURI> newUri;
@@ -577,19 +589,17 @@ Location::GetPathname(nsAString& aPathname)
aPathname.Truncate();
nsCOMPtr<nsIURI> uri;
- nsresult result = NS_OK;
-
- result = GetURI(getter_AddRefs(uri));
+ nsresult result = GetURI(getter_AddRefs(uri));
+ if (NS_FAILED(result) || !uri) {
+ return result;
+ }
- nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(uri));
- if (url) {
- nsAutoCString file;
+ nsAutoCString file;
- result = url->GetFilePath(file);
+ result = uri->GetFilePath(file);
- if (NS_SUCCEEDED(result)) {
- AppendUTF8toUTF16(file, aPathname);
- }
+ if (NS_SUCCEEDED(result)) {
+ AppendUTF8toUTF16(file, aPathname);
}
return result;
@@ -604,8 +614,7 @@ Location::SetPathname(const nsAString& aPathname)
return rv;
}
- nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(uri));
- if (url && NS_SUCCEEDED(url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) {
+ if (NS_SUCCEEDED(uri->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) {
return SetURI(uri);
}
@@ -697,6 +706,10 @@ Location::GetProtocol(nsAString& aProtocol)
NS_IMETHODIMP
Location::SetProtocol(const nsAString& aProtocol)
{
+ if (aProtocol.IsEmpty()) {
+ return NS_OK; // Ignore empty string
+ }
+
nsCOMPtr<nsIURI> uri;
nsresult rv = GetWritableURI(getter_AddRefs(uri));
if (NS_WARN_IF(NS_FAILED(rv) || !uri)) {
@@ -750,6 +763,10 @@ Location::GetSearch(nsAString& aSearch)
NS_IMETHODIMP
Location::SetSearch(const nsAString& aSearch)
{
+ if (aSearch.IsEmpty()) {
+ return NS_OK; // Ignore empty string
+ }
+
nsresult rv = SetSearchInternal(aSearch);
if (NS_FAILED(rv)) {
return rv;
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
index 5c315517c..ed96ee23b 100644
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -767,12 +767,6 @@ StaticRefPtr<VibrateWindowListener> gVibrateWindowListener;
static bool
MayVibrate(nsIDocument* doc) {
-#if MOZ_WIDGET_GONK
- if (XRE_IsParentProcess()) {
- return true; // The system app can always vibrate
- }
-#endif // MOZ_WIDGET_GONK
-
// Hidden documents cannot start or stop a vibration.
return (doc && !doc->Hidden());
}
diff --git a/dom/base/ScreenOrientation.cpp b/dom/base/ScreenOrientation.cpp
index bb3ccf5c3..ec9c4fa29 100644
--- a/dom/base/ScreenOrientation.cpp
+++ b/dom/base/ScreenOrientation.cpp
@@ -309,7 +309,7 @@ ScreenOrientation::LockInternal(ScreenOrientationInternal aOrientation, ErrorRes
return nullptr;
}
-#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
+#if !defined(MOZ_WIDGET_ANDROID)
// User agent does not support locking the screen orientation.
p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return p.forget();
diff --git a/dom/base/StructuredCloneHolder.cpp b/dom/base/StructuredCloneHolder.cpp
index 1c27c632e..8e7cee340 100644
--- a/dom/base/StructuredCloneHolder.cpp
+++ b/dom/base/StructuredCloneHolder.cpp
@@ -1075,9 +1075,9 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
return ReadFormData(aCx, aReader, aIndex, this);
}
- if (aTag == SCTAG_DOM_IMAGEBITMAP) {
- MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
- mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
+ if (aTag == SCTAG_DOM_IMAGEBITMAP &&
+ (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
+ mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) {
// Get the current global object.
// This can be null.
@@ -1087,7 +1087,9 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
parent, GetSurfaces(), aIndex);
}
- if (aTag == SCTAG_DOM_WASM) {
+ if (aTag == SCTAG_DOM_WASM &&
+ (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
+ mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) {
return ReadWasmModule(aCx, aIndex, this);
}
@@ -1202,9 +1204,9 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
return true;
}
- if (aTag == SCTAG_DOM_CANVAS) {
- MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
- mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
+ if (aTag == SCTAG_DOM_CANVAS &&
+ (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
+ mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) {
MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent);
@@ -1222,9 +1224,9 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
return true;
}
- if (aTag == SCTAG_DOM_IMAGEBITMAP) {
- MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
- mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
+ if (aTag == SCTAG_DOM_IMAGEBITMAP &&
+ (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
+ mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) {
MOZ_ASSERT(aContent);
ImageBitmapCloneData* data =
static_cast<ImageBitmapCloneData*>(aContent);
@@ -1328,9 +1330,9 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
return;
}
- if (aTag == SCTAG_DOM_CANVAS) {
- MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
- mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
+ if (aTag == SCTAG_DOM_CANVAS &&
+ (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
+ mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) {
MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent);
@@ -1338,9 +1340,9 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
return;
}
- if (aTag == SCTAG_DOM_IMAGEBITMAP) {
- MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
- mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
+ if (aTag == SCTAG_DOM_IMAGEBITMAP &&
+ (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
+ mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread)) {
MOZ_ASSERT(aContent);
ImageBitmapCloneData* data =
static_cast<ImageBitmapCloneData*>(aContent);
diff --git a/dom/base/Timeout.h b/dom/base/Timeout.h
index e929f3dd1..42e2f57f5 100644
--- a/dom/base/Timeout.h
+++ b/dom/base/Timeout.h
@@ -41,7 +41,11 @@ public:
// default main thread being used.
nsresult InitTimer(nsIEventTarget* aTarget, uint32_t aDelay);
- enum class Reason { eTimeoutOrInterval, eIdleCallbackTimeout };
+ enum class Reason
+ {
+ eTimeoutOrInterval,
+ eIdleCallbackTimeout,
+ };
#ifdef DEBUG
bool HasRefCntOne() const;
@@ -62,6 +66,8 @@ public:
// True if this is a repeating/interval timer
bool mIsInterval;
+ // Used to allow several reasons for setting a timeout, where each
+ // 'Reason' value is using a possibly overlapping set of id:s.
Reason mReason;
// Returned as value of setTimeout()
diff --git a/dom/base/TimeoutHandler.cpp b/dom/base/TimeoutHandler.cpp
new file mode 100644
index 000000000..78c3f16dd
--- /dev/null
+++ b/dom/base/TimeoutHandler.cpp
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "TimeoutHandler.h"
+
+namespace mozilla {
+namespace dom {
+
+TimeoutHandler::TimeoutHandler(JSContext* aCx)
+ : TimeoutHandler()
+{
+ nsJSUtils::GetCallingLocation(aCx, mFileName, &mLineNo, &mColumn);
+}
+
+nsresult
+TimeoutHandler::Call()
+{
+ return NS_OK;
+}
+
+void
+TimeoutHandler::GetLocation(const char** aFileName, uint32_t* aLineNo,
+ uint32_t* aColumn)
+{
+ *aFileName = mFileName.get();
+ *aLineNo = mLineNo;
+ *aColumn = mColumn;
+}
+
+NS_IMPL_CYCLE_COLLECTION_0(TimeoutHandler)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeoutHandler)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeoutHandler)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeoutHandler)
+ NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler)
+NS_INTERFACE_MAP_END
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/base/TimeoutHandler.h b/dom/base/TimeoutHandler.h
new file mode 100644
index 000000000..cb0a0ce94
--- /dev/null
+++ b/dom/base/TimeoutHandler.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_timeout_handler_h
+#define mozilla_dom_timeout_handler_h
+
+#include "nsCOMPtr.h"
+#include "nsISupports.h"
+#include "nsITimeoutHandler.h"
+
+namespace mozilla {
+namespace dom {
+
+/**
+ * Utility class for implementing nsITimeoutHandlers, designed to be subclassed.
+ */
+class TimeoutHandler : public nsITimeoutHandler
+{
+public:
+ // TimeoutHandler doesn't actually contain cycles, but subclasses
+ // probably will.
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(TimeoutHandler)
+
+ virtual nsresult Call() override;
+ virtual void GetLocation(const char** aFileName, uint32_t* aLineNo,
+ uint32_t* aColumn) override;
+ virtual void MarkForCC() override {}
+protected:
+ TimeoutHandler() : mFileName(""), mLineNo(0), mColumn(0) {}
+ explicit TimeoutHandler(JSContext *aCx);
+
+ virtual ~TimeoutHandler() {}
+private:
+ TimeoutHandler(const TimeoutHandler&) = delete;
+ TimeoutHandler& operator=(const TimeoutHandler&) = delete;
+ TimeoutHandler& operator=(const TimeoutHandler&&) = delete;
+
+ nsCString mFileName;
+ uint32_t mLineNo;
+ uint32_t mColumn;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_timeout_handler_h
diff --git a/dom/base/WebSocket.cpp b/dom/base/WebSocket.cpp
index d85bae82b..af4b7858b 100644
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -340,7 +340,7 @@ WebSocketImpl::PrintErrorOnConsole(const char *aBundleURI,
new PrintErrorOnConsoleRunnable(this, aBundleURI, aError, aFormatStrings,
aFormatStringsLen);
ErrorResult rv;
- runnable->Dispatch(rv);
+ runnable->Dispatch(Killing, rv);
// XXXbz this seems totally broken. We should be propagating this out, but
// none of our callers really propagate anything usefully. Come to think of
// it, why is this a syncrunnable anyway? Can't this be a fire-and-forget
@@ -629,7 +629,7 @@ WebSocketImpl::Disconnect()
RefPtr<DisconnectInternalRunnable> runnable =
new DisconnectInternalRunnable(this);
ErrorResult rv;
- runnable->Dispatch(rv);
+ runnable->Dispatch(Killing, rv);
// XXXbz this seems totally broken. We should be propagating this out, but
// where to, exactly?
rv.SuppressException();
@@ -1293,7 +1293,7 @@ WebSocket::ConstructorCommon(const GlobalObject& aGlobal,
new InitRunnable(webSocketImpl, !!aTransportProvider, aUrl,
protocolArray, nsDependentCString(file.get()), lineno,
column, aRv, &connectionFailed);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
@@ -1377,7 +1377,7 @@ WebSocket::ConstructorCommon(const GlobalObject& aGlobal,
"not yet implemented");
RefPtr<AsyncOpenRunnable> runnable =
new AsyncOpenRunnable(webSocket->mImpl, aRv);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
diff --git a/dom/base/moz.build b/dom/base/moz.build
index 0fb345d22..77eb01ba6 100755
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -217,6 +217,7 @@ EXPORTS.mozilla.dom += [
'TabGroup.h',
'Text.h',
'Timeout.h',
+ 'TimeoutHandler.h',
'TreeWalker.h',
'WebKitCSSMatrix.h',
'WebSocket.h',
@@ -364,6 +365,7 @@ UNIFIED_SOURCES += [
'TextInputProcessor.cpp',
'ThirdPartyUtil.cpp',
'Timeout.cpp',
+ 'TimeoutHandler.cpp',
'TimerClamping.cpp',
'TreeWalker.cpp',
'WebKitCSSMatrix.cpp',
@@ -460,11 +462,6 @@ LOCAL_INCLUDES += [
'/xpcom/ds',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- LOCAL_INCLUDES += [
- '../system/gonk',
- ]
-
if CONFIG['MOZ_WEBRTC']:
LOCAL_INCLUDES += [
'/netwerk/sctp/datachannel',
diff --git a/dom/base/nsContentPermissionHelper.cpp b/dom/base/nsContentPermissionHelper.cpp
index fd04b1013..c57fc6233 100644
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -5,9 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <map>
-#ifdef MOZ_WIDGET_GONK
-#include "GonkPermission.h"
-#endif // MOZ_WIDGET_GONK
#include "nsCOMPtr.h"
#include "nsIDOMElement.h"
#include "nsIPrincipal.h"
diff --git a/dom/base/nsContentPolicy.cpp b/dom/base/nsContentPolicy.cpp
index 337debcea..5511b9086 100644
--- a/dom/base/nsContentPolicy.cpp
+++ b/dom/base/nsContentPolicy.cpp
@@ -20,6 +20,7 @@
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsIDOMWindow.h"
+#include "nsITabChild.h"
#include "nsIContent.h"
#include "nsILoadContext.h"
#include "nsCOMArray.h"
@@ -89,8 +90,9 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
{
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(requestingContext));
nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext));
- NS_ASSERTION(!requestingContext || node || window,
- "Context should be a DOM node or a DOM window!");
+ nsCOMPtr<nsITabChild> tabChild(do_QueryInterface(requestingContext));
+ NS_ASSERTION(!requestingContext || node || window || tabChild,
+ "Context should be a DOM node, DOM window or a tabChild!");
}
#endif
diff --git a/dom/base/nsContentPolicyUtils.h b/dom/base/nsContentPolicyUtils.h
index ed0544226..600b24c56 100644
--- a/dom/base/nsContentPolicyUtils.h
+++ b/dom/base/nsContentPolicyUtils.h
@@ -134,6 +134,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
CASE_RETURN( TYPE_INTERNAL_IMAGE_FAVICON );
CASE_RETURN( TYPE_INTERNAL_STYLESHEET );
CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD );
+ CASE_RETURN( TYPE_SAVEAS_DOWNLOAD );
default:
return "<Unknown Type>";
}
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index ef87a250e..34c7d23b8 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -281,6 +281,7 @@ bool nsContentUtils::sIsCutCopyAllowed = true;
bool nsContentUtils::sIsFrameTimingPrefEnabled = false;
bool nsContentUtils::sIsPerformanceTimingEnabled = false;
bool nsContentUtils::sIsResourceTimingEnabled = false;
+bool nsContentUtils::sIsPerformanceNavigationTimingEnabled = false;
bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
bool nsContentUtils::sEncodeDecodeURLHash = false;
@@ -571,6 +572,9 @@ nsContentUtils::Init()
Preferences::AddBoolVarCache(&sIsResourceTimingEnabled,
"dom.enable_resource_timing", true);
+ Preferences::AddBoolVarCache(&sIsPerformanceNavigationTimingEnabled,
+ "dom.enable_performance_navigation_timing", true);
+
Preferences::AddBoolVarCache(&sIsUserTimingLoggingEnabled,
"dom.performance.enable_user_timing_logging", false);
@@ -5100,7 +5104,7 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
handler->OnLinkClick(aContent, aLinkURI,
fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
- fileName, nullptr, nullptr, aIsTrusted);
+ fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
}
}
@@ -9772,9 +9776,13 @@ nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
rv = aChannel->GetReferrer(getter_AddRefs(referrer));
NS_ENSURE_SUCCESS(rv, false);
+ nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
+ nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal();
+
// Actually perform the cross process load
bool reloadSucceeded = false;
- rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer, &reloadSucceeded);
+ rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer,
+ triggeringPrincipal, &reloadSucceeded);
NS_ENSURE_SUCCESS(rv, false);
return reloadSucceeded;
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 0932f451e..9ae6d2155 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2033,6 +2033,14 @@ public:
}
/*
+ * Returns true if the performance timing APIs are enabled.
+ */
+ static bool IsPerformanceNavigationTimingEnabled()
+ {
+ return sIsPerformanceNavigationTimingEnabled;
+ }
+
+ /*
* Returns true if notification should be sent for peformance timing events.
*/
static bool SendPerformanceTimingNotifications()
@@ -2825,6 +2833,7 @@ private:
static uint32_t sHandlingInputTimeout;
static bool sIsPerformanceTimingEnabled;
static bool sIsResourceTimingEnabled;
+ static bool sIsPerformanceNavigationTimingEnabled;
static bool sIsUserTimingLoggingEnabled;
static bool sIsFrameTimingPrefEnabled;
static bool sIsExperimentalAutocompleteEnabled;
diff --git a/dom/base/nsDOMNavigationTiming.cpp b/dom/base/nsDOMNavigationTiming.cpp
index 31b2932fb..32ce8a8cb 100644
--- a/dom/base/nsDOMNavigationTiming.cpp
+++ b/dom/base/nsDOMNavigationTiming.cpp
@@ -15,6 +15,9 @@
#include "nsPrintfCString.h"
#include "mozilla/dom/PerformanceNavigation.h"
#include "mozilla/TimeStamp.h"
+#include "mozilla/Telemetry.h"
+
+using namespace mozilla;
nsDOMNavigationTiming::nsDOMNavigationTiming()
{
@@ -30,47 +33,36 @@ nsDOMNavigationTiming::Clear()
{
mNavigationType = TYPE_RESERVED;
mNavigationStartHighRes = 0;
- mBeforeUnloadStart = 0;
- mUnloadStart = 0;
- mUnloadEnd = 0;
- mLoadEventStart = 0;
- mLoadEventEnd = 0;
- mDOMLoading = 0;
- mDOMInteractive = 0;
- mDOMContentLoadedEventStart = 0;
- mDOMContentLoadedEventEnd = 0;
- mDOMComplete = 0;
-
- mLoadEventStartSet = false;
- mLoadEventEndSet = false;
- mDOMLoadingSet = false;
- mDOMInteractiveSet = false;
- mDOMContentLoadedEventStartSet = false;
- mDOMContentLoadedEventEndSet = false;
- mDOMCompleteSet = false;
+ mBeforeUnloadStart = TimeStamp();
+ mUnloadStart = TimeStamp();
+ mUnloadEnd = TimeStamp();
+ mLoadEventStart = TimeStamp();
+ mLoadEventEnd = TimeStamp();
+ mDOMLoading = TimeStamp();
+ mDOMInteractive = TimeStamp();
+ mDOMContentLoadedEventStart = TimeStamp();
+ mDOMContentLoadedEventEnd = TimeStamp();
+ mDOMComplete = TimeStamp();
+
mDocShellHasBeenActiveSinceNavigationStart = false;
}
DOMTimeMilliSec
-nsDOMNavigationTiming::TimeStampToDOM(mozilla::TimeStamp aStamp) const
+nsDOMNavigationTiming::TimeStampToDOM(TimeStamp aStamp) const
{
if (aStamp.IsNull()) {
return 0;
}
- mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
- return GetNavigationStart() + static_cast<int64_t>(duration.ToMilliseconds());
-}
-DOMTimeMilliSec nsDOMNavigationTiming::DurationFromStart()
-{
- return TimeStampToDOM(mozilla::TimeStamp::Now());
+ TimeDuration duration = aStamp - mNavigationStart;
+ return GetNavigationStart() + static_cast<int64_t>(duration.ToMilliseconds());
}
void
nsDOMNavigationTiming::NotifyNavigationStart(DocShellState aDocShellState)
{
mNavigationStartHighRes = (double)PR_Now() / PR_USEC_PER_MSEC;
- mNavigationStartTimeStamp = mozilla::TimeStamp::Now();
+ mNavigationStart = TimeStamp::Now();
mDocShellHasBeenActiveSinceNavigationStart = (aDocShellState == DocShellState::eActive);
}
@@ -86,7 +78,7 @@ nsDOMNavigationTiming::NotifyFetchStart(nsIURI* aURI, Type aNavigationType)
void
nsDOMNavigationTiming::NotifyBeforeUnload()
{
- mBeforeUnloadStart = DurationFromStart();
+ mBeforeUnloadStart = TimeStamp::Now();
}
void
@@ -99,105 +91,107 @@ nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI* aOldURI)
void
nsDOMNavigationTiming::NotifyUnloadEventStart()
{
- mUnloadStart = DurationFromStart();
+ mUnloadStart = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyUnloadEventEnd()
{
- mUnloadEnd = DurationFromStart();
+ mUnloadEnd = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyLoadEventStart()
{
- if (!mLoadEventStartSet) {
- mLoadEventStart = DurationFromStart();
- mLoadEventStartSet = true;
+ if (!mLoadEventStart.IsNull()) {
+ return;
}
+ mLoadEventStart = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyLoadEventEnd()
{
- if (!mLoadEventEndSet) {
- mLoadEventEnd = DurationFromStart();
- mLoadEventEndSet = true;
+ if (!mLoadEventEnd.IsNull()) {
+ return;
}
+ mLoadEventEnd = TimeStamp::Now();
}
void
-nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue)
+nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, TimeStamp aValue)
{
- if (!mDOMLoadingSet) {
- mLoadedURI = aURI;
- mDOMLoading = TimeStampToDOM(aValue);
- mDOMLoadingSet = true;
+ if (!mDOMLoading.IsNull()) {
+ return;
}
+ mLoadedURI = aURI;
+ mDOMLoading = aValue;
}
void
nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
{
- if (!mDOMLoadingSet) {
- mLoadedURI = aURI;
- mDOMLoading = DurationFromStart();
- mDOMLoadingSet = true;
+ if (!mDOMLoading.IsNull()) {
+ return;
}
+ mLoadedURI = aURI;
+ mDOMLoading = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI)
{
- if (!mDOMInteractiveSet) {
- mLoadedURI = aURI;
- mDOMInteractive = DurationFromStart();
- mDOMInteractiveSet = true;
+ if (!mDOMInteractive.IsNull()) {
+ return;
}
+ mLoadedURI = aURI;
+ mDOMInteractive = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI)
{
- if (!mDOMCompleteSet) {
- mLoadedURI = aURI;
- mDOMComplete = DurationFromStart();
- mDOMCompleteSet = true;
+ if (!mDOMComplete.IsNull()) {
+ return;
}
+ mLoadedURI = aURI;
+ mDOMComplete = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
{
- if (!mDOMContentLoadedEventStartSet) {
- mLoadedURI = aURI;
- mDOMContentLoadedEventStart = DurationFromStart();
- mDOMContentLoadedEventStartSet = true;
+ if (!mDOMContentLoadedEventStart.IsNull()) {
+ return;
}
+
+ mLoadedURI = aURI;
+ mDOMContentLoadedEventStart = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
{
- if (!mDOMContentLoadedEventEndSet) {
- mLoadedURI = aURI;
- mDOMContentLoadedEventEnd = DurationFromStart();
- mDOMContentLoadedEventEndSet = true;
+ if (!mDOMContentLoadedEventEnd.IsNull()) {
+ return;
}
+
+ mLoadedURI = aURI;
+ mDOMContentLoadedEventEnd = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
{
MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!mNavigationStartTimeStamp.IsNull());
+ MOZ_ASSERT(!mNavigationStart.IsNull());
- if (!mNonBlankPaintTimeStamp.IsNull()) {
+ if (!mNonBlankPaint.IsNull()) {
return;
}
- mNonBlankPaintTimeStamp = TimeStamp::Now();
- TimeDuration elapsed = mNonBlankPaintTimeStamp - mNavigationStartTimeStamp;
+ mNonBlankPaint = TimeStamp::Now();
+ TimeDuration elapsed = mNonBlankPaint - mNavigationStart;
if (profiler_is_active()) {
nsAutoCString spec;
@@ -212,8 +206,8 @@ nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
if (mDocShellHasBeenActiveSinceNavigationStart) {
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS,
- mNavigationStartTimeStamp,
- mNonBlankPaintTimeStamp);
+ mNavigationStart,
+ mNonBlankPaint);
}
}
@@ -224,24 +218,24 @@ nsDOMNavigationTiming::NotifyDocShellStateChanged(DocShellState aDocShellState)
(aDocShellState == DocShellState::eActive);
}
-DOMTimeMilliSec
-nsDOMNavigationTiming::GetUnloadEventStart()
+mozilla::TimeStamp
+nsDOMNavigationTiming::GetUnloadEventStartTimeStamp() const
{
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
if (NS_SUCCEEDED(rv)) {
return mUnloadStart;
}
- return 0;
+ return mozilla::TimeStamp();
}
-DOMTimeMilliSec
-nsDOMNavigationTiming::GetUnloadEventEnd()
+mozilla::TimeStamp
+nsDOMNavigationTiming::GetUnloadEventEndTimeStamp() const
{
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
if (NS_SUCCEEDED(rv)) {
return mUnloadEnd;
}
- return 0;
+ return mozilla::TimeStamp();
}
diff --git a/dom/base/nsDOMNavigationTiming.h b/dom/base/nsDOMNavigationTiming.h
index 9babece96..3be2527ca 100644
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -47,38 +47,91 @@ public:
mozilla::TimeStamp GetNavigationStartTimeStamp() const
{
- return mNavigationStartTimeStamp;
+ return mNavigationStart;
+ }
+
+ DOMTimeMilliSec GetUnloadEventStart()
+ {
+ return TimeStampToDOM(GetUnloadEventStartTimeStamp());
+ }
+
+ DOMTimeMilliSec GetUnloadEventEnd()
+ {
+ return TimeStampToDOM(GetUnloadEventEndTimeStamp());
}
- DOMTimeMilliSec GetUnloadEventStart();
- DOMTimeMilliSec GetUnloadEventEnd();
DOMTimeMilliSec GetDomLoading() const
{
- return mDOMLoading;
+ return TimeStampToDOM(mDOMLoading);
}
DOMTimeMilliSec GetDomInteractive() const
{
- return mDOMInteractive;
+ return TimeStampToDOM(mDOMInteractive);
}
DOMTimeMilliSec GetDomContentLoadedEventStart() const
{
- return mDOMContentLoadedEventStart;
+ return TimeStampToDOM(mDOMContentLoadedEventStart);
}
DOMTimeMilliSec GetDomContentLoadedEventEnd() const
{
- return mDOMContentLoadedEventEnd;
+ return TimeStampToDOM(mDOMContentLoadedEventEnd);
}
DOMTimeMilliSec GetDomComplete() const
{
- return mDOMComplete;
+ return TimeStampToDOM(mDOMComplete);
}
DOMTimeMilliSec GetLoadEventStart() const
{
- return mLoadEventStart;
+ return TimeStampToDOM(mLoadEventStart);
}
DOMTimeMilliSec GetLoadEventEnd() const
{
- return mLoadEventEnd;
+ return TimeStampToDOM(mLoadEventEnd);
+ }
+ DOMTimeMilliSec GetTimeToNonBlankPaint() const
+ {
+ return TimeStampToDOM(mNonBlankPaint);
+ }
+
+ DOMHighResTimeStamp GetUnloadEventStartHighRes()
+ {
+ mozilla::TimeStamp stamp = GetUnloadEventStartTimeStamp();
+ if (stamp.IsNull()) {
+ return 0;
+ }
+ return TimeStampToDOMHighRes(stamp);
+ }
+ DOMHighResTimeStamp GetUnloadEventEndHighRes()
+ {
+ mozilla::TimeStamp stamp = GetUnloadEventEndTimeStamp();
+ if (stamp.IsNull()) {
+ return 0;
+ }
+ return TimeStampToDOMHighRes(stamp);
+ }
+ DOMHighResTimeStamp GetDomInteractiveHighRes() const
+ {
+ return TimeStampToDOMHighRes(mDOMInteractive);
+ }
+ DOMHighResTimeStamp GetDomContentLoadedEventStartHighRes() const
+ {
+ return TimeStampToDOMHighRes(mDOMContentLoadedEventStart);
+ }
+ DOMHighResTimeStamp GetDomContentLoadedEventEndHighRes() const
+ {
+ return TimeStampToDOMHighRes(mDOMContentLoadedEventEnd);
+ }
+ DOMHighResTimeStamp GetDomCompleteHighRes() const
+ {
+ return TimeStampToDOMHighRes(mDOMComplete);
+ }
+ DOMHighResTimeStamp GetLoadEventStartHighRes() const
+ {
+ return TimeStampToDOMHighRes(mLoadEventStart);
+ }
+ DOMHighResTimeStamp GetLoadEventEndHighRes() const
+ {
+ return TimeStampToDOMHighRes(mLoadEventEnd);
}
enum class DocShellState : uint8_t {
@@ -108,9 +161,13 @@ public:
DOMTimeMilliSec TimeStampToDOM(mozilla::TimeStamp aStamp) const;
- inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp)
+ inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp) const
{
- mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
+ MOZ_ASSERT(!aStamp.IsNull(), "The timestamp should not be null");
+ if (aStamp.IsNull()) {
+ return 0;
+ }
+ mozilla::TimeDuration duration = aStamp - mNavigationStart;
return duration.ToMilliseconds();
}
@@ -120,37 +177,29 @@ private:
void Clear();
+ mozilla::TimeStamp GetUnloadEventStartTimeStamp() const;
+ mozilla::TimeStamp GetUnloadEventEndTimeStamp() const;
+
nsCOMPtr<nsIURI> mUnloadedURI;
nsCOMPtr<nsIURI> mLoadedURI;
Type mNavigationType;
DOMHighResTimeStamp mNavigationStartHighRes;
- mozilla::TimeStamp mNavigationStartTimeStamp;
- mozilla::TimeStamp mNonBlankPaintTimeStamp;
- DOMTimeMilliSec DurationFromStart();
-
- DOMTimeMilliSec mBeforeUnloadStart;
- DOMTimeMilliSec mUnloadStart;
- DOMTimeMilliSec mUnloadEnd;
- DOMTimeMilliSec mLoadEventStart;
- DOMTimeMilliSec mLoadEventEnd;
-
- DOMTimeMilliSec mDOMLoading;
- DOMTimeMilliSec mDOMInteractive;
- DOMTimeMilliSec mDOMContentLoadedEventStart;
- DOMTimeMilliSec mDOMContentLoadedEventEnd;
- DOMTimeMilliSec mDOMComplete;
-
- // Booleans to keep track of what things we've already been notified
- // about. We don't update those once we've been notified about them
- // once.
- bool mLoadEventStartSet : 1;
- bool mLoadEventEndSet : 1;
- bool mDOMLoadingSet : 1;
- bool mDOMInteractiveSet : 1;
- bool mDOMContentLoadedEventStartSet : 1;
- bool mDOMContentLoadedEventEndSet : 1;
- bool mDOMCompleteSet : 1;
+ mozilla::TimeStamp mNavigationStart;
+ mozilla::TimeStamp mNonBlankPaint;
+
+ mozilla::TimeStamp mBeforeUnloadStart;
+ mozilla::TimeStamp mUnloadStart;
+ mozilla::TimeStamp mUnloadEnd;
+ mozilla::TimeStamp mLoadEventStart;
+ mozilla::TimeStamp mLoadEventEnd;
+
+ mozilla::TimeStamp mDOMLoading;
+ mozilla::TimeStamp mDOMInteractive;
+ mozilla::TimeStamp mDOMContentLoadedEventStart;
+ mozilla::TimeStamp mDOMContentLoadedEventEnd;
+ mozilla::TimeStamp mDOMComplete;
+
bool mDocShellHasBeenActiveSinceNavigationStart : 1;
};
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index eaea49b02..8acfd901a 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -2054,10 +2054,17 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
mFirstChild = content->GetNextSibling();
}
mChildren.RemoveChildAt(i);
+ if (content == mCachedRootElement) {
+ // Immediately clear mCachedRootElement, now that it's been removed
+ // from mChildren, so that GetRootElement() will stop returning this
+ // now-stale value.
+ mCachedRootElement = nullptr;
+ }
nsNodeUtils::ContentRemoved(this, content, i, previousSibling);
content->UnbindFromTree();
}
- mCachedRootElement = nullptr;
+ MOZ_ASSERT(!mCachedRootElement,
+ "After removing all children, there should be no root elem");
}
mInUnlinkOrDeletion = oldVal;
@@ -3913,8 +3920,18 @@ nsDocument::RemoveChildAt(uint32_t aIndex, bool aNotify)
DestroyElementMaps();
}
- doRemoveChildAt(aIndex, aNotify, oldKid, mChildren);
+ // Preemptively clear mCachedRootElement, since we may be about to remove it
+ // from our child list, and we don't want to return this maybe-obsolete value
+ // from any GetRootElement() calls that happen inside of doRemoveChildAt().
+ // (NOTE: for this to be useful, doRemoveChildAt() must NOT trigger any
+ // GetRootElement() calls until after it's removed the child from mChildren.
+ // Any call before that point would restore this soon-to-be-obsolete cached
+ // answer, and our clearing here would be fruitless.)
mCachedRootElement = nullptr;
+ doRemoveChildAt(aIndex, aNotify, oldKid, mChildren);
+ MOZ_ASSERT(mCachedRootElement != oldKid,
+ "Stale pointer in mCachedRootElement, after we tried to clear it "
+ "(maybe somebody called GetRootElement() too early?)");
}
void
@@ -12490,7 +12507,8 @@ nsDocument::ScheduleIntersectionObserverNotification()
void
nsDocument::NotifyIntersectionObservers()
{
- for (const auto& observer : mIntersectionObservers) {
+ nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers);
+ for (const auto& observer : observers) {
observer->Notify();
}
}
@@ -12846,3 +12864,19 @@ nsDocument::CheckCustomElementName(const ElementCreationOptions& aOptions,
return is;
}
+
+Selection*
+nsIDocument::GetSelection(ErrorResult& aRv)
+{
+ nsCOMPtr<nsPIDOMWindowInner> window = GetInnerWindow();
+ if (!window) {
+ return nullptr;
+ }
+
+ NS_ASSERTION(window->IsInnerWindow(), "Should have inner window here!");
+ if (!window->IsCurrentInnerWindow()) {
+ return nullptr;
+ }
+
+ return nsGlobalWindow::Cast(window)->GetSelection(aRv);
+}
diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp
index 049bc0a1a..6fffd376b 100644
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -271,10 +271,10 @@ BuildClonedMessageData(typename BlobTraits<Flavor>::ConcreteContentManagerType*
ClonedMessageData& aClonedData)
{
SerializedStructuredCloneBuffer& buffer = aClonedData.data();
- auto iter = aData.Data().Iter();
+ auto iter = aData.Data().Start();
size_t size = aData.Data().Size();
bool success;
- buffer.data = aData.Data().Borrow<js::SystemAllocPolicy>(iter, size, &success);
+ buffer.data = aData.Data().Borrow(iter, size, &success);
if (NS_WARN_IF(!success)) {
return false;
}
@@ -1286,6 +1286,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
if (aRetVal) {
ErrorResult rv;
StructuredCloneData* data = aRetVal->AppendElement();
+ data->InitScope(JS::StructuredCloneScope::DifferentProcess);
data->Write(cx, rval, rv);
if (NS_WARN_IF(rv.Failed())) {
aRetVal->RemoveElementAt(aRetVal->Length() - 1);
diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h
index e4ae7ede8..8fefa0e02 100644
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -694,6 +694,7 @@ GK_ATOM(onadapterremoved, "onadapterremoved")
GK_ATOM(onafterprint, "onafterprint")
GK_ATOM(onafterscriptexecute, "onafterscriptexecute")
GK_ATOM(onalerting, "onalerting")
+GK_ATOM(onanimationcancel, "onanimationcancel")
GK_ATOM(onanimationend, "onanimationend")
GK_ATOM(onanimationiteration, "onanimationiteration")
GK_ATOM(onanimationstart, "onanimationstart")
@@ -704,6 +705,7 @@ GK_ATOM(onattributechanged, "onattributechanged")
GK_ATOM(onattributereadreq, "onattributereadreq")
GK_ATOM(onattributewritereq, "onattributewritereq")
GK_ATOM(onaudioprocess, "onaudioprocess")
+GK_ATOM(onauxclick, "onauxclick")
GK_ATOM(onbeforecopy, "onbeforecopy")
GK_ATOM(onbeforecut, "onbeforecut")
GK_ATOM(onbeforepaste, "onbeforepaste")
@@ -941,6 +943,7 @@ GK_ATOM(ontouchstart, "ontouchstart")
GK_ATOM(ontouchend, "ontouchend")
GK_ATOM(ontouchmove, "ontouchmove")
GK_ATOM(ontouchcancel, "ontouchcancel")
+GK_ATOM(ontransitioncancel, "ontransitioncancel")
GK_ATOM(ontransitionend, "ontransitionend")
GK_ATOM(ontransitionrun, "ontransitionrun")
GK_ATOM(ontransitionstart, "ontransitionstart")
@@ -2237,6 +2240,7 @@ GK_ATOM(windows_accent_color_applies, "windows-accent-color-applies")
GK_ATOM(windows_accent_color_is_dark, "windows-accent-color-is-dark")
GK_ATOM(windows_default_theme, "windows-default-theme")
GK_ATOM(mac_graphite_theme, "mac-graphite-theme")
+GK_ATOM(mac_lion_theme, "mac-lion-theme")
GK_ATOM(mac_yosemite_theme, "mac-yosemite-theme")
GK_ATOM(windows_compositor, "windows-compositor")
GK_ATOM(windows_glass, "windows-glass")
@@ -2268,6 +2272,7 @@ GK_ATOM(_moz_windows_accent_color_applies, "-moz-windows-accent-color-applies")
GK_ATOM(_moz_windows_accent_color_is_dark, "-moz-windows-accent-color-is-dark")
GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme")
GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme")
+GK_ATOM(_moz_mac_lion_theme, "-moz-mac-lion-theme")
GK_ATOM(_moz_mac_yosemite_theme, "-moz-mac-yosemite-theme")
GK_ATOM(_moz_windows_compositor, "-moz-windows-compositor")
GK_ATOM(_moz_windows_classic, "-moz-windows-classic")
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index f784031f6..884ad69ca 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -23,8 +23,9 @@
#include "mozilla/dom/StorageEvent.h"
#include "mozilla/dom/StorageEventBinding.h"
#include "mozilla/dom/Timeout.h"
+#include "mozilla/dom/TimeoutHandler.h"
#include "mozilla/IntegerPrintfMacros.h"
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
#include "mozilla/dom/WindowOrientationObserver.h"
#endif
#include "nsDOMOfflineResourceList.h"
@@ -248,10 +249,6 @@
#include "mozilla/dom/SpeechSynthesis.h"
#endif
-#ifdef MOZ_B2G
-#include "nsPISocketTransportService.h"
-#endif
-
// Apple system headers seem to have a check() macro. <sigh>
#ifdef check
class nsIScriptTimeoutHandler;
@@ -552,29 +549,284 @@ DialogValueHolder::Get(JSContext* aCx, JS::Handle<JSObject*> aScope,
}
}
+class IdleRequestExecutor final : public nsIRunnable
+ , public nsICancelableRunnable
+ , public nsIIncrementalRunnable
+{
+public:
+ explicit IdleRequestExecutor(nsGlobalWindow* aWindow)
+ : mDispatched(false)
+ , mDeadline(TimeStamp::Now())
+ , mWindow(aWindow)
+ {
+ MOZ_DIAGNOSTIC_ASSERT(mWindow);
+ MOZ_DIAGNOSTIC_ASSERT(mWindow->IsInnerWindow());
+ }
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable)
+
+ NS_DECL_NSIRUNNABLE
+ nsresult Cancel() override;
+ void SetDeadline(TimeStamp aDeadline) override;
+
+ void MaybeDispatch();
+private:
+ ~IdleRequestExecutor() {}
+
+ bool mDispatched;
+ TimeStamp mDeadline;
+ RefPtr<nsGlobalWindow> mWindow;
+};
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequestExecutor)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutor)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutor)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequestExecutor)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequestExecutor)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor)
+ NS_INTERFACE_MAP_ENTRY(nsIRunnable)
+ NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)
+ NS_INTERFACE_MAP_ENTRY(nsIIncrementalRunnable)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable)
+NS_INTERFACE_MAP_END
+
+NS_IMETHODIMP
+IdleRequestExecutor::Run()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ mDispatched = false;
+ if (mWindow) {
+ return mWindow->ExecuteIdleRequest(mDeadline);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+IdleRequestExecutor::Cancel()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ mWindow = nullptr;
+ return NS_OK;
+}
+
void
-nsGlobalWindow::PostThrottledIdleCallback()
+IdleRequestExecutor::SetDeadline(TimeStamp aDeadline)
{
- AssertIsOnMainThread();
+ MOZ_ASSERT(NS_IsMainThread());
+
+ if (!mWindow) {
+ return;
+ }
- if (mThrottledIdleRequestCallbacks.isEmpty())
+ mDeadline = aDeadline;
+}
+
+void
+IdleRequestExecutor::MaybeDispatch()
+{
+ // If we've already dispatched the executor we don't want to do it
+ // again. Also, if we've called IdleRequestExecutor::Cancel mWindow
+ // will be null, which indicates that we shouldn't dispatch this
+ // executor either.
+ if (mDispatched || !mWindow) {
return;
+ }
- RefPtr<IdleRequest> request(mThrottledIdleRequestCallbacks.popFirst());
- // ownership transferred from mThrottledIdleRequestCallbacks to
- // mIdleRequestCallbacks
- mIdleRequestCallbacks.insertBack(request);
+ mDispatched = true;
+ RefPtr<IdleRequestExecutor> request = this;
NS_IdleDispatchToCurrentThread(request.forget());
}
-/* static */ void
-nsGlobalWindow::InsertIdleCallbackIntoList(IdleRequest* aRequest,
- IdleRequests& aList)
+class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler
{
- aList.insertBack(aRequest);
+public:
+ explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor)
+ : mExecutor(aExecutor)
+ {
+ }
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestExecutorTimeoutHandler,
+ TimeoutHandler)
+
+ nsresult Call() override
+ {
+ mExecutor->MaybeDispatch();
+ return NS_OK;
+ }
+private:
+ ~IdleRequestExecutorTimeoutHandler() {}
+ RefPtr<IdleRequestExecutor> mExecutor;
+};
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler, mExecutor)
+
+NS_IMPL_ADDREF_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler)
+NS_IMPL_RELEASE_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler)
+ NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler)
+NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
+
+void
+nsGlobalWindow::ScheduleIdleRequestDispatch()
+{
+ AssertIsOnMainThread();
+
+ if (mIdleRequestCallbacks.isEmpty()) {
+ if (mIdleRequestExecutor) {
+ mIdleRequestExecutor->Cancel();
+ mIdleRequestExecutor = nullptr;
+ }
+
+ return;
+ }
+
+ if (!mIdleRequestExecutor) {
+ mIdleRequestExecutor = new IdleRequestExecutor(this);
+ }
+
+ nsPIDOMWindowOuter* outer = GetOuterWindow();
+ if (outer && outer->AsOuter()->IsBackground()) {
+ nsCOMPtr<nsITimeoutHandler> handler = new IdleRequestExecutorTimeoutHandler(mIdleRequestExecutor);
+ int32_t dummy;
+ // Set a timeout handler with a timeout of 0 ms to throttle idle
+ // callback requests coming from a backround window using
+ // background timeout throttling.
+ SetTimeoutOrInterval(handler, 0, false,
+ Timeout::Reason::eIdleCallbackTimeout, &dummy);
+ return;
+ }
+
+ mIdleRequestExecutor->MaybeDispatch();
+}
+
+void
+nsGlobalWindow::SuspendIdleRequests()
+{
+ if (mIdleRequestExecutor) {
+ mIdleRequestExecutor->Cancel();
+ mIdleRequestExecutor = nullptr;
+ }
+}
+
+void
+nsGlobalWindow::ResumeIdleRequests()
+{
+ MOZ_ASSERT(!mIdleRequestExecutor);
+
+ ScheduleIdleRequestDispatch();
+}
+
+void
+nsGlobalWindow::InsertIdleCallback(IdleRequest* aRequest)
+{
+ AssertIsOnMainThread();
+ mIdleRequestCallbacks.insertBack(aRequest);
aRequest->AddRef();
}
+void
+nsGlobalWindow::RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest)
+{
+ AssertIsOnMainThread();
+
+ if (aRequest->HasTimeout()) {
+ ClearTimeoutOrInterval(aRequest->GetTimeoutHandle(),
+ Timeout::Reason::eIdleCallbackTimeout);
+ }
+
+ aRequest->removeFrom(mIdleRequestCallbacks);
+ aRequest->Release();
+}
+
+nsresult
+nsGlobalWindow::RunIdleRequest(IdleRequest* aRequest,
+ DOMHighResTimeStamp aDeadline,
+ bool aDidTimeout)
+{
+ AssertIsOnMainThread();
+ RefPtr<IdleRequest> request(aRequest);
+ RemoveIdleCallback(request);
+ return request->IdleRun(AsInner(), aDeadline, aDidTimeout);
+}
+
+nsresult
+nsGlobalWindow::ExecuteIdleRequest(TimeStamp aDeadline)
+{
+ AssertIsOnMainThread();
+ RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
+
+ if (!request) {
+ // There are no more idle requests, so stop scheduling idle
+ // request callbacks.
+ return NS_OK;
+ }
+
+ DOMHighResTimeStamp deadline = 0.0;
+
+ if (Performance* perf = GetPerformance()) {
+ deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline);
+ }
+
+ nsresult result = RunIdleRequest(request, deadline, false);
+
+ ScheduleIdleRequestDispatch();
+ return result;
+}
+
+class IdleRequestTimeoutHandler final : public TimeoutHandler
+{
+public:
+ IdleRequestTimeoutHandler(JSContext* aCx,
+ IdleRequest* aIdleRequest,
+ nsPIDOMWindowInner* aWindow)
+ : TimeoutHandler(aCx)
+ , mIdleRequest(aIdleRequest)
+ , mWindow(aWindow)
+ {
+ }
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestTimeoutHandler,
+ TimeoutHandler)
+
+ nsresult Call() override
+ {
+ return nsGlobalWindow::Cast(mWindow)->RunIdleRequest(mIdleRequest, 0.0, true);
+ }
+
+private:
+ ~IdleRequestTimeoutHandler() {}
+
+ RefPtr<IdleRequest> mIdleRequest;
+ nsCOMPtr<nsPIDOMWindowInner> mWindow;
+};
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestTimeoutHandler,
+ TimeoutHandler,
+ mIdleRequest,
+ mWindow)
+
+NS_IMPL_ADDREF_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler)
+NS_IMPL_RELEASE_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestTimeoutHandler)
+ NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler)
+NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
+
uint32_t
nsGlobalWindow::RequestIdleCallback(JSContext* aCx,
IdleRequestCallback& aCallback,
@@ -584,33 +836,36 @@ nsGlobalWindow::RequestIdleCallback(JSContext* aCx,
MOZ_RELEASE_ASSERT(IsInnerWindow());
AssertIsOnMainThread();
- uint32_t handle = ++mIdleRequestCallbackCounter;
+ uint32_t handle = mIdleRequestCallbackCounter++;
RefPtr<IdleRequest> request =
- new IdleRequest(aCx, AsInner(), aCallback, handle);
+ new IdleRequest(&aCallback, handle);
if (aOptions.mTimeout.WasPassed()) {
- aError = request->SetTimeout(aOptions.mTimeout.Value());
- if (NS_WARN_IF(aError.Failed())) {
+ int32_t timeoutHandle;
+ nsCOMPtr<nsITimeoutHandler> handler(new IdleRequestTimeoutHandler(aCx, request, AsInner()));
+
+ nsresult rv = SetTimeoutOrInterval(
+ handler, aOptions.mTimeout.Value(), false,
+ Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle);
+
+ if (NS_WARN_IF(NS_FAILED(rv))) {
return 0;
}
- }
- nsGlobalWindow* outer = GetOuterWindowInternal();
- if (outer && outer->AsOuter()->IsBackground()) {
- // mThrottledIdleRequestCallbacks now owns request
- InsertIdleCallbackIntoList(request, mThrottledIdleRequestCallbacks);
-
- NS_DelayedDispatchToCurrentThread(
- NewRunnableMethod(this, &nsGlobalWindow::PostThrottledIdleCallback),
- 10000);
- } else {
- MOZ_ASSERT(mThrottledIdleRequestCallbacks.isEmpty());
+ request->SetTimeoutHandle(timeoutHandle);
+ }
- // mIdleRequestCallbacks now owns request
- InsertIdleCallbackIntoList(request, mIdleRequestCallbacks);
+ // If the list of idle callback requests is not empty it means that
+ // we've already dispatched the first idle request. If we're
+ // suspended we should only queue the idle callback and not schedule
+ // it to run, that will be done in ResumeIdleRequest.
+ bool needsScheduling = !IsSuspended() && mIdleRequestCallbacks.isEmpty();
+ // mIdleRequestCallbacks now owns request
+ InsertIdleCallback(request);
- NS_IdleDispatchToCurrentThread(request.forget());
+ if (needsScheduling) {
+ ScheduleIdleRequestDispatch();
}
return handle;
@@ -623,7 +878,7 @@ nsGlobalWindow::CancelIdleCallback(uint32_t aHandle)
for (IdleRequest* r : mIdleRequestCallbacks) {
if (r->Handle() == aHandle) {
- r->Cancel();
+ RemoveIdleCallback(r);
break;
}
}
@@ -632,29 +887,17 @@ nsGlobalWindow::CancelIdleCallback(uint32_t aHandle)
void
nsGlobalWindow::DisableIdleCallbackRequests()
{
- while (!mIdleRequestCallbacks.isEmpty()) {
- RefPtr<IdleRequest> request = mIdleRequestCallbacks.popFirst();
- request->Cancel();
+ if (mIdleRequestExecutor) {
+ mIdleRequestExecutor->Cancel();
+ mIdleRequestExecutor = nullptr;
}
- while (!mThrottledIdleRequestCallbacks.isEmpty()) {
- RefPtr<IdleRequest> request = mThrottledIdleRequestCallbacks.popFirst();
- request->Cancel();
- }
-}
-
-void nsGlobalWindow::UnthrottleIdleCallbackRequests()
-{
- AssertIsOnMainThread();
-
- while (!mThrottledIdleRequestCallbacks.isEmpty()) {
- RefPtr<IdleRequest> request(mThrottledIdleRequestCallbacks.popFirst());
- mIdleRequestCallbacks.insertBack(request);
- NS_IdleDispatchToCurrentThread(request.forget());
+ while (!mIdleRequestCallbacks.isEmpty()) {
+ RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
+ RemoveIdleCallback(request);
}
}
-
namespace mozilla {
namespace dom {
extern uint64_t
@@ -1306,13 +1549,10 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mSerial(0),
mIdleCallbackTimeoutCounter(1),
mIdleRequestCallbackCounter(1),
+ mIdleRequestExecutor(nullptr),
#ifdef DEBUG
mSetOpenerWindowCalled(false),
#endif
-#ifdef MOZ_B2G
- mNetworkUploadObserverEnabled(false),
- mNetworkDownloadObserverEnabled(false),
-#endif
mCleanedUp(false),
mDialogAbuseCount(0),
mAreDialogsEnabled(true),
@@ -1665,11 +1905,6 @@ nsGlobalWindow::CleanUp()
os->RemoveObserver(mObserver, "dom-storage2-changed");
}
-#ifdef MOZ_B2G
- DisableNetworkEvent(eNetworkUpload);
- DisableNetworkEvent(eNetworkDownload);
-#endif // MOZ_B2G
-
if (mIdleService) {
mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
}
@@ -1713,7 +1948,7 @@ nsGlobalWindow::CleanUp()
mSpeechSynthesis = nullptr;
#endif
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
mOrientationChangeObserver = nullptr;
#endif
@@ -1738,9 +1973,6 @@ nsGlobalWindow::CleanUp()
mHasGamepad = false;
DisableVRUpdates();
mHasVREvents = false;
-#ifdef MOZ_B2G
- DisableTimeChangeNotifications();
-#endif
DisableIdleCallbackRequests();
} else {
MOZ_ASSERT(!mHasGamepad);
@@ -1844,7 +2076,7 @@ nsGlobalWindow::FreeInnerObjects()
mScreen = nullptr;
}
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
mOrientationChangeObserver = nullptr;
#endif
@@ -2033,14 +2265,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWakeLock)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)
for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));
}
- for (IdleRequest* request : tmp->mThrottledIdleRequestCallbacks) {
- cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));
- }
-
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
#ifdef MOZ_GAMEPAD
@@ -2147,6 +2376,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
tmp->UnlinkHostObjectURIs();
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
tmp->DisableIdleCallbackRequests();
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@@ -2275,8 +2505,13 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument)
return false;
}
- NS_ASSERTION(NS_IsAboutBlank(mDoc->GetDocumentURI()),
- "How'd this happen?");
+#ifdef DEBUG
+{
+ nsCOMPtr<nsIURI> uri;
+ mDoc->GetDocumentURI()->CloneIgnoringRef(getter_AddRefs(uri));
+ NS_ASSERTION(NS_IsAboutBlank(uri), "How'd this happen?");
+}
+#endif
// Great, we're the original document, check for one of the other
// conditions.
@@ -2878,8 +3113,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
newInnerWindow->mPerformance =
Performance::CreateForMainThread(newInnerWindow->AsInner(),
currentInner->mPerformance->GetDOMTiming(),
- currentInner->mPerformance->GetChannel(),
- currentInner->mPerformance->GetParentPerformance());
+ currentInner->mPerformance->GetChannel());
}
}
@@ -4093,22 +4327,7 @@ nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
timedChannel = nullptr;
}
if (timing) {
- // If we are dealing with an iframe, we will need the parent's performance
- // object (so we can add the iframe as a resource of that page).
- Performance* parentPerformance = nullptr;
- nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
- if (parentWindow) {
- nsPIDOMWindowInner* parentInnerWindow = nullptr;
- if (parentWindow) {
- parentInnerWindow = parentWindow->GetCurrentInnerWindow();
- }
- if (parentInnerWindow) {
- parentPerformance = parentInnerWindow->GetPerformance();
- }
- }
- mPerformance =
- Performance::CreateForMainThread(this, timing, timedChannel,
- parentPerformance);
+ mPerformance = Performance::CreateForMainThread(this, timing, timedChannel);
}
}
@@ -10237,12 +10456,6 @@ void nsGlobalWindow::SetIsBackground(bool aIsBackground)
ResetTimersForThrottleReduction(gMinBackgroundTimeoutValue);
}
- if (!aIsBackground) {
- nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
- if (inner) {
- inner->UnthrottleIdleCallbackRequests();
- }
- }
#ifdef MOZ_GAMEPAD
if (!aIsBackground) {
nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
@@ -11904,27 +12117,6 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
-#ifdef MOZ_B2G
- if (!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) ||
- !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC)) {
- MOZ_ASSERT(IsInnerWindow());
- if (!AsInner()->IsCurrentInnerWindow()) {
- return NS_OK;
- }
-
- RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
- event->InitEvent(
- !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC)
- ? NETWORK_UPLOAD_EVENT_NAME
- : NETWORK_DOWNLOAD_EVENT_NAME,
- false, false);
- event->SetTrusted(true);
-
- bool dummy;
- return DispatchEvent(event, &dummy);
- }
-#endif // MOZ_B2G
-
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages"));
MOZ_ASSERT(IsInnerWindow());
@@ -12036,6 +12228,8 @@ nsGlobalWindow::Suspend()
mozilla::dom::workers::SuspendWorkersForWindow(AsInner());
+ SuspendIdleRequests();
+
for (Timeout* t = mTimeouts.getFirst(); t; t = t->getNext()) {
// Leave the timers with the current time remaining. This will
// cause the timers to potentially fire when the window is
@@ -12146,6 +12340,8 @@ nsGlobalWindow::Resume()
t->AddRef();
}
+ ResumeIdleRequests();
+
// Resume all of the workers for this window. We must do this
// after timeouts since workers may have queued events that can trigger
// a setTimeout().
@@ -13813,7 +14009,7 @@ nsGlobalWindow::DisableDeviceSensor(uint32_t aType)
}
}
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
void
nsGlobalWindow::EnableOrientationChangeListener()
{
@@ -14437,7 +14633,9 @@ nsGlobalWindow::NotifyDefaultButtonLoaded(Element& aDefaultButton,
return;
}
LayoutDeviceIntRect buttonRect =
- LayoutDeviceIntRect::FromUnknownRect(frame->GetScreenRect());
+ LayoutDeviceIntRect::FromAppUnitsToNearest(
+ frame->GetScreenRectInAppUnits(),
+ frame->PresContext()->AppUnitsPerDevPixel());
// Get the widget rect in screen coordinates.
nsIWidget *widget = GetNearestWidget();
@@ -14706,7 +14904,7 @@ nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
}
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
int16_t
nsGlobalWindow::Orientation(CallerType aCallerType) const
{
@@ -14820,80 +15018,6 @@ nsGlobalWindow::GetIsPrerendered()
return docShell && docShell->GetIsPrerendered();
}
-#ifdef MOZ_B2G
-void
-nsGlobalWindow::EnableNetworkEvent(EventMessage aEventMessage)
-{
- MOZ_ASSERT(IsInnerWindow());
-
- nsCOMPtr<nsIPermissionManager> permMgr =
- services::GetPermissionManager();
- if (!permMgr) {
- NS_ERROR("No PermissionManager available!");
- return;
- }
-
- uint32_t permission = nsIPermissionManager::DENY_ACTION;
- permMgr->TestExactPermissionFromPrincipal(GetPrincipal(), "network-events",
- &permission);
-
- if (permission != nsIPermissionManager::ALLOW_ACTION) {
- return;
- }
-
- nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
- if (!os) {
- NS_ERROR("ObserverService should be available!");
- return;
- }
-
- switch (aEventMessage) {
- case eNetworkUpload:
- if (!mNetworkUploadObserverEnabled) {
- mNetworkUploadObserverEnabled = true;
- os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC, false);
- }
- break;
- case eNetworkDownload:
- if (!mNetworkDownloadObserverEnabled) {
- mNetworkDownloadObserverEnabled = true;
- os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC, false);
- }
- break;
- default:
- break;
- }
-}
-
-void
-nsGlobalWindow::DisableNetworkEvent(EventMessage aEventMessage)
-{
- MOZ_ASSERT(IsInnerWindow());
-
- nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
- if (!os) {
- return;
- }
-
- switch (aEventMessage) {
- case eNetworkUpload:
- if (mNetworkUploadObserverEnabled) {
- mNetworkUploadObserverEnabled = false;
- os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC);
- }
- break;
- case eNetworkDownload:
- if (mNetworkDownloadObserverEnabled) {
- mNetworkDownloadObserverEnabled = false;
- os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC);
- }
- break;
- default:
- break;
- }
-}
-#endif // MOZ_B2G
-
void
nsGlobalWindow::RedefineProperty(JSContext* aCx, const char* aPropName,
JS::Handle<JS::Value> aValue,
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index dbceeab74..467bc6796 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -102,6 +102,8 @@ struct nsRect;
class nsWindowSizes;
+class IdleRequestExecutor;
+
namespace mozilla {
class DOMEventTargetHelper;
class ThrottledEventQueue;
@@ -118,6 +120,7 @@ class Gamepad;
enum class ImageBitmapFormat : uint32_t;
class IdleRequest;
class IdleRequestCallback;
+class IncrementalRunnable;
class Location;
class MediaQueryList;
class MozSelfSupport;
@@ -135,7 +138,7 @@ class U2F;
class VRDisplay;
class VREventObserver;
class WakeLock;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
class WindowOrientationObserver;
#endif
class Worklet;
@@ -628,7 +631,7 @@ public:
virtual void EnableDeviceSensor(uint32_t aType) override;
virtual void DisableDeviceSensor(uint32_t aType) override;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
virtual void EnableOrientationChangeListener() override;
virtual void DisableOrientationChangeListener() override;
#endif
@@ -636,13 +639,6 @@ public:
virtual void EnableTimeChangeNotifications() override;
virtual void DisableTimeChangeNotifications() override;
-#ifdef MOZ_B2G
- // Inner windows only.
- virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) override;
- virtual void DisableNetworkEvent(
- mozilla::EventMessage aEventMessage) override;
-#endif // MOZ_B2G
-
virtual nsresult SetArguments(nsIArray* aArguments) override;
void MaybeForgiveSpamCount();
@@ -909,7 +905,7 @@ public:
nsIDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError);
already_AddRefed<nsIDOMOfflineResourceList> GetApplicationCache() override;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
int16_t Orientation(mozilla::dom::CallerType aCallerType) const;
#endif
@@ -1097,7 +1093,6 @@ public:
mozilla::ErrorResult& aError);
void CancelIdleCallback(uint32_t aHandle);
-
#ifdef MOZ_WEBSPEECH
mozilla::dom::SpeechSynthesis*
GetSpeechSynthesis(mozilla::ErrorResult& aError);
@@ -1762,6 +1757,21 @@ private:
mozilla::dom::TabGroup* TabGroupInner();
mozilla::dom::TabGroup* TabGroupOuter();
+public:
+ void DisableIdleCallbackRequests();
+ uint32_t IdleRequestHandle() const { return mIdleRequestCallbackCounter; }
+ nsresult RunIdleRequest(mozilla::dom::IdleRequest* aRequest,
+ DOMHighResTimeStamp aDeadline, bool aDidTimeout);
+ nsresult ExecuteIdleRequest(TimeStamp aDeadline);
+ void ScheduleIdleRequestDispatch();
+ void SuspendIdleRequests();
+ void ResumeIdleRequests();
+
+ typedef mozilla::LinkedList<mozilla::dom::IdleRequest> IdleRequests;
+ void InsertIdleCallback(mozilla::dom::IdleRequest* aRequest);
+
+ void RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest);
+
protected:
// These members are only used on outer window objects. Make sure
// you never set any of these on an inner object!
@@ -1912,32 +1922,18 @@ protected:
uint32_t mSerial;
- void DisableIdleCallbackRequests();
- void UnthrottleIdleCallbackRequests();
-
- void PostThrottledIdleCallback();
-
- typedef mozilla::LinkedList<mozilla::dom::IdleRequest> IdleRequests;
- static void InsertIdleCallbackIntoList(mozilla::dom::IdleRequest* aRequest,
- IdleRequests& aList);
-
// The current idle request callback timeout handle
uint32_t mIdleCallbackTimeoutCounter;
// The current idle request callback handle
uint32_t mIdleRequestCallbackCounter;
IdleRequests mIdleRequestCallbacks;
- IdleRequests mThrottledIdleRequestCallbacks;
+ RefPtr<IdleRequestExecutor> mIdleRequestExecutor;
#ifdef DEBUG
bool mSetOpenerWindowCalled;
nsCOMPtr<nsIURI> mLastOpenedURI;
#endif
-#ifdef MOZ_B2G
- bool mNetworkUploadObserverEnabled;
- bool mNetworkDownloadObserverEnabled;
-#endif // MOZ_B2G
-
bool mCleanedUp;
nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache;
@@ -1975,7 +1971,7 @@ protected:
nsTArray<uint32_t> mEnabledSensors;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
nsAutoPtr<mozilla::dom::WindowOrientationObserver> mOrientationChangeObserver;
#endif
@@ -2002,6 +1998,7 @@ protected:
friend class nsDOMWindowUtils;
friend class mozilla::dom::PostMessageEvent;
friend class DesktopNotification;
+ friend class IdleRequestExecutor;
static WindowByIdTable* sWindowsById;
static bool sWarnedAboutWindowInternal;
diff --git a/dom/base/nsIContentPolicy.idl b/dom/base/nsIContentPolicy.idl
index a73565a9a..200b97fbc 100644
--- a/dom/base/nsIContentPolicy.idl
+++ b/dom/base/nsIContentPolicy.idl
@@ -20,7 +20,7 @@ interface nsIPrincipal;
* by launching a dialog to prompt the user for something).
*/
-[scriptable,uuid(caad4f1f-d047-46ac-ae9d-dc598e4fb91b)]
+[scriptable,uuid(64a5ae16-6836-475c-9938-4b6cc1eee8fb)]
interface nsIContentPolicy : nsIContentPolicyBase
{
/**
diff --git a/dom/base/nsIContentPolicyBase.idl b/dom/base/nsIContentPolicyBase.idl
index 884e3d96d..908e562a8 100644
--- a/dom/base/nsIContentPolicyBase.idl
+++ b/dom/base/nsIContentPolicyBase.idl
@@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType;
* by launching a dialog to prompt the user for something).
*/
-[scriptable,uuid(17418187-d86f-48dd-92d1-238838df0a4e)]
+[scriptable,uuid(d6ab1d11-8e24-4db4-8582-c40a78281737)]
interface nsIContentPolicyBase : nsISupports
{
/**
@@ -329,11 +329,17 @@ interface nsIContentPolicyBase : nsISupports
*/
const nsContentPolicyType TYPE_INTERNAL_IMAGE_FAVICON = 41;
+ /**
+ * Indicates an save-as link download from the front-end code.
+ */
+ const nsContentPolicyType TYPE_SAVEAS_DOWNLOAD = 42;
+
/* When adding new content types, please update nsContentBlocker,
- * NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
- * implementations, the static_assert in dom/cache/DBSchema.cpp,
- * and other things that are not listed here that are related to
- * nsIContentPolicy. */
+ * NS_CP_ContentTypeName, nsCSPContext, CSP_ContentTypeToDirective,
+ * DoContentSecurityChecks, all nsIContentPolicy implementations, the
+ * static_assert in dom/cache/DBSchema.cpp, nsPermissionManager.cpp,
+ * and other things that are not listed here that are related
+ * to nsIContentPolicy. */
//////////////////////////////////////////////////////////////////////
diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h
index 8f35e9ba5..7a73fae71 100644
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -18,11 +18,11 @@
#include "nsINode.h" // for base class
#include "nsIScriptGlobalObject.h" // for member (in nsCOMPtr)
#include "nsIServiceManager.h"
+#include "nsIURI.h" // for use in inline functions
#include "nsIUUIDGenerator.h"
#include "nsPIDOMWindow.h" // for use in inline functions
#include "nsPropertyTable.h" // for member
-#include "nsDataHashtable.h" // for member
-#include "nsURIHashKey.h" // for member
+#include "nsTHashtable.h" // for member
#include "mozilla/net/ReferrerPolicy.h" // for member
#include "nsWeakReference.h"
#include "mozilla/UseCounter.h"
@@ -151,6 +151,7 @@ class NodeIterator;
enum class OrientationType : uint32_t;
class ProcessingInstruction;
class Promise;
+class Selection;
class StyleSheetList;
class SVGDocument;
class SVGSVGElement;
@@ -181,13 +182,6 @@ enum DocumentFlavor {
DocumentFlavorPlain, // Just a Document
};
-// Enum for HSTS priming states
-enum class HSTSPrimingState {
- eNO_HSTS_PRIMING = 0, // don't do HSTS Priming
- eHSTS_PRIMING_ALLOW = 1, // if HSTS priming fails, allow the load to proceed
- eHSTS_PRIMING_BLOCK = 2 // if HSTS priming fails, block the load
-};
-
// Document states
// RTL locale: specific to the XUL localedir attribute
@@ -405,34 +399,6 @@ public:
}
/**
- * Check to see if a subresource we want to load requires HSTS priming
- * to be done.
- */
- HSTSPrimingState GetHSTSPrimingStateForLocation(nsIURI* aContentLocation) const
- {
- HSTSPrimingState state;
- if (mHSTSPrimingURIList.Get(aContentLocation, &state)) {
- return state;
- }
- return HSTSPrimingState::eNO_HSTS_PRIMING;
- }
-
- /**
- * Add a subresource to the HSTS priming list. If this URI is
- * not in the HSTS cache, it will trigger an HSTS priming request
- * when we try to load it.
- */
- void AddHSTSPrimingLocation(nsIURI* aContentLocation, HSTSPrimingState aState)
- {
- mHSTSPrimingURIList.Put(aContentLocation, aState);
- }
-
- void ClearHSTSPrimingLocation(nsIURI* aContentLocation)
- {
- mHSTSPrimingURIList.Remove(aContentLocation);
- }
-
- /**
* Set the principal responsible for this document.
*/
virtual void SetPrincipal(nsIPrincipal *aPrincipal) = 0;
@@ -898,6 +864,8 @@ public:
*/
Element* GetRootElement() const;
+ mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aRv);
+
/**
* Retrieve information about the viewport as a data structure.
* This will return information in the viewport META data section
@@ -2984,11 +2952,6 @@ protected:
bool mUpgradeInsecureRequests;
bool mUpgradeInsecurePreloads;
- // if nsMixedContentBlocker requires sending an HSTS priming request,
- // temporarily store that in the document so that it can be propogated to the
- // LoadInfo and eventually the HTTP Channel
- nsDataHashtable<nsURIHashKey, HSTSPrimingState> mHSTSPrimingURIList;
-
mozilla::WeakPtr<nsDocShell> mDocumentContainer;
nsCString mCharacterSet;
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp
index 3a649a61d..09e848710 100644
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1777,8 +1777,8 @@ nsINode::Before(const Sequence<OwningNodeOrString>& aNodes,
nsCOMPtr<nsINode> viablePreviousSibling =
FindViablePreviousSibling(*this, aNodes);
- nsCOMPtr<nsINode> node =
- ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
+ nsCOMPtr<nsIDocument> doc = OwnerDoc();
+ nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv);
if (aRv.Failed()) {
return;
}
@@ -1800,8 +1800,8 @@ nsINode::After(const Sequence<OwningNodeOrString>& aNodes,
nsCOMPtr<nsINode> viableNextSibling = FindViableNextSibling(*this, aNodes);
- nsCOMPtr<nsINode> node =
- ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
+ nsCOMPtr<nsIDocument> doc = OwnerDoc();
+ nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv);
if (aRv.Failed()) {
return;
}
@@ -1820,8 +1820,8 @@ nsINode::ReplaceWith(const Sequence<OwningNodeOrString>& aNodes,
nsCOMPtr<nsINode> viableNextSibling = FindViableNextSibling(*this, aNodes);
- nsCOMPtr<nsINode> node =
- ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
+ nsCOMPtr<nsIDocument> doc = OwnerDoc();
+ nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv);
if (aRv.Failed()) {
return;
}
@@ -1880,8 +1880,8 @@ void
nsINode::Prepend(const Sequence<OwningNodeOrString>& aNodes,
ErrorResult& aRv)
{
- nsCOMPtr<nsINode> node =
- ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
+ nsCOMPtr<nsIDocument> doc = OwnerDoc();
+ nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv);
if (aRv.Failed()) {
return;
}
@@ -1894,8 +1894,8 @@ void
nsINode::Append(const Sequence<OwningNodeOrString>& aNodes,
ErrorResult& aRv)
{
- nsCOMPtr<nsINode> node =
- ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
+ nsCOMPtr<nsIDocument> doc = OwnerDoc();
+ nsCOMPtr<nsINode> node = ConvertNodesOrStringsIntoNode(aNodes, doc, aRv);
if (aRv.Failed()) {
return;
}
@@ -1907,6 +1907,10 @@ void
nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify,
nsIContent* aKid, nsAttrAndChildArray& aChildArray)
{
+ // NOTE: This function must not trigger any calls to
+ // nsIDocument::GetRootElement() calls until *after* it has removed aKid from
+ // aChildArray. Any calls before then could potentially restore a stale
+ // value for our cached root element, per note in nsDocument::RemoveChildAt().
NS_PRECONDITION(aKid && aKid->GetParentNode() == this &&
aKid == GetChildAt(aIndex) &&
IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid");
diff --git a/dom/base/nsISelectionPrivate.idl b/dom/base/nsISelectionPrivate.idl
index 68412885e..049873b28 100644
--- a/dom/base/nsISelectionPrivate.idl
+++ b/dom/base/nsISelectionPrivate.idl
@@ -29,7 +29,7 @@ native nsDirection(nsDirection);
native ScrollAxis(nsIPresShell::ScrollAxis);
[scriptable, builtinclass, uuid(0c9f4f74-ee7e-4fe9-be6b-0ba856368178)]
-interface nsISelectionPrivate : nsISelection
+interface nsISelectionPrivate : nsISupports
{
const short ENDOFPRECEDINGLINE=0;
const short STARTOFNEXTLINE=1;
diff --git a/dom/base/nsISimpleContentPolicy.idl b/dom/base/nsISimpleContentPolicy.idl
index 493aee1a5..dc0474736 100644
--- a/dom/base/nsISimpleContentPolicy.idl
+++ b/dom/base/nsISimpleContentPolicy.idl
@@ -28,7 +28,7 @@ interface nsIDOMElement;
* by launching a dialog to prompt the user for something).
*/
-[scriptable,uuid(b9df71e3-a9b3-4706-b2d5-e6c0d3d68ec7)]
+[scriptable,uuid(1553a476-8a14-410b-8ecc-47f48e937392)]
interface nsISimpleContentPolicy : nsIContentPolicyBase
{
/**
diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
index 576f3052a..3be1a6d2f 100644
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1006,110 +1006,6 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv)
return NS_OK;
}
-#ifdef MOZ_JPROF
-
-#include <signal.h>
-
-inline bool
-IsJProfAction(struct sigaction *action)
-{
- return (action->sa_sigaction &&
- (action->sa_flags & (SA_RESTART | SA_SIGINFO)) == (SA_RESTART | SA_SIGINFO));
-}
-
-void NS_JProfStartProfiling();
-void NS_JProfStopProfiling();
-void NS_JProfClearCircular();
-
-static bool
-JProfStartProfilingJS(JSContext *cx, unsigned argc, JS::Value *vp)
-{
- NS_JProfStartProfiling();
- return true;
-}
-
-void NS_JProfStartProfiling()
-{
- // Figure out whether we're dealing with SIGPROF, SIGALRM, or
- // SIGPOLL profiling (SIGALRM for JP_REALTIME, SIGPOLL for
- // JP_RTC_HZ)
- struct sigaction action;
-
- // Must check ALRM before PROF since both are enabled for real-time
- sigaction(SIGALRM, nullptr, &action);
- //printf("SIGALRM: %p, flags = %x\n",action.sa_sigaction,action.sa_flags);
- if (IsJProfAction(&action)) {
- //printf("Beginning real-time jprof profiling.\n");
- raise(SIGALRM);
- return;
- }
-
- sigaction(SIGPROF, nullptr, &action);
- //printf("SIGPROF: %p, flags = %x\n",action.sa_sigaction,action.sa_flags);
- if (IsJProfAction(&action)) {
- //printf("Beginning process-time jprof profiling.\n");
- raise(SIGPROF);
- return;
- }
-
- sigaction(SIGPOLL, nullptr, &action);
- //printf("SIGPOLL: %p, flags = %x\n",action.sa_sigaction,action.sa_flags);
- if (IsJProfAction(&action)) {
- //printf("Beginning rtc-based jprof profiling.\n");
- raise(SIGPOLL);
- return;
- }
-
- printf("Could not start jprof-profiling since JPROF_FLAGS was not set.\n");
-}
-
-static bool
-JProfStopProfilingJS(JSContext *cx, unsigned argc, JS::Value *vp)
-{
- NS_JProfStopProfiling();
- return true;
-}
-
-void
-NS_JProfStopProfiling()
-{
- raise(SIGUSR1);
- //printf("Stopped jprof profiling.\n");
-}
-
-static bool
-JProfClearCircularJS(JSContext *cx, unsigned argc, JS::Value *vp)
-{
- NS_JProfClearCircular();
- return true;
-}
-
-void
-NS_JProfClearCircular()
-{
- raise(SIGUSR2);
- //printf("cleared jprof buffer\n");
-}
-
-static bool
-JProfSaveCircularJS(JSContext *cx, unsigned argc, JS::Value *vp)
-{
- // Not ideal...
- NS_JProfStopProfiling();
- NS_JProfStartProfiling();
- return true;
-}
-
-static const JSFunctionSpec JProfFunctions[] = {
- JS_FS("JProfStartProfiling", JProfStartProfilingJS, 0, 0),
- JS_FS("JProfStopProfiling", JProfStopProfilingJS, 0, 0),
- JS_FS("JProfClearCircular", JProfClearCircularJS, 0, 0),
- JS_FS("JProfSaveCircular", JProfSaveCircularJS, 0, 0),
- JS_FS_END
-};
-
-#endif /* defined(MOZ_JPROF) */
-
nsresult
nsJSContext::InitClasses(JS::Handle<JSObject*> aGlobalObj)
{
@@ -1121,11 +1017,6 @@ nsJSContext::InitClasses(JS::Handle<JSObject*> aGlobalObj)
// Attempt to initialize profiling functions
::JS_DefineProfilingFunctions(cx, aGlobalObj);
-#ifdef MOZ_JPROF
- // Attempt to initialize JProf functions
- ::JS_DefineFunctions(cx, aGlobalObj, JProfFunctions);
-#endif
-
return NS_OK;
}
diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp
index 69a9414fe..ecea95dc1 100644
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -297,15 +297,6 @@ nsNodeUtils::LastRelease(nsINode* aNode)
NodeWillBeDestroyed, (aNode));
}
- if (aNode->IsElement()) {
- Element* elem = aNode->AsElement();
- FragmentOrElement::nsDOMSlots* domSlots =
- static_cast<FragmentOrElement::nsDOMSlots*>(slots);
- for (auto& reg : domSlots->mRegisteredIntersectionObservers) {
- reg.observer->UnlinkTarget(*elem);
- }
- }
-
delete slots;
aNode->mSlots = nullptr;
}
diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h
index 45823057a..47affbb06 100644
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -444,7 +444,7 @@ public:
*/
virtual void DisableDeviceSensor(uint32_t aType) = 0;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
virtual void EnableOrientationChangeListener() = 0;
virtual void DisableOrientationChangeListener() = 0;
#endif
@@ -452,24 +452,6 @@ public:
virtual void EnableTimeChangeNotifications() = 0;
virtual void DisableTimeChangeNotifications() = 0;
-#ifdef MOZ_B2G
- /**
- * Tell the window that it should start to listen to the network event of the
- * given aType.
- *
- * Inner windows only.
- */
- virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) = 0;
-
- /**
- * Tell the window that it should stop to listen to the network event of the
- * given aType.
- *
- * Inner windows only.
- */
- virtual void DisableNetworkEvent(mozilla::EventMessage aEventMessage) = 0;
-#endif // MOZ_B2G
-
/**
* Tell this window that there is an observer for gamepad input
*
diff --git a/dom/base/nsStructuredCloneContainer.cpp b/dom/base/nsStructuredCloneContainer.cpp
index 8c2cdc091..ea2d38bc8 100644
--- a/dom/base/nsStructuredCloneContainer.cpp
+++ b/dom/base/nsStructuredCloneContainer.cpp
@@ -137,7 +137,7 @@ nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
return NS_ERROR_FAILURE;
}
- auto iter = Data().Iter();
+ auto iter = Data().Start();
size_t size = Data().Size();
nsAutoCString binaryData;
binaryData.SetLength(size);
diff --git a/dom/base/test/bug704320.sjs b/dom/base/test/bug704320.sjs
index dff77f4b3..e0f549533 100644
--- a/dom/base/test/bug704320.sjs
+++ b/dom/base/test/bug704320.sjs
@@ -194,12 +194,6 @@ function createPolicyTest(policy, optionalEarlierPolicy) {
}
function handleRequest(request, response) {
- if (request.method == 'HEAD') {
- // respond to a HEAD request with a 418 so that we can easily distinguish
- // HSTS priming responses and ignore them
- response.setStatusLine('1.1', 418, "I'm a teapot");
- return;
- }
var sharedKey = 'bug704320.sjs';
var params = request.queryString.split('&');
var action = params[0].split('=')[1];
diff --git a/dom/base/test/file_ipc_messagemanager_blob.html b/dom/base/test/file_ipc_messagemanager_blob.html
new file mode 100644
index 000000000..dbdd64a34
--- /dev/null
+++ b/dom/base/test/file_ipc_messagemanager_blob.html
@@ -0,0 +1 @@
+<!DOCTYPE HTML><html><body></body></html>
diff --git a/dom/base/test/file_simplecontentpolicy.js b/dom/base/test/file_simplecontentpolicy.js
index 1f9606c49..2727b9530 100644
--- a/dom/base/test/file_simplecontentpolicy.js
+++ b/dom/base/test/file_simplecontentpolicy.js
@@ -39,7 +39,6 @@ var policy = {
{
// Remember last content type seen for the test url
if (contentLocation.spec.endsWith(urlSuffix)) {
- assert.ok(frame === browserElement, "correct <browser> element");
sendAsyncMessage("shouldLoad", {contentType: contentType, isTopLevel: isTopLevel});
return Ci.nsIContentPolicy.REJECT_REQUEST;
}
diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini
index ddfd57443..b3b804ce4 100644
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -676,6 +676,7 @@ skip-if = (toolkit == 'android') # Android: Bug 775227
[test_intersectionobservers.html]
skip-if = true # Track Bug 1320704
[test_ipc_messagemanager_blob.html]
+support-files = file_ipc_messagemanager_blob.html
[test_link_prefetch.html]
skip-if = !e10s # Track Bug 1281415
[test_link_stylesheet.html]
diff --git a/dom/base/test/referrerHelper.js b/dom/base/test/referrerHelper.js
index 207bf5f15..01a22829c 100644
--- a/dom/base/test/referrerHelper.js
+++ b/dom/base/test/referrerHelper.js
@@ -25,9 +25,6 @@ function doXHR(url, onSuccess, onFail) {
xhr.onload = function () {
if (xhr.status == 200) {
onSuccess(xhr);
- } else if (xhr.status == 418) {
- // Ignore HSTS priming responses
- return;
} else {
onFail(xhr);
}
diff --git a/dom/base/test/test_intersectionobservers.html b/dom/base/test/test_intersectionobservers.html
index e7875e3af..10e3d7712 100644
--- a/dom/base/test/test_intersectionobservers.html
+++ b/dom/base/test/test_intersectionobservers.html
@@ -325,7 +325,7 @@ limitations under the License.
});
- it('does not trigger if target does not intersect when observing begins',
+ it('does trigger if target does not intersect when observing begins',
function(done) {
var spy = sinon.spy();
@@ -334,7 +334,7 @@ limitations under the License.
targetEl2.style.top = '-40px';
io.observe(targetEl2);
callDelayed(function() {
- expect(spy.callCount).to.be(0);
+ expect(spy.callCount).to.be(1);
done();
}, ASYNC_TIMEOUT);
});
@@ -528,7 +528,7 @@ limitations under the License.
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1);
var records = sortRecords(spy.lastCall.args[0]);
- expect(records.length).to.be(2);
+ expect(records.length).to.be(3);
expect(records[0].target).to.be(targetEl1);
expect(records[0].intersectionRatio).to.be(0.25);
expect(records[1].target).to.be(targetEl2);
@@ -636,10 +636,10 @@ limitations under the License.
expect(records.length).to.be(3);
expect(records[0].target).to.be(targetEl1);
expect(records[0].intersectionRatio).to.be(0.5);
- expect(records[1].target).to.be(targetEl3);
- expect(records[1].intersectionRatio).to.be(0.5);
- expect(records[2].target).to.be(targetEl4);
+ expect(records[2].target).to.be(targetEl3);
expect(records[2].intersectionRatio).to.be(0.5);
+ expect(records[3].target).to.be(targetEl4);
+ expect(records[3].intersectionRatio).to.be(0.5);
io.disconnect();
done();
}, {root: rootEl, rootMargin: '-10px 10%'});
@@ -652,11 +652,11 @@ limitations under the License.
function(done) {
io = new IntersectionObserver(function(records) {
records = sortRecords(records);
- expect(records.length).to.be(2);
+ expect(records.length).to.be(4);
expect(records[0].target).to.be(targetEl1);
expect(records[0].intersectionRatio).to.be(0.5);
- expect(records[1].target).to.be(targetEl4);
- expect(records[1].intersectionRatio).to.be(0.5);
+ expect(records[3].target).to.be(targetEl4);
+ expect(records[3].intersectionRatio).to.be(0.5);
io.disconnect();
done();
}, {root: rootEl, rootMargin: '-5% -2.5% 0px'});
@@ -669,13 +669,13 @@ limitations under the License.
function(done) {
io = new IntersectionObserver(function(records) {
records = sortRecords(records);
- expect(records.length).to.be(3);
+ expect(records.length).to.be(4);
expect(records[0].target).to.be(targetEl1);
expect(records[0].intersectionRatio).to.be(0.5);
expect(records[1].target).to.be(targetEl2);
expect(records[1].intersectionRatio).to.be(0.5);
- expect(records[2].target).to.be(targetEl4);
- expect(records[2].intersectionRatio).to.be(0.25);
+ expect(records[3].target).to.be(targetEl4);
+ expect(records[3].intersectionRatio).to.be(0.25);
io.disconnect();
done();
}, {root: rootEl, rootMargin: '5% -2.5% -10px -190px'});
@@ -705,9 +705,9 @@ limitations under the License.
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1);
var records = sortRecords(spy.lastCall.args[0]);
- expect(records.length).to.be(1);
- expect(records[0].intersectionRatio).to.be(0);
- expect(records[0].target).to.be(targetEl2);
+ expect(records.length).to.be(2);
+ expect(records[1].intersectionRatio).to.be(0);
+ expect(records[1].target).to.be(targetEl2);
done();
}, ASYNC_TIMEOUT);
},
@@ -797,14 +797,14 @@ limitations under the License.
function(done) {
document.getElementById('fixtures').appendChild(rootEl);
callDelayed(function() {
- expect(spy.callCount).to.be(0);
+ expect(spy.callCount).to.be(1);
done();
}, ASYNC_TIMEOUT);
},
function(done) {
parentEl.insertBefore(targetEl1, targetEl2);
spy.waitForNotification(function() {
- expect(spy.callCount).to.be(1);
+ expect(spy.callCount).to.be(2);
var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(1);
expect(records[0].intersectionRatio).to.be(1);
@@ -815,7 +815,7 @@ limitations under the License.
function(done) {
grandParentEl.parentNode.removeChild(grandParentEl);
spy.waitForNotification(function() {
- expect(spy.callCount).to.be(2);
+ expect(spy.callCount).to.be(3);
var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(1);
expect(records[0].intersectionRatio).to.be(0);
@@ -826,7 +826,7 @@ limitations under the License.
function(done) {
rootEl.appendChild(targetEl1);
spy.waitForNotification(function() {
- expect(spy.callCount).to.be(3);
+ expect(spy.callCount).to.be(4);
var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(1);
expect(records[0].intersectionRatio).to.be(1);
@@ -837,7 +837,7 @@ limitations under the License.
function(done) {
rootEl.parentNode.removeChild(rootEl);
spy.waitForNotification(function() {
- expect(spy.callCount).to.be(4);
+ expect(spy.callCount).to.be(5);
var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(1);
expect(records[0].intersectionRatio).to.be(0);
@@ -867,8 +867,14 @@ limitations under the License.
targetEl1.style.top = '220px';
targetEl1.style.left = '220px';
+
+ var callCount = 0;
io = new IntersectionObserver(function(records) {
+ callCount++;
+ if (callCount <= 1) {
+ return;
+ }
expect(records.length).to.be(1);
expect(records[0].intersectionRatio).to.be(1);
done();
@@ -891,6 +897,19 @@ limitations under the License.
var win = window.open("intersectionobserver_window.html");
});
+ it('triggers only once if observed multiple times (and does not crash when collected)', function(done) {
+ var spy = sinon.spy();
+ io = new IntersectionObserver(spy, {root: rootEl});
+ io.observe(targetEl1);
+ io.observe(targetEl1);
+ io.observe(targetEl1);
+
+ callDelayed(function () {
+ expect(spy.callCount).to.be(1);
+ done();
+ }, ASYNC_TIMEOUT);
+ });
+
});
describe('observe subframe', function () {
diff --git a/dom/base/test/test_ipc_messagemanager_blob.html b/dom/base/test/test_ipc_messagemanager_blob.html
index 74eab2945..77d6c767f 100644
--- a/dom/base/test/test_ipc_messagemanager_blob.html
+++ b/dom/base/test/test_ipc_messagemanager_blob.html
@@ -14,8 +14,7 @@
SimpleTest.waitForExplicitFinish();
- const childFrameURL =
- "data:text/html,<!DOCTYPE HTML><html><body></body></html>";
+ const childFrameURL = "file_ipc_messagemanager_blob.html";
function childFrameScript() {
"use strict";
diff --git a/dom/base/test/test_x-frame-options.html b/dom/base/test/test_x-frame-options.html
index 8e24d8a78..a0c7acdc3 100644
--- a/dom/base/test/test_x-frame-options.html
+++ b/dom/base/test/test_x-frame-options.html
@@ -147,7 +147,11 @@ var testFrameInDataURI = function() {
SimpleTest.waitForExplicitFinish();
// load the test harness
-document.getElementById("harness").src = "file_x-frame-options_main.html";
+SpecialPowers.pushPrefEnv({
+ "set": [["security.data_uri.block_toplevel_data_uri_navigations", false],]
+}, function() {
+ document.getElementById("harness").src = "file_x-frame-options_main.html";
+});
</script>
</pre>
diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp
index 33f5f7a44..7056658a7 100644
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -259,8 +259,8 @@ TErrorResult<CleanupPolicy>::ThrowJSException(JSContext* cx, JS::Handle<JS::Valu
// Make sure mJSException is initialized _before_ we try to root it. But
// don't set it to exn yet, because we don't want to do that until after we
// root.
- mJSException.setUndefined();
- if (!js::AddRawValueRoot(cx, &mJSException, "TErrorResult::mJSException")) {
+ mJSException.asValueRef().setUndefined();
+ if (!js::AddRawValueRoot(cx, &mJSException.asValueRef(), "TErrorResult::mJSException")) {
// Don't use NS_ERROR_DOM_JS_EXCEPTION, because that indicates we have
// in fact rooted mJSException.
mResult = NS_ERROR_OUT_OF_MEMORY;
@@ -289,7 +289,7 @@ TErrorResult<CleanupPolicy>::SetPendingJSException(JSContext* cx)
mJSException = exception;
// If JS_WrapValue failed, not much we can do about it... No matter
// what, go ahead and unroot mJSException.
- js::RemoveRawValueRoot(cx, &mJSException);
+ js::RemoveRawValueRoot(cx, &mJSException.asValueRef());
mResult = NS_OK;
#ifdef DEBUG
@@ -395,8 +395,8 @@ TErrorResult<CleanupPolicy>::ClearUnionData()
if (IsJSException()) {
JSContext* cx = dom::danger::GetJSContext();
MOZ_ASSERT(cx);
- mJSException.setUndefined();
- js::RemoveRawValueRoot(cx, &mJSException);
+ mJSException.asValueRef().setUndefined();
+ js::RemoveRawValueRoot(cx, &mJSException.asValueRef());
#ifdef DEBUG
mUnionState = HasNothing;
#endif // DEBUG
@@ -439,13 +439,13 @@ TErrorResult<CleanupPolicy>::operator=(TErrorResult<CleanupPolicy>&& aRHS)
} else if (aRHS.IsJSException()) {
JSContext* cx = dom::danger::GetJSContext();
MOZ_ASSERT(cx);
- mJSException.setUndefined();
- if (!js::AddRawValueRoot(cx, &mJSException, "TErrorResult::mJSException")) {
+ mJSException.asValueRef().setUndefined();
+ if (!js::AddRawValueRoot(cx, &mJSException.asValueRef(), "TErrorResult::mJSException")) {
MOZ_CRASH("Could not root mJSException, we're about to OOM");
}
mJSException = aRHS.mJSException;
- aRHS.mJSException.setUndefined();
- js::RemoveRawValueRoot(cx, &aRHS.mJSException);
+ aRHS.mJSException.asValueRef().setUndefined();
+ js::RemoveRawValueRoot(cx, &aRHS.mJSException.asValueRef());
} else if (aRHS.IsDOMException()) {
mDOMExceptionInfo = aRHS.mDOMExceptionInfo;
aRHS.mDOMExceptionInfo = nullptr;
@@ -497,7 +497,7 @@ TErrorResult<CleanupPolicy>::CloneTo(TErrorResult& aRv) const
aRv.mUnionState = HasJSException;
#endif
JSContext* cx = dom::danger::GetJSContext();
- JS::Rooted<JS::Value> exception(cx, mJSException);
+ JS::Rooted<JS::Value> exception(cx, mJSException.asValueRef());
aRv.ThrowJSException(cx, exception);
}
}
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 3174c37dd..7a6668687 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1069,6 +1069,20 @@ class CGHeaders(CGWrapper):
if parent:
ancestors.append(parent)
interfaceDeps.extend(ancestors)
+
+ # Include parent interface headers needed for jsonifier code.
+ jsonInterfaceParents = []
+ for desc in descriptors:
+ if not desc.operations['Jsonifier']:
+ continue
+ parent = desc.interface.parent
+ while parent:
+ parentDesc = desc.getDescriptor(parent.identifier.name)
+ if parentDesc.operations['Jsonifier']:
+ jsonInterfaceParents.append(parentDesc.interface)
+ parent = parent.parent
+ interfaceDeps.extend(jsonInterfaceParents)
+
bindingIncludes = set(self.getDeclarationFilename(d) for d in interfaceDeps)
# Grab all the implementation declaration files we need.
diff --git a/dom/bindings/DOMJSProxyHandler.cpp b/dom/bindings/DOMJSProxyHandler.cpp
index 65e540bc1..23f0abd88 100644
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -166,6 +166,10 @@ DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
nsISupports* native = UnwrapDOMObject<nsISupports>(obj);
nsWrapperCache* cache;
CallQueryInterface(native, &cache);
+ if (!cache) {
+ return expando;
+ }
+
if (expandoAndGeneration) {
cache->PreserveWrapper(native);
expandoAndGeneration->expando.setObject(*expando);
diff --git a/dom/bindings/ErrorResult.h b/dom/bindings/ErrorResult.h
index c45e7ea3b..7c3fc9e2f 100644
--- a/dom/bindings/ErrorResult.h
+++ b/dom/bindings/ErrorResult.h
@@ -461,7 +461,7 @@ private:
// (and deallocated) by SetPendingDOMException.
union {
Message* mMessage; // valid when IsErrorWithMessage()
- JS::Value mJSException; // valid when IsJSException()
+ JS::UninitializedValue mJSException; // valid when IsJSException()
DOMExceptionInfo* mDOMExceptionInfo; // valid when IsDOMException()
};
diff --git a/dom/broadcastchannel/BroadcastChannel.cpp b/dom/broadcastchannel/BroadcastChannel.cpp
index c3c2d448b..d154b6562 100644
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -154,8 +154,8 @@ public:
bool success;
SerializedStructuredCloneBuffer& buffer = message.data();
- auto iter = mData->BufferData().Iter();
- buffer.data = mData->BufferData().Borrow<js::SystemAllocPolicy>(iter, mData->BufferData().Size(), &success);
+ auto iter = mData->BufferData().Start();
+ buffer.data = mData->BufferData().Borrow(iter, mData->BufferData().Size(), &success);
if (NS_WARN_IF(!success)) {
return NS_OK;
}
@@ -369,7 +369,7 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
RefPtr<InitializeRunnable> runnable =
new InitializeRunnable(workerPrivate, origin, principalInfo, aRv);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Closing, aRv);
}
if (aRv.Failed()) {
diff --git a/dom/browser-element/mochitest/browserElementTestHelpers.js b/dom/browser-element/mochitest/browserElementTestHelpers.js
index 004b25333..8df1476ac 100644
--- a/dom/browser-element/mochitest/browserElementTestHelpers.js
+++ b/dom/browser-element/mochitest/browserElementTestHelpers.js
@@ -84,6 +84,10 @@ const browserElementTestHelpers = {
this.unlockTestReady.bind(this));
},
+ allowTopLevelDataURINavigation: function() {
+ this._setPref("security.data_uri.block_toplevel_data_uri_navigations", false);
+ },
+
_observers: [],
// This function is a wrapper which lets you register an observer to one of
diff --git a/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js b/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js
index 420b4bc34..65a777861 100644
--- a/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js
+++ b/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var srcResizeTo = "data:text/html, \
diff --git a/dom/browser-element/mochitest/browserElement_Close.js b/dom/browser-element/mochitest/browserElement_Close.js
index 57bdf384d..103805404 100644
--- a/dom/browser-element/mochitest/browserElement_Close.js
+++ b/dom/browser-element/mochitest/browserElement_Close.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement('iframe');
diff --git a/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js b/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
index 66aa8e015..a8c361ebd 100644
--- a/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
+++ b/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
@@ -4,6 +4,7 @@ SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.setClipboardPlainTextOnlyPref(false);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
var audioUrl = 'http://mochi.test:8888/tests/dom/browser-element/mochitest/audio.ogg';
var videoUrl = 'http://mochi.test:8888/tests/dom/browser-element/mochitest/short-video.ogv';
diff --git a/dom/browser-element/mochitest/browserElement_CopyPaste.js b/dom/browser-element/mochitest/browserElement_CopyPaste.js
index b23feef59..97a37be8b 100644
--- a/dom/browser-element/mochitest/browserElement_CopyPaste.js
+++ b/dom/browser-element/mochitest/browserElement_CopyPaste.js
@@ -9,6 +9,7 @@ SimpleTest.requestFlakyTimeout("untriaged");
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.setupAccessibleCaretPref();
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm');
var gTextarea = null;
diff --git a/dom/browser-element/mochitest/browserElement_DataURI.js b/dom/browser-element/mochitest/browserElement_DataURI.js
index f57f4566a..d31678f89 100644
--- a/dom/browser-element/mochitest/browserElement_DataURI.js
+++ b/dom/browser-element/mochitest/browserElement_DataURI.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe1 = document.createElement('iframe');
diff --git a/dom/browser-element/mochitest/browserElement_Iconchange.js b/dom/browser-element/mochitest/browserElement_Iconchange.js
index 367a2de15..283331d3c 100644
--- a/dom/browser-element/mochitest/browserElement_Iconchange.js
+++ b/dom/browser-element/mochitest/browserElement_Iconchange.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function createHtml(link) {
return 'data:text/html,<html><head>' + link + '<body></body></html>';
diff --git a/dom/browser-element/mochitest/browserElement_Manifestchange.js b/dom/browser-element/mochitest/browserElement_Manifestchange.js
index 22cf8fe7c..5b3733d14 100644
--- a/dom/browser-element/mochitest/browserElement_Manifestchange.js
+++ b/dom/browser-element/mochitest/browserElement_Manifestchange.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function createHtml(manifest) {
return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' + manifest + '<body></body></html>';
diff --git a/dom/browser-element/mochitest/browserElement_Metachange.js b/dom/browser-element/mochitest/browserElement_Metachange.js
index 7789a3e18..53c8d2397 100644
--- a/dom/browser-element/mochitest/browserElement_Metachange.js
+++ b/dom/browser-element/mochitest/browserElement_Metachange.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function createHtml(meta) {
return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' + meta + '<body></body></html>';
diff --git a/dom/browser-element/mochitest/browserElement_Opensearch.js b/dom/browser-element/mochitest/browserElement_Opensearch.js
index 8df44d2a9..5762e6f0e 100644
--- a/dom/browser-element/mochitest/browserElement_Opensearch.js
+++ b/dom/browser-element/mochitest/browserElement_Opensearch.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function createHtml(link) {
return 'data:text/html,<html><head>' + link + '<body></body></html>';
diff --git a/dom/browser-element/mochitest/browserElement_PromptCheck.js b/dom/browser-element/mochitest/browserElement_PromptCheck.js
index d6edde09f..952f4468e 100644
--- a/dom/browser-element/mochitest/browserElement_PromptCheck.js
+++ b/dom/browser-element/mochitest/browserElement_PromptCheck.js
@@ -13,6 +13,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest()
{
diff --git a/dom/browser-element/mochitest/browserElement_PromptConfirm.js b/dom/browser-element/mochitest/browserElement_PromptConfirm.js
index c01836a25..b920a6d26 100644
--- a/dom/browser-element/mochitest/browserElement_PromptConfirm.js
+++ b/dom/browser-element/mochitest/browserElement_PromptConfirm.js
@@ -11,6 +11,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement('iframe');
diff --git a/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js b/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js
index 583d58734..3ab206388 100644
--- a/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js
+++ b/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js
@@ -9,6 +9,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement('iframe');
diff --git a/dom/browser-element/mochitest/browserElement_ScrollEvent.js b/dom/browser-element/mochitest/browserElement_ScrollEvent.js
index 06dc91b86..5230c524a 100644
--- a/dom/browser-element/mochitest/browserElement_ScrollEvent.js
+++ b/dom/browser-element/mochitest/browserElement_ScrollEvent.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement('iframe');
diff --git a/dom/browser-element/mochitest/browserElement_Titlechange.js b/dom/browser-element/mochitest/browserElement_Titlechange.js
index 78c939ad8..145e9baa8 100644
--- a/dom/browser-element/mochitest/browserElement_Titlechange.js
+++ b/dom/browser-element/mochitest/browserElement_Titlechange.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe1 = document.createElement('iframe');
diff --git a/dom/browser-element/mochitest/browserElement_TopBarrier.js b/dom/browser-element/mochitest/browserElement_TopBarrier.js
index 3bd68854c..186622b33 100644
--- a/dom/browser-element/mochitest/browserElement_TopBarrier.js
+++ b/dom/browser-element/mochitest/browserElement_TopBarrier.js
@@ -7,6 +7,7 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
var iframe;
function runTest() {
diff --git a/dom/cache/Cache.cpp b/dom/cache/Cache.cpp
index 0d5815edb..b183bf387 100644
--- a/dom/cache/Cache.cpp
+++ b/dom/cache/Cache.cpp
@@ -618,7 +618,7 @@ Cache::AddAll(const GlobalObject& aGlobal,
new FetchHandler(mActor->GetWorkerHolder(), this,
Move(aRequestList), promise);
- RefPtr<Promise> fetchPromise = Promise::All(aGlobal, fetchList, aRv);
+ RefPtr<Promise> fetchPromise = Promise::All(aGlobal.Context(), fetchList, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
diff --git a/dom/cache/DBSchema.cpp b/dom/cache/DBSchema.cpp
index d16ba2d6a..176e7b9d1 100644
--- a/dom/cache/DBSchema.cpp
+++ b/dom/cache/DBSchema.cpp
@@ -287,7 +287,8 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD == 38 &&
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 &&
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40 &&
- nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON == 41,
+ nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON == 41 &&
+ nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD == 42,
"nsContentPolicyType values are as expected");
namespace {
diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp
index 15df2b337..18af28e9f 100644
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -105,6 +105,7 @@
#include "mozilla/dom/CanvasPath.h"
#include "mozilla/dom/HTMLImageElement.h"
#include "mozilla/dom/HTMLVideoElement.h"
+#include "mozilla/dom/SVGImageElement.h"
#include "mozilla/dom/SVGMatrix.h"
#include "mozilla/dom/TextMetrics.h"
#include "mozilla/dom/SVGMatrix.h"
@@ -140,10 +141,6 @@ using mozilla::gl::GLContextProvider;
#include "gfxWindowsPlatform.h"
#endif
-#ifdef MOZ_WIDGET_GONK
-#include "mozilla/layers/ShadowLayers.h"
-#endif
-
// windows.h (included by chromium code) defines this, in its infinite wisdom
#undef DrawText
@@ -1865,8 +1862,6 @@ CanvasRenderingContext2D::GetHeight() const
NS_IMETHODIMP
CanvasRenderingContext2D::SetDimensions(int32_t aWidth, int32_t aHeight)
{
- ClearTarget();
-
// Zero sized surfaces can cause problems.
mZero = false;
if (aHeight == 0) {
@@ -1877,14 +1872,14 @@ CanvasRenderingContext2D::SetDimensions(int32_t aWidth, int32_t aHeight)
aWidth = 1;
mZero = true;
}
- mWidth = aWidth;
- mHeight = aHeight;
+
+ ClearTarget(aWidth, aHeight);
return NS_OK;
}
void
-CanvasRenderingContext2D::ClearTarget()
+CanvasRenderingContext2D::ClearTarget(int32_t aWidth, int32_t aHeight)
{
Reset();
@@ -1892,6 +1887,12 @@ CanvasRenderingContext2D::ClearTarget()
SetInitialState();
+ // Update dimensions only if new (strictly positive) values were passed.
+ if (aWidth > 0 && aHeight > 0) {
+ mWidth = aWidth;
+ mHeight = aHeight;
+ }
+
// For vertical writing-mode, unless text-orientation is sideways,
// we'll modify the initial value of textBaseline to 'middle'.
RefPtr<nsStyleContext> canvasStyle;
@@ -2477,10 +2478,10 @@ CanvasRenderingContext2D::CreatePattern(const CanvasImageSource& aSource,
return nullptr;
}
- Element* htmlElement;
+ Element* element;
if (aSource.IsHTMLCanvasElement()) {
HTMLCanvasElement* canvas = &aSource.GetAsHTMLCanvasElement();
- htmlElement = canvas;
+ element = canvas;
nsIntSize size = canvas->GetSize();
if (size.width == 0 || size.height == 0) {
@@ -2505,7 +2506,7 @@ CanvasRenderingContext2D::CreatePattern(const CanvasImageSource& aSource,
}
RefPtr<CanvasPattern> pat =
- new CanvasPattern(this, srcSurf, repeatMode, htmlElement->NodePrincipal(), canvas->IsWriteOnly(), false);
+ new CanvasPattern(this, srcSurf, repeatMode, element->NodePrincipal(), canvas->IsWriteOnly(), false);
return pat.forget();
}
@@ -2516,11 +2517,19 @@ CanvasRenderingContext2D::CreatePattern(const CanvasImageSource& aSource,
return nullptr;
}
- htmlElement = img;
+ element = img;
+ } else if (aSource.IsSVGImageElement()) {
+ SVGImageElement* img = &aSource.GetAsSVGImageElement();
+ if (img->IntrinsicState().HasState(NS_EVENT_STATE_BROKEN)) {
+ aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return nullptr;
+ }
+
+ element = img;
} else if (aSource.IsHTMLVideoElement()) {
auto& video = aSource.GetAsHTMLVideoElement();
video.MarkAsContentSource(mozilla::dom::HTMLVideoElement::CallerAPI::CREATE_PATTERN);
- htmlElement = &video;
+ element = &video;
} else {
// Special case for ImageBitmap
ImageBitmap& imgBitmap = aSource.GetAsImageBitmap();
@@ -2559,7 +2568,7 @@ CanvasRenderingContext2D::CreatePattern(const CanvasImageSource& aSource,
// The canvas spec says that createPattern should use the first frame
// of animated images
nsLayoutUtils::SurfaceFromElementResult res =
- nsLayoutUtils::SurfaceFromElement(htmlElement,
+ nsLayoutUtils::SurfaceFromElement(element,
nsLayoutUtils::SFE_WANT_FIRST_FRAME, mTarget);
if (!res.GetSourceSurface()) {
@@ -4949,6 +4958,9 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
if (aImage.IsHTMLImageElement()) {
HTMLImageElement* img = &aImage.GetAsHTMLImageElement();
element = img;
+ } else if (aImage.IsSVGImageElement()) {
+ SVGImageElement* img = &aImage.GetAsSVGImageElement();
+ element = img;
} else {
HTMLVideoElement* video = &aImage.GetAsHTMLVideoElement();
video->MarkAsContentSource(mozilla::dom::HTMLVideoElement::CallerAPI::DRAW_IMAGE);
diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h
index c3ee3bdcb..848b3ee08 100644
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -38,8 +38,8 @@ class SourceSurface;
} // namespace gl
namespace dom {
-class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap;
-typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap CanvasImageSource;
+class HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap;
+typedef HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap CanvasImageSource;
class ImageData;
class StringOrCanvasGradientOrCanvasPattern;
class OwningStringOrCanvasGradientOrCanvasPattern;
@@ -669,8 +669,11 @@ protected:
/**
* Disposes an old target and prepares to lazily create a new target.
+ *
+ * Parameters are the new dimensions to be used, or if either is negative,
+ * existing dimensions will be left unchanged.
*/
- void ClearTarget();
+ void ClearTarget(int32_t aWidth = -1, int32_t aHeight = -1);
/*
* Returns the target to the buffer provider. i.e. this will queue a frame for
diff --git a/dom/canvas/ImageBitmap.cpp b/dom/canvas/ImageBitmap.cpp
index 6588e0aa3..e45cdfc6f 100644
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -950,7 +950,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData,
imageSize,
aCropRect,
getter_AddRefs(data));
- task->Dispatch(aRv);
+ task->Dispatch(Terminating, aRv);
}
if (NS_WARN_IF(!data)) {
@@ -1377,10 +1377,10 @@ private:
RefPtr<DecodeBlobInMainThreadSyncTask> task =
new DecodeBlobInMainThreadSyncTask(mWorkerPrivate, *mBlob, mCropRect,
getter_AddRefs(data), sourceSize);
- task->Dispatch(rv); // This is a synchronous call.
+ task->Dispatch(Terminating, rv); // This is a synchronous call.
+ // In case the worker is terminating, this rejection can be handled.
if (NS_WARN_IF(rv.Failed())) {
- // XXXbz does this really make sense if we're shutting down? Ah, well.
mPromise->MaybeReject(rv);
return nullptr;
}
@@ -2104,7 +2104,10 @@ ImageBitmap::Create(nsIGlobalObject* aGlobal,
aFormat,
aLayout,
getter_AddRefs(data));
- task->Dispatch(aRv);
+ task->Dispatch(Terminating, aRv);
+ if (aRv.Failed()) {
+ return promise.forget();
+ }
}
if (NS_WARN_IF(!data)) {
diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp
index 176d56f8c..32eed6354 100644
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -9,7 +9,6 @@
#include "AccessCheck.h"
#include "gfxContext.h"
-#include "gfxCrashReporterUtils.h"
#include "gfxPattern.h"
#include "gfxPrefs.h"
#include "gfxUtils.h"
@@ -51,10 +50,6 @@
#include "VRManagerChild.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
-#ifdef MOZ_WIDGET_GONK
-#include "mozilla/layers/ShadowLayers.h"
-#endif
-
// Local
#include "CanvasUtils.h"
#include "WebGL1Context.h"
@@ -545,30 +540,6 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
// for now it's just behind a pref for testing/evaluation.
baseCaps.bpp16 = gfxPrefs::WebGLPrefer16bpp();
-#ifdef MOZ_WIDGET_GONK
- do {
- auto canvasElement = webgl->GetCanvas();
- if (!canvasElement)
- break;
-
- auto ownerDoc = canvasElement->OwnerDoc();
- nsIWidget* docWidget = nsContentUtils::WidgetForDocument(ownerDoc);
- if (!docWidget)
- break;
-
- layers::LayerManager* layerManager = docWidget->GetLayerManager();
- if (!layerManager)
- break;
-
- // XXX we really want "AsSurfaceAllocator" here for generality
- layers::ShadowLayerForwarder* forwarder = layerManager->AsShadowForwarder();
- if (!forwarder)
- break;
-
- baseCaps.surfaceAllocator = forwarder->GetTextureForwarder();
- } while (false);
-#endif
-
// Done with baseCaps construction.
if (!gfxPrefs::WebGLForceMSAA()) {
@@ -984,7 +955,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
// Alright, now let's start trying.
bool forceEnabled = gfxPrefs::WebGLForceEnabled();
- ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
MOZ_ASSERT(!gl);
std::vector<FailureReason> failReasons;
@@ -1115,8 +1085,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
//////
- reporter.SetSuccessful();
-
failureId = NS_LITERAL_CSTRING("SUCCESS");
return NS_OK;
}
diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp
index 867e47cbd..fd9ee4957 100644
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -216,7 +216,21 @@ WebGLContext::BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fa
UniquePtr<FakeBlackTexture>& fakeBlackTex = *slot;
if (!fakeBlackTex) {
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
+ if (IsWebGL2()) {
+ gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS, 0);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, 0);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, 0);
+ }
+
fakeBlackTex = FakeBlackTexture::Create(gl, target, fakeBlack);
+
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mPixelStore_UnpackAlignment);
+ if (IsWebGL2()) {
+ gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS, mPixelStore_UnpackSkipPixels);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, mPixelStore_UnpackSkipRows);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, mPixelStore_UnpackSkipImages);
+ }
if (!fakeBlackTex) {
return false;
}
@@ -1212,13 +1226,8 @@ WebGLContext::FakeBlackTexture::Create(gl::GLContext* gl, TexTarget target,
gl->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
gl->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
- // We allocate our zeros on the heap, and we overallocate (16 bytes instead of 4) to
- // minimize the risk of running into a driver bug in texImage2D, as it is a bit
- // unusual maybe to create 1x1 textures, and the stack may not have the alignment that
- // TexImage2D expects.
-
const webgl::DriverUnpackInfo dui = {texFormat, texFormat, LOCAL_GL_UNSIGNED_BYTE};
- UniqueBuffer zeros = moz_xcalloc(1, 16); // Infallible allocation.
+ UniqueBuffer zeros = moz_xcalloc(1, 4); // Infallible allocation.
MOZ_ASSERT(gl->IsCurrent());
diff --git a/dom/canvas/test/webgl-mochitest/driver-info.js b/dom/canvas/test/webgl-mochitest/driver-info.js
index e2f6e003a..3f2fe102c 100644
--- a/dom/canvas/test/webgl-mochitest/driver-info.js
+++ b/dom/canvas/test/webgl-mochitest/driver-info.js
@@ -81,9 +81,6 @@ DriverInfo = (function() {
var versionMatch = /Mac OS X (\d+.\d+)/.exec(navigator.userAgent);
version = versionMatch ? parseFloat(versionMatch[1]) : null;
- } else if (runtime.widgetToolkit == 'gonk') {
- os = OS.B2G;
-
} else if (navigator.appVersion.indexOf('Android') != -1) {
os = OS.ANDROID;
// From layout/tools/reftest/reftest.js:
diff --git a/dom/console/Console.cpp b/dom/console/Console.cpp
index 79e3eadc5..ff5a92167 100755
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -1336,10 +1336,7 @@ Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
- TimeDuration duration =
- mozilla::TimeStamp::Now() - workerPrivate->NowBaseTimeStamp();
-
- monotonicTimer = TimerClamping::ReduceMsTimeValue(duration.ToMilliseconds());
+ monotonicTimer = workerPrivate->TimeStampToDOMHighRes(TimeStamp::Now());
}
}
diff --git a/dom/console/Console.h b/dom/console/Console.h
index b334d79f9..2f375c8eb 100644
--- a/dom/console/Console.h
+++ b/dom/console/Console.h
@@ -258,9 +258,8 @@ private:
// the max number of timers is reached.
// * aCx - the JSContext rooting aName.
// * aName - this is (should be) the name of the timer as JS::Value.
- // * aTimestamp - the monotonicTimer for this context (taken from
- // window->performance.now() or from Now() -
- // workerPrivate->NowBaseTimeStamp() in workers.
+ // * aTimestamp - the monotonicTimer for this context taken from
+ // performance.now().
// * aTimerLabel - This label will be populated with the aName converted to a
// string.
// * aTimerValue - the StartTimer value stored into (or taken from)
@@ -290,9 +289,8 @@ private:
// the aName timer doesn't exist in the mTimerRegistry.
// * aCx - the JSContext rooting aName.
// * aName - this is (should be) the name of the timer as JS::Value.
- // * aTimestamp - the monotonicTimer for this context (taken from
- // window->performance.now() or from Now() -
- // workerPrivate->NowBaseTimeStamp() in workers.
+ // * aTimestamp - the monotonicTimer for this context taken from
+ // performance.now().
// * aTimerLabel - This label will be populated with the aName converted to a
// string.
// * aTimerDuration - the difference between aTimestamp and when the timer
diff --git a/dom/downloads/DownloadsAPI.js b/dom/downloads/DownloadsAPI.js
deleted file mode 100644
index 8294e2a3e..000000000
--- a/dom/downloads/DownloadsAPI.js
+++ /dev/null
@@ -1,517 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-Cu.import("resource://gre/modules/DownloadsIPC.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsIMessageSender");
-XPCOMUtils.defineLazyServiceGetter(this, "volumeService",
- "@mozilla.org/telephony/volume-service;1",
- "nsIVolumeService");
-
-/**
- * The content process implementations of navigator.mozDownloadManager and its
- * DOMDownload download objects. Uses DownloadsIPC.jsm to communicate with
- * DownloadsAPI.jsm in the parent process.
- */
-
-function debug(aStr) {
-#ifdef MOZ_DEBUG
- dump("-*- DownloadsAPI.js : " + aStr + "\n");
-#endif
-}
-
-function DOMDownloadManagerImpl() {
- debug("DOMDownloadManagerImpl constructor");
-}
-
-DOMDownloadManagerImpl.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
-
- // nsIDOMGlobalPropertyInitializer implementation
- init: function(aWindow) {
- debug("DownloadsManager init");
- this.initDOMRequestHelper(aWindow,
- ["Downloads:Added",
- "Downloads:Removed"]);
-
- // Get the manifest URL if this is an installed app
- let appsService = Cc["@mozilla.org/AppsService;1"]
- .getService(Ci.nsIAppsService);
- let principal = aWindow.document.nodePrincipal;
- // This returns the empty string if we're not an installed app. Coerce to
- // null.
- this._manifestURL = appsService.getManifestURLByLocalId(principal.appId) ||
- null;
- },
-
- uninit: function() {
- debug("uninit");
- downloadsCache.evict(this._window);
- },
-
- set ondownloadstart(aHandler) {
- this.__DOM_IMPL__.setEventHandler("ondownloadstart", aHandler);
- },
-
- get ondownloadstart() {
- return this.__DOM_IMPL__.getEventHandler("ondownloadstart");
- },
-
- getDownloads: function() {
- debug("getDownloads()");
-
- return this.createPromise(function (aResolve, aReject) {
- DownloadsIPC.getDownloads().then(
- function(aDownloads) {
- // Turn the list of download objects into DOM objects and
- // send them.
- let array = new this._window.Array();
- for (let id in aDownloads) {
- let dom = createDOMDownloadObject(this._window, aDownloads[id]);
- array.push(this._prepareForContent(dom));
- }
- aResolve(array);
- }.bind(this),
- function() {
- aReject("GetDownloadsError");
- }
- );
- }.bind(this));
- },
-
- clearAllDone: function() {
- debug("clearAllDone()");
- // This is a void function; we just kick it off. No promises, etc.
- DownloadsIPC.clearAllDone();
- },
-
- remove: function(aDownload) {
- debug("remove " + aDownload.url + " " + aDownload.id);
- return this.createPromise(function (aResolve, aReject) {
- if (!downloadsCache.has(this._window, aDownload.id)) {
- debug("no download " + aDownload.id);
- aReject("InvalidDownload");
- return;
- }
-
- DownloadsIPC.remove(aDownload.id).then(
- function(aResult) {
- let dom = createDOMDownloadObject(this._window, aResult);
- // Change the state right away to not race against the update message.
- dom.wrappedJSObject.state = "finalized";
- aResolve(this._prepareForContent(dom));
- }.bind(this),
- function() {
- aReject("RemoveError");
- }
- );
- }.bind(this));
- },
-
- adoptDownload: function(aAdoptDownloadDict) {
- // Our AdoptDownloadDict only includes simple types, which WebIDL enforces.
- // We have no object/any types so we do not need to worry about invoking
- // JSON.stringify (and it inheriting our security privileges).
- debug("adoptDownload");
- return this.createPromise(function (aResolve, aReject) {
- if (!aAdoptDownloadDict) {
- debug("Download dictionary is required!");
- aReject("InvalidDownload");
- return;
- }
- if (!aAdoptDownloadDict.storageName || !aAdoptDownloadDict.storagePath ||
- !aAdoptDownloadDict.contentType) {
- debug("Missing one of: storageName, storagePath, contentType");
- aReject("InvalidDownload");
- return;
- }
-
- // Convert storageName/storagePath to a local filesystem path.
- let volume;
- // getVolumeByName throws if you give it something it doesn't like
- // because XPConnect converts the NS_ERROR_NOT_AVAILABLE to an
- // exception. So catch it.
- try {
- volume = volumeService.getVolumeByName(aAdoptDownloadDict.storageName);
- } catch (ex) {}
- if (!volume) {
- debug("Invalid storage name: " + aAdoptDownloadDict.storageName);
- aReject("InvalidDownload");
- return;
- }
- let computedPath = volume.mountPoint + '/' +
- aAdoptDownloadDict.storagePath;
- // We validate that there is actually a file at the given path in the
- // parent process in DownloadsAPI.js because that's where the file
- // access would actually occur either way.
-
- // Create a DownloadsAPI.jsm 'jsonDownload' style representation.
- let jsonDownload = {
- url: aAdoptDownloadDict.url,
- path: computedPath,
- contentType: aAdoptDownloadDict.contentType,
- startTime: aAdoptDownloadDict.startTime.valueOf() || Date.now(),
- sourceAppManifestURL: this._manifestURL
- };
-
- DownloadsIPC.adoptDownload(jsonDownload).then(
- function(aResult) {
- let domDownload = createDOMDownloadObject(this._window, aResult);
- aResolve(this._prepareForContent(domDownload));
- }.bind(this),
- function(aResult) {
- // This will be one of: AdoptError (generic catch-all),
- // AdoptNoSuchFile, AdoptFileIsDirectory
- aReject(aResult.error);
- }
- );
- }.bind(this));
- },
-
-
- /**
- * Turns a chrome download object into a content accessible one.
- * When we have __DOM_IMPL__ available we just use that, otherwise
- * we run _create() with the wrapped js object.
- */
- _prepareForContent: function(aChromeObject) {
- if (aChromeObject.__DOM_IMPL__) {
- return aChromeObject.__DOM_IMPL__;
- }
- let res = this._window.DOMDownload._create(this._window,
- aChromeObject.wrappedJSObject);
- return res;
- },
-
- receiveMessage: function(aMessage) {
- let data = aMessage.data;
- switch(aMessage.name) {
- case "Downloads:Added":
- debug("Adding " + uneval(data));
- let event = new this._window.DownloadEvent("downloadstart", {
- download:
- this._prepareForContent(createDOMDownloadObject(this._window, data))
- });
- this.__DOM_IMPL__.dispatchEvent(event);
- break;
- }
- },
-
- classID: Components.ID("{c6587afa-0696-469f-9eff-9dac0dd727fe}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver,
- Ci.nsIDOMGlobalPropertyInitializer]),
-
-};
-
-/**
- * Keep track of download objects per window.
- */
-var downloadsCache = {
- init: function() {
- this.cache = new WeakMap();
- },
-
- has: function(aWindow, aId) {
- let downloads = this.cache.get(aWindow);
- return !!(downloads && downloads[aId]);
- },
-
- get: function(aWindow, aDownload) {
- let downloads = this.cache.get(aWindow);
- if (!(downloads && downloads[aDownload.id])) {
- debug("Adding download " + aDownload.id + " to cache.");
- if (!downloads) {
- this.cache.set(aWindow, {});
- downloads = this.cache.get(aWindow);
- }
- // Create the object and add it to the cache.
- let impl = Cc["@mozilla.org/downloads/download;1"]
- .createInstance(Ci.nsISupports);
- impl.wrappedJSObject._init(aWindow, aDownload);
- downloads[aDownload.id] = impl;
- }
- return downloads[aDownload.id];
- },
-
- evict: function(aWindow) {
- this.cache.delete(aWindow);
- }
-};
-
-downloadsCache.init();
-
-/**
- * The DOM facade of a download object.
- */
-
-function createDOMDownloadObject(aWindow, aDownload) {
- return downloadsCache.get(aWindow, aDownload);
-}
-
-function DOMDownloadImpl() {
- debug("DOMDownloadImpl constructor ");
-
- this.wrappedJSObject = this;
- this.totalBytes = 0;
- this.currentBytes = 0;
- this.url = null;
- this.path = null;
- this.storageName = null;
- this.storagePath = null;
- this.contentType = null;
-
- /* fields that require getters/setters */
- this._error = null;
- this._startTime = new Date();
- this._state = "stopped";
-
- /* private fields */
- this.id = null;
-}
-
-DOMDownloadImpl.prototype = {
-
- createPromise: function(aPromiseInit) {
- return new this._window.Promise(aPromiseInit);
- },
-
- pause: function() {
- debug("DOMDownloadImpl pause");
- let id = this.id;
- // We need to wrap the Promise.jsm promise in a "real" DOM promise...
- return this.createPromise(function(aResolve, aReject) {
- DownloadsIPC.pause(id).then(aResolve, aReject);
- });
- },
-
- resume: function() {
- debug("DOMDownloadImpl resume");
- let id = this.id;
- // We need to wrap the Promise.jsm promise in a "real" DOM promise...
- return this.createPromise(function(aResolve, aReject) {
- DownloadsIPC.resume(id).then(aResolve, aReject);
- });
- },
-
- set onstatechange(aHandler) {
- this.__DOM_IMPL__.setEventHandler("onstatechange", aHandler);
- },
-
- get onstatechange() {
- return this.__DOM_IMPL__.getEventHandler("onstatechange");
- },
-
- get error() {
- return this._error;
- },
-
- set error(aError) {
- this._error = aError;
- },
-
- get startTime() {
- return this._startTime;
- },
-
- set startTime(aStartTime) {
- if (aStartTime instanceof Date) {
- this._startTime = aStartTime;
- }
- else {
- this._startTime = new Date(aStartTime);
- }
- },
-
- get state() {
- return this._state;
- },
-
- // We require a setter here to simplify the internals of the Download Manager
- // since we actually pass dummy JSON objects to the child process and update
- // them. This is the case for all other setters for read-only attributes
- // implemented in this object.
- set state(aState) {
- // We need to ensure that XPCOM consumers of this API respect the enum
- // values as well.
- if (["downloading",
- "stopped",
- "succeeded",
- "finalized"].indexOf(aState) != -1) {
- this._state = aState;
- }
- },
-
- /**
- * Initialize a DOMDownload instance for the given window using the
- * 'jsonDownload' serialized format of the download encoded by
- * DownloadsAPI.jsm.
- */
- _init: function(aWindow, aDownload) {
- this._window = aWindow;
- this.id = aDownload.id;
- this._update(aDownload);
- Services.obs.addObserver(this, "downloads-state-change-" + this.id,
- /* ownsWeak */ true);
- debug("observer set for " + this.id);
- },
-
- /**
- * Updates the state of the object and fires the statechange event.
- */
- _update: function(aDownload) {
- debug("update " + uneval(aDownload));
- if (this.id != aDownload.id) {
- return;
- }
-
- let props = ["totalBytes", "currentBytes", "url", "path", "storageName",
- "storagePath", "state", "contentType", "startTime",
- "sourceAppManifestURL"];
- let changed = false;
- let changedProps = {};
-
- props.forEach((prop) => {
- if (prop in aDownload && (aDownload[prop] != this[prop])) {
- this[prop] = aDownload[prop];
- changedProps[prop] = changed = true;
- }
- });
-
- // When the path changes, we should update the storage name and
- // storage path used for our downloaded file in case our download
- // was re-targetted to a different storage and/or filename.
- if (changedProps["path"]) {
- let storages = this._window.navigator.getDeviceStorages("sdcard");
- let preferredStorageName;
- // Use the first one or the default storage. Just like jsdownloads picks
- // the default / preferred download directory.
- storages.forEach((aStorage) => {
- if (aStorage.default || !preferredStorageName) {
- preferredStorageName = aStorage.storageName;
- }
- });
- // Now get the path for this storage area.
- let volume;
- if (preferredStorageName) {
- let volume = volumeService.getVolumeByName(preferredStorageName);
- if (volume) {
- // Finally, create the relative path of the file that can be used
- // later on to retrieve the file via DeviceStorage. Our path
- // needs to omit the starting '/'.
- this.storageName = preferredStorageName;
- this.storagePath =
- this.path.substring(this.path.indexOf(volume.mountPoint) +
- volume.mountPoint.length + 1);
- }
- }
- }
-
- if (aDownload.error) {
- //
- // When we get a generic error failure back from the js downloads api
- // we will verify the status of device storage to see if we can't provide
- // a better error result value.
- //
- // XXX If these checks expand further, consider moving them into their
- // own function.
- //
- let result = aDownload.error.result;
- let storage = this._window.navigator.getDeviceStorage("sdcard");
-
- // If we don't have access to device storage we'll opt out of these
- // extra checks as they are all dependent on the state of the storage.
- if (result == Cr.NS_ERROR_FAILURE && storage) {
- // We will delay sending the notification until we've inferred which
- // error is really happening.
- changed = false;
- debug("Attempting to infer error via device storage sanity checks.");
- // Get device storage and request availability status.
- let available = storage.available();
- available.onsuccess = (function() {
- debug("Storage Status = '" + available.result + "'");
- let inferredError = result;
- switch (available.result) {
- case "unavailable":
- inferredError = Cr.NS_ERROR_FILE_NOT_FOUND;
- break;
- case "shared":
- inferredError = Cr.NS_ERROR_FILE_ACCESS_DENIED;
- break;
- }
- this._updateWithError(aDownload, inferredError);
- }).bind(this);
- available.onerror = (function() {
- this._updateWithError(aDownload, result);
- }).bind(this);
- }
-
- this.error =
- new this._window.DOMError("DownloadError", result);
- } else {
- this.error = null;
- }
-
- // The visible state has not changed, so no need to fire an event.
- if (!changed) {
- return;
- }
-
- this._sendStateChange();
- },
-
- _updateWithError: function(aDownload, aError) {
- this.error =
- new this._window.DOMError("DownloadError", aError);
- this._sendStateChange();
- },
-
- _sendStateChange: function() {
- // __DOM_IMPL__ may not be available at first update.
- if (this.__DOM_IMPL__) {
- let event = new this._window.DownloadEvent("statechange", {
- download: this.__DOM_IMPL__
- });
- debug("Dispatching statechange event. state=" + this.state);
- this.__DOM_IMPL__.dispatchEvent(event);
- }
- },
-
- observe: function(aSubject, aTopic, aData) {
- debug("DOMDownloadImpl observe " + aTopic);
- if (aTopic !== "downloads-state-change-" + this.id) {
- return;
- }
-
- try {
- let download = JSON.parse(aData);
- // We get the start time as milliseconds, not as a Date object.
- if (download.startTime) {
- download.startTime = new Date(download.startTime);
- }
- this._update(download);
- } catch(e) {}
- },
-
- classID: Components.ID("{96b81b99-aa96-439d-8c59-92eeed34705f}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
- Ci.nsIObserver,
- Ci.nsISupportsWeakReference])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMDownloadManagerImpl,
- DOMDownloadImpl]);
diff --git a/dom/downloads/DownloadsAPI.jsm b/dom/downloads/DownloadsAPI.jsm
deleted file mode 100644
index dfb8286fe..000000000
--- a/dom/downloads/DownloadsAPI.jsm
+++ /dev/null
@@ -1,365 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-this.EXPORTED_SYMBOLS = [];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Downloads.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/osfile.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageBroadcaster");
-
-/**
- * Parent process logic that services download API requests from the
- * DownloadAPI.js instances in content processeses. The actual work of managing
- * downloads is done by Toolkit's Downloads.jsm. This module is loaded by B2G's
- * shell.js
- */
-
-function debug(aStr) {
-#ifdef MOZ_DEBUG
- dump("-*- DownloadsAPI.jsm : " + aStr + "\n");
-#endif
-}
-
-function sendPromiseMessage(aMm, aMessageName, aData, aError) {
- debug("sendPromiseMessage " + aMessageName);
- let msg = {
- id: aData.id,
- promiseId: aData.promiseId
- };
-
- if (aError) {
- msg.error = aError;
- }
-
- aMm.sendAsyncMessage(aMessageName, msg);
-}
-
-var DownloadsAPI = {
- init: function() {
- debug("init");
-
- this._ids = new WeakMap(); // Maps toolkit download objects to ids.
- this._index = {}; // Maps ids to downloads.
-
- ["Downloads:GetList",
- "Downloads:ClearAllDone",
- "Downloads:Remove",
- "Downloads:Pause",
- "Downloads:Resume",
- "Downloads:Adopt"].forEach((msgName) => {
- ppmm.addMessageListener(msgName, this);
- });
-
- let self = this;
- Task.spawn(function () {
- let list = yield Downloads.getList(Downloads.ALL);
- yield list.addView(self);
-
- debug("view added to download list.");
- }).then(null, Components.utils.reportError);
-
- this._currentId = 0;
- },
-
- /**
- * Returns a unique id for each download, hashing the url and the path.
- */
- downloadId: function(aDownload) {
- let id = this._ids.get(aDownload, null);
- if (!id) {
- id = "download-" + this._currentId++;
- this._ids.set(aDownload, id);
- this._index[id] = aDownload;
- }
- return id;
- },
-
- getDownloadById: function(aId) {
- return this._index[aId];
- },
-
- /**
- * Converts a download object into a plain json object that we'll
- * send to the DOM side.
- */
- jsonDownload: function(aDownload) {
- let res = {
- totalBytes: aDownload.totalBytes,
- currentBytes: aDownload.currentBytes,
- url: aDownload.source.url,
- path: aDownload.target.path,
- contentType: aDownload.contentType,
- startTime: aDownload.startTime.getTime(),
- sourceAppManifestURL: aDownload._unknownProperties &&
- aDownload._unknownProperties.sourceAppManifestURL
- };
-
- if (aDownload.error) {
- res.error = aDownload.error;
- }
-
- res.id = this.downloadId(aDownload);
-
- // The state of the download. Can be any of "downloading", "stopped",
- // "succeeded", finalized".
-
- // Default to "stopped"
- res.state = "stopped";
- if (!aDownload.stopped &&
- !aDownload.canceled &&
- !aDownload.succeeded &&
- !aDownload.DownloadError) {
- res.state = "downloading";
- } else if (aDownload.succeeded) {
- res.state = "succeeded";
- }
- return res;
- },
-
- /**
- * download view methods.
- */
- onDownloadAdded: function(aDownload) {
- let download = this.jsonDownload(aDownload);
- debug("onDownloadAdded " + uneval(download));
- ppmm.broadcastAsyncMessage("Downloads:Added", download);
- },
-
- onDownloadRemoved: function(aDownload) {
- let download = this.jsonDownload(aDownload);
- download.state = "finalized";
- debug("onDownloadRemoved " + uneval(download));
- ppmm.broadcastAsyncMessage("Downloads:Removed", download);
- this._index[this._ids.get(aDownload)] = null;
- this._ids.delete(aDownload);
- },
-
- onDownloadChanged: function(aDownload) {
- let download = this.jsonDownload(aDownload);
- debug("onDownloadChanged " + uneval(download));
- ppmm.broadcastAsyncMessage("Downloads:Changed", download);
- },
-
- receiveMessage: function(aMessage) {
- if (!aMessage.target.assertPermission("downloads")) {
- debug("No 'downloads' permission!");
- return;
- }
-
- debug("message: " + aMessage.name);
-
- switch (aMessage.name) {
- case "Downloads:GetList":
- this.getList(aMessage.data, aMessage.target);
- break;
- case "Downloads:ClearAllDone":
- this.clearAllDone(aMessage.data, aMessage.target);
- break;
- case "Downloads:Remove":
- this.remove(aMessage.data, aMessage.target);
- break;
- case "Downloads:Pause":
- this.pause(aMessage.data, aMessage.target);
- break;
- case "Downloads:Resume":
- this.resume(aMessage.data, aMessage.target);
- break;
- case "Downloads:Adopt":
- this.adoptDownload(aMessage.data, aMessage.target);
- break;
- default:
- debug("Invalid message: " + aMessage.name);
- }
- },
-
- getList: function(aData, aMm) {
- debug("getList called!");
- let self = this;
- Task.spawn(function () {
- let list = yield Downloads.getList(Downloads.ALL);
- let downloads = yield list.getAll();
- let res = [];
- downloads.forEach((aDownload) => {
- res.push(self.jsonDownload(aDownload));
- });
- aMm.sendAsyncMessage("Downloads:GetList:Return", res);
- }).then(null, Components.utils.reportError);
- },
-
- clearAllDone: function(aData, aMm) {
- debug("clearAllDone called!");
- Task.spawn(function () {
- let list = yield Downloads.getList(Downloads.ALL);
- list.removeFinished();
- }).then(null, Components.utils.reportError);
- },
-
- remove: function(aData, aMm) {
- debug("remove id " + aData.id);
- let download = this.getDownloadById(aData.id);
- if (!download) {
- sendPromiseMessage(aMm, "Downloads:Remove:Return",
- aData, "NoSuchDownload");
- return;
- }
-
- Task.spawn(function() {
- yield download.finalize(true);
- let list = yield Downloads.getList(Downloads.ALL);
- yield list.remove(download);
- }).then(
- function() {
- sendPromiseMessage(aMm, "Downloads:Remove:Return", aData);
- },
- function() {
- sendPromiseMessage(aMm, "Downloads:Remove:Return",
- aData, "RemoveError");
- }
- );
- },
-
- pause: function(aData, aMm) {
- debug("pause id " + aData.id);
- let download = this.getDownloadById(aData.id);
- if (!download) {
- sendPromiseMessage(aMm, "Downloads:Pause:Return",
- aData, "NoSuchDownload");
- return;
- }
-
- download.cancel().then(
- function() {
- sendPromiseMessage(aMm, "Downloads:Pause:Return", aData);
- },
- function() {
- sendPromiseMessage(aMm, "Downloads:Pause:Return",
- aData, "PauseError");
- }
- );
- },
-
- resume: function(aData, aMm) {
- debug("resume id " + aData.id);
- let download = this.getDownloadById(aData.id);
- if (!download) {
- sendPromiseMessage(aMm, "Downloads:Resume:Return",
- aData, "NoSuchDownload");
- return;
- }
-
- download.start().then(
- function() {
- sendPromiseMessage(aMm, "Downloads:Resume:Return", aData);
- },
- function() {
- sendPromiseMessage(aMm, "Downloads:Resume:Return",
- aData, "ResumeError");
- }
- );
- },
-
- /**
- * Receive a download to adopt in the same representation we produce from
- * our "jsonDownload" normalizer and add it to the list of downloads.
- */
- adoptDownload: function(aData, aMm) {
- let adoptJsonRep = aData.jsonDownload;
- debug("adoptDownload " + uneval(adoptJsonRep));
-
- Task.spawn(function* () {
- // Verify that the file exists on disk. This will result in a rejection
- // if the file does not exist. We will also use this information for the
- // file size to avoid weird inconsistencies. We ignore the filesystem
- // timestamp in favor of whatever the caller is telling us.
- let fileInfo = yield OS.File.stat(adoptJsonRep.path);
-
- // We also require that the file is not a directory.
- if (fileInfo.isDir) {
- throw new Error("AdoptFileIsDirectory");
- }
-
- // We need to create a Download instance to add to the list. Create a
- // serialized representation and then from there the instance.
- let serializedRep = {
- // explicit initializations in toSerializable
- source: {
- url: adoptJsonRep.url
- // This is where isPrivate would go if adoption supported private
- // browsing.
- },
- target: {
- path: adoptJsonRep.path,
- },
- startTime: adoptJsonRep.startTime,
- // kPlainSerializableDownloadProperties propagations
- succeeded: true, // (all adopted downloads are required to be completed)
- totalBytes: fileInfo.size,
- contentType: adoptJsonRep.contentType,
- // unknown properties added/used by the DownloadsAPI
- currentBytes: fileInfo.size,
- sourceAppManifestURL: adoptJsonRep.sourceAppManifestURL
- };
-
- let download = yield Downloads.createDownload(serializedRep);
-
- // The ALL list is a DownloadCombinedList instance that combines the
- // PUBLIC (persisted to disk) and PRIVATE (ephemeral) download lists..
- // When we call add on it, it dispatches to the appropriate list based on
- // the 'isPrivate' field of the source. (Which we don't initialize and
- // defaults to false.)
- let allDownloadList = yield Downloads.getList(Downloads.ALL);
-
- // This add will automatically notify all views of the added download,
- // including DownloadsAPI instances and the DownloadAutoSaveView that's
- // subscribed to the PUBLIC list and will save the download.
- yield allDownloadList.add(download);
-
- debug("download adopted");
- // The notification above occurred synchronously, and so we will have
- // already dispatched an added notification for our download to the child
- // process in question. As such, we only need to relay the download id
- // since the download will already have been cached.
- return download;
- }.bind(this)).then(
- (download) => {
- sendPromiseMessage(aMm, "Downloads:Adopt:Return",
- {
- id: this.downloadId(download),
- promiseId: aData.promiseId
- });
- },
- (ex) => {
- let reportAs = "AdoptError";
- // Provide better error codes for expected errors.
- if (ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
- reportAs = "AdoptNoSuchFile";
- } else if (ex.message === "AdoptFileIsDirectory") {
- reportAs = ex.message;
- } else {
- // Anything else is unexpected and should be reported to help track
- // down what's going wrong.
- debug("unexpected download error: " + ex);
- Cu.reportError(ex);
- }
- sendPromiseMessage(aMm, "Downloads:Adopt:Return",
- {
- promiseId: aData.promiseId
- },
- reportAs);
- });
- }
-};
-
-DownloadsAPI.init();
diff --git a/dom/downloads/DownloadsAPI.manifest b/dom/downloads/DownloadsAPI.manifest
deleted file mode 100644
index 8d6dc9396..000000000
--- a/dom/downloads/DownloadsAPI.manifest
+++ /dev/null
@@ -1,6 +0,0 @@
-# DownloadsAPI.js
-component {c6587afa-0696-469f-9eff-9dac0dd727fe} DownloadsAPI.js
-contract @mozilla.org/downloads/manager;1 {c6587afa-0696-469f-9eff-9dac0dd727fe}
-
-component {96b81b99-aa96-439d-8c59-92eeed34705f} DownloadsAPI.js
-contract @mozilla.org/downloads/download;1 {96b81b99-aa96-439d-8c59-92eeed34705f}
diff --git a/dom/downloads/DownloadsIPC.jsm b/dom/downloads/DownloadsIPC.jsm
deleted file mode 100644
index 0e290abf4..000000000
--- a/dom/downloads/DownloadsIPC.jsm
+++ /dev/null
@@ -1,224 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-this.EXPORTED_SYMBOLS = ["DownloadsIPC"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsIMessageSender");
-
-/**
- * This module lives in the child process and receives the ipc messages
- * from the parent. It saves the download's state and redispatch changes
- * to DOM objects using an observer notification.
- *
- * This module needs to be loaded once and only once per process.
- */
-
-function debug(aStr) {
-#ifdef MOZ_DEBUG
- dump("-*- DownloadsIPC.jsm : " + aStr + "\n");
-#endif
-}
-
-const ipcMessages = ["Downloads:Added",
- "Downloads:Removed",
- "Downloads:Changed",
- "Downloads:GetList:Return",
- "Downloads:Remove:Return",
- "Downloads:Pause:Return",
- "Downloads:Resume:Return",
- "Downloads:Adopt:Return"];
-
-this.DownloadsIPC = {
- downloads: {},
-
- init: function() {
- debug("init");
- Services.obs.addObserver(this, "xpcom-shutdown", false);
- ipcMessages.forEach((aMessage) => {
- cpmm.addMessageListener(aMessage, this);
- });
-
- // We need to get the list of current downloads.
- this.ready = false;
- this.getListPromises = [];
- this.downloadPromises = {};
- cpmm.sendAsyncMessage("Downloads:GetList", {});
- this._promiseId = 0;
- },
-
- notifyChanges: function(aId) {
- // TODO: use the subject instead of stringifying.
- if (this.downloads[aId]) {
- debug("notifyChanges notifying changes for " + aId);
- Services.obs.notifyObservers(null, "downloads-state-change-" + aId,
- JSON.stringify(this.downloads[aId]));
- } else {
- debug("notifyChanges failed for " + aId)
- }
- },
-
- _updateDownloadsArray: function(aDownloads) {
- this.downloads = [];
- // We actually have an array of downloads.
- aDownloads.forEach((aDownload) => {
- this.downloads[aDownload.id] = aDownload;
- });
- },
-
- receiveMessage: function(aMessage) {
- let download = aMessage.data;
- debug("message: " + aMessage.name);
- switch(aMessage.name) {
- case "Downloads:GetList:Return":
- this._updateDownloadsArray(download);
-
- if (!this.ready) {
- this.getListPromises.forEach(aPromise =>
- aPromise.resolve(this.downloads));
- this.getListPromises.length = 0;
- }
- this.ready = true;
- break;
- case "Downloads:Added":
- this.downloads[download.id] = download;
- this.notifyChanges(download.id);
- break;
- case "Downloads:Removed":
- if (this.downloads[download.id]) {
- this.downloads[download.id] = download;
- this.notifyChanges(download.id);
- delete this.downloads[download.id];
- }
- break;
- case "Downloads:Changed":
- // Only update properties that actually changed.
- let cached = this.downloads[download.id];
- if (!cached) {
- debug("No download found for " + download.id);
- return;
- }
- let props = ["totalBytes", "currentBytes", "url", "path", "state",
- "contentType", "startTime"];
- let changed = false;
-
- props.forEach((aProp) => {
- if (download[aProp] && (download[aProp] != cached[aProp])) {
- cached[aProp] = download[aProp];
- changed = true;
- }
- });
-
- // Updating the error property. We always get a 'state' change as
- // well.
- cached.error = download.error;
-
- if (changed) {
- this.notifyChanges(download.id);
- }
- break;
- case "Downloads:Remove:Return":
- case "Downloads:Pause:Return":
- case "Downloads:Resume:Return":
- case "Downloads:Adopt:Return":
- if (this.downloadPromises[download.promiseId]) {
- if (!download.error) {
- this.downloadPromises[download.promiseId].resolve(download);
- } else {
- this.downloadPromises[download.promiseId].reject(download);
- }
- delete this.downloadPromises[download.promiseId];
- }
- break;
- }
- },
-
- /**
- * Returns a promise that is resolved with the list of current downloads.
- */
- getDownloads: function() {
- debug("getDownloads()");
- let deferred = Promise.defer();
- if (this.ready) {
- debug("Returning existing list.");
- deferred.resolve(this.downloads);
- } else {
- this.getListPromises.push(deferred);
- }
- return deferred.promise;
- },
-
- /**
- * Void function to trigger removal of completed downloads.
- */
- clearAllDone: function() {
- debug("clearAllDone");
- cpmm.sendAsyncMessage("Downloads:ClearAllDone", {});
- },
-
- promiseId: function() {
- return this._promiseId++;
- },
-
- remove: function(aId) {
- debug("remove " + aId);
- let deferred = Promise.defer();
- let pId = this.promiseId();
- this.downloadPromises[pId] = deferred;
- cpmm.sendAsyncMessage("Downloads:Remove",
- { id: aId, promiseId: pId });
- return deferred.promise;
- },
-
- pause: function(aId) {
- debug("pause " + aId);
- let deferred = Promise.defer();
- let pId = this.promiseId();
- this.downloadPromises[pId] = deferred;
- cpmm.sendAsyncMessage("Downloads:Pause",
- { id: aId, promiseId: pId });
- return deferred.promise;
- },
-
- resume: function(aId) {
- debug("resume " + aId);
- let deferred = Promise.defer();
- let pId = this.promiseId();
- this.downloadPromises[pId] = deferred;
- cpmm.sendAsyncMessage("Downloads:Resume",
- { id: aId, promiseId: pId });
- return deferred.promise;
- },
-
- adoptDownload: function(aJsonDownload) {
- debug("adoptDownload");
- let deferred = Promise.defer();
- let pId = this.promiseId();
- this.downloadPromises[pId] = deferred;
- cpmm.sendAsyncMessage("Downloads:Adopt",
- { jsonDownload: aJsonDownload, promiseId: pId });
- return deferred.promise;
- },
-
- observe: function(aSubject, aTopic, aData) {
- if (aTopic == "xpcom-shutdown") {
- ipcMessages.forEach((aMessage) => {
- cpmm.removeMessageListener(aMessage, this);
- });
- }
- }
-};
-
-DownloadsIPC.init();
diff --git a/dom/downloads/moz.build b/dom/downloads/moz.build
deleted file mode 100644
index 07bda1c4f..000000000
--- a/dom/downloads/moz.build
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-if CONFIG["MOZ_B2G"]:
- MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
-
-EXTRA_COMPONENTS += [
- 'DownloadsAPI.manifest',
-]
-
-EXTRA_PP_COMPONENTS += [
- 'DownloadsAPI.js',
-]
-
-EXTRA_PP_JS_MODULES += [
- 'DownloadsAPI.jsm',
- 'DownloadsIPC.jsm',
-]
diff --git a/dom/downloads/tests/clear_all_done_helper.js b/dom/downloads/tests/clear_all_done_helper.js
deleted file mode 100644
index 62fa1a2f3..000000000
--- a/dom/downloads/tests/clear_all_done_helper.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * A helper to clear out the existing downloads known to the mozDownloadManager
- * / downloads.js.
- *
- * It exists because previously mozDownloadManager.clearAllDone() thought that
- * when it returned that all the completed downloads would be cleared out. It
- * was wrong and this led to various intermittent test failurse. In discussion
- * on https://bugzil.la/979446#c13 and onwards, it was decided that
- * clearAllDone() was in the wrong and that the jsdownloads API it depends on
- * was not going to change to make it be in the right.
- *
- * The existing uses of clearAllDone() in tests seemed to be about:
- * - Exploding if there was somehow still a download in progress
- * - Clearing out the download list at the start of a test so that calls to
- * getDownloads() wouldn't have to worry about existing downloads, etc.
- *
- * From discussion, the right way to handle clearing is to wait for the expected
- * removal events to occur for the existing downloads. So that's what we do.
- * We still generate a test failure if there are any in-progress downloads.
- *
- * @param {Boolean} [getDownloads=false]
- * If true, invoke getDownloads after clearing the download list and return
- * its value.
- */
-function clearAllDoneHelper(getDownloads) {
- var clearedPromise = new Promise(function(resolve, reject) {
- function gotDownloads(downloads) {
- // If there are no downloads, we're already done.
- if (downloads.length === 0) {
- resolve();
- return;
- }
-
- // Track the set of expected downloads that will be finalized.
- var expectedIds = new Set();
- function changeHandler(evt) {
- var download = evt.download;
- if (download.state === "finalized") {
- expectedIds.delete(download.id);
- if (expectedIds.size === 0) {
- resolve();
- }
- }
- }
- downloads.forEach(function(download) {
- if (download.state === "downloading") {
- ok(false, "A download is still active: " + download.path);
- reject("Active download");
- }
- download.onstatechange = changeHandler;
- expectedIds.add(download.id);
- });
- navigator.mozDownloadManager.clearAllDone();
- }
- function gotBadNews(err) {
- ok(false, "Problem clearing all downloads: " + err);
- reject(err);
- }
- navigator.mozDownloadManager.getDownloads().then(gotDownloads, gotBadNews);
- });
- if (!getDownloads) {
- return clearedPromise;
- }
- return clearedPromise.then(function() {
- return navigator.mozDownloadManager.getDownloads();
- });
-}
diff --git a/dom/downloads/tests/mochitest.ini b/dom/downloads/tests/mochitest.ini
deleted file mode 100644
index e13e4d887..000000000
--- a/dom/downloads/tests/mochitest.ini
+++ /dev/null
@@ -1,15 +0,0 @@
-[DEFAULT]
-# The actual requirement for mozDownloadManager is MOZ_GONK because of
-# the nsIVolumeService dependency. Until https://bugzil.la/1130264 is
-# addressed, there is no way for mulet to run these tests.
-run-if = toolkit == 'gonk'
-support-files =
- serve_file.sjs
- clear_all_done_helper.js
-
-[test_downloads_navigator_object.html]
-[test_downloads_basic.html]
-[test_downloads_large.html]
-[test_downloads_bad_file.html]
-[test_downloads_pause_remove.html]
-[test_downloads_pause_resume.html]
diff --git a/dom/downloads/tests/serve_file.sjs b/dom/downloads/tests/serve_file.sjs
deleted file mode 100644
index d0171d7ca..000000000
--- a/dom/downloads/tests/serve_file.sjs
+++ /dev/null
@@ -1,170 +0,0 @@
-// Serves a file with a given mime type and size at an optionally given rate.
-
-function getQuery(request) {
- var query = {};
- request.queryString.split('&').forEach(function (val) {
- var [name, value] = val.split('=');
- query[name] = unescape(value);
- });
- return query;
-}
-
-function handleResponse() {
- // Is this a rate limited response?
- if (this.state.rate > 0) {
- // Calculate how many bytes we have left to send.
- var bytesToWrite = this.state.totalBytes - this.state.sentBytes;
-
- // Do we have any bytes left to send? If not we'll just fall thru and
- // cancel our repeating timer and finalize the response.
- if (bytesToWrite > 0) {
- // Figure out how many bytes to send, based on the rate limit.
- bytesToWrite =
- (bytesToWrite > this.state.rate) ? this.state.rate : bytesToWrite;
-
- for (let i = 0; i < bytesToWrite; i++) {
- try {
- this.response.bodyOutputStream.write("0", 1);
- } catch (e) {
- // Connection was closed by client.
- if (e == Components.results.NS_ERROR_NOT_AVAILABLE) {
- // There's no harm in calling this multiple times.
- this.response.finish();
-
- // It's possible that our timer wasn't cancelled in time
- // and we'll be called again.
- if (this.timer) {
- this.timer.cancel();
- this.timer = null;
- }
-
- return;
- }
- }
- }
-
- // Update the number of bytes we've sent to the client.
- this.state.sentBytes += bytesToWrite;
-
- // Wait until the next call to do anything else.
- return;
- }
- }
- else {
- // Not rate limited, write it all out.
- for (let i = 0; i < this.state.totalBytes; i++) {
- this.response.write("0");
- }
- }
-
- // Finalize the response.
- this.response.finish();
-
- // All done sending, go ahead and cancel our repeating timer.
- this.timer.cancel();
-
- // Clear the timer.
- this.timer = null;
-}
-
-function handleRequest(request, response) {
- var query = getQuery(request);
-
- // sending at a specific rate requires our response to be asynchronous so
- // we handle all requests asynchronously. See handleResponse().
- response.processAsync();
-
- // Default status when responding.
- var version = "1.1";
- var statusCode = 200;
- var description = "OK";
-
- // Default values for content type, size and rate.
- var contentType = "text/plain";
- var contentRange = null;
- var size = 1024;
- var rate = 0;
-
- // optional content type to be used by our response.
- if ("contentType" in query) {
- contentType = query["contentType"];
- }
-
- // optional size (in bytes) for generated file.
- if ("size" in query) {
- size = parseInt(query["size"]);
- }
-
- // optional range request check.
- if (request.hasHeader("range")) {
- version = "1.1";
- statusCode = 206;
- description = "Partial Content";
-
- // We'll only support simple range byte style requests.
- var [offset, total] = request.getHeader("range").slice("bytes=".length).split("-");
- // Enforce valid Number values.
- offset = parseInt(offset);
- offset = isNaN(offset) ? 0 : offset;
- // Same.
- total = parseInt(total);
- total = isNaN(total) ? 0 : total;
-
- // We'll need to original total size as part of the Content-Range header
- // value in our response.
- var originalSize = size;
-
- // If we have a total size requested, we must make sure to send that number
- // of bytes only (minus the start offset).
- if (total && total < size) {
- size = total - offset;
- } else if (offset) {
- // Looks like we just have a byte offset to deal with.
- size = size - offset;
- }
-
- // We specifically need to add a Content-Range header to all responses for
- // requests that include a range request header.
- contentRange = "bytes " + offset + "-" + (size - 1) + "/" + originalSize;
- }
-
- // optional rate (in bytes/s) at which to send the file.
- if ("rate" in query) {
- rate = parseInt(query["rate"]);
- }
-
- // The context for the responseHandler.
- var context = {
- response: response,
- state: {
- contentType: contentType,
- totalBytes: size,
- sentBytes: 0,
- rate: rate
- },
- timer: null
- };
-
- // The notify implementation for the timer.
- context.notify = handleResponse.bind(context);
-
- context.timer =
- Components.classes["@mozilla.org/timer;1"]
- .createInstance(Components.interfaces.nsITimer);
-
- // generate the content.
- response.setStatusLine(version, statusCode, description);
- response.setHeader("Content-Type", contentType, false);
- if (contentRange) {
- response.setHeader("Content-Range", contentRange, false);
- }
- response.setHeader("Content-Length", size.toString(), false);
-
- // initialize the timer and start writing out the response.
- context.timer.initWithCallback(
- context,
- 1000,
- Components.interfaces.nsITimer.TYPE_REPEATING_SLACK
- );
-
-}
diff --git a/dom/downloads/tests/test_downloads_bad_file.html b/dom/downloads/tests/test_downloads_bad_file.html
deleted file mode 100644
index a2b3992e6..000000000
--- a/dom/downloads/tests/test_downloads_bad_file.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=960749
--->
-<head>
- <title>Test for Bug 960749 Downloads API</title>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=960749">Mozilla Bug 960749</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=1024" download=".&lt;.EVIL.&gt;\ / : * ? &quot; |file.bin" id="download1">Download #1</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing a simple download, waiting for it to be done.
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-var expected = "_.EVIL.__ _ _ _ _ _ _file.bin";
-
-function next() {
- index += 1;
- if (index >= steps.length) {
- ok(false, "Shouldn't get here!");
- return;
- }
- try {
- steps[index]();
- } catch(ex) {
- ok(false, "Caught exception", ex);
- }
-}
-
-function checkTargetFilename(download) {
- ok(download.path.endsWith(expected),
- "Download path leaf name '" + download.path +
- "' should match '" + expected + "' filename.");
-
- SimpleTest.finish();
-}
-
-function downloadChange(evt) {
- var download = evt.download;
-
- if (download.state === "succeeded") {
- checkTargetFilename(download);
- }
-}
-
-function downloadStart(evt) {
- var download = evt.download;
- download.onstatechange = downloadChange;
-}
-
-var steps = [
- // Start by setting the pref to true.
- function() {
- SpecialPowers.pushPrefEnv({
- set: [["dom.mozDownloads.enabled", true]]
- }, next);
- },
-
- // Setup the event listeners.
- function() {
- SpecialPowers.pushPermissions([
- {type: "downloads", allow: true, context: document}
- ], function() {
- navigator.mozDownloadManager.ondownloadstart = downloadStart;
- next();
- });
- },
-
- // Click on the <a download> to start the download.
- function() {
- document.getElementById("download1").click();
- }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
-
diff --git a/dom/downloads/tests/test_downloads_basic.html b/dom/downloads/tests/test_downloads_basic.html
deleted file mode 100644
index 051a1faa1..000000000
--- a/dom/downloads/tests/test_downloads_basic.html
+++ /dev/null
@@ -1,128 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
- <title>Test for Bug 938023 Downloads API</title>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=1024" download="test.bin" id="download1">Download #1</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing a simple download, waiting for it to be done.
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-var todayDate = new Date();
-var baseServeURL = "http://mochi.test:8888/tests/dom/downloads/tests/";
-var lastKnownCurrentBytes = 0;
-
-function next() {
- index += 1;
- if (index >= steps.length) {
- ok(false, "Shouldn't get here!");
- return;
- }
- try {
- steps[index]();
- } catch(ex) {
- ok(false, "Caught exception", ex);
- }
-}
-
-function checkConsistentDownloadAttributes(download) {
- var href = document.getElementById("download1").getAttribute("href");
- var expectedServeURL = baseServeURL + href;
- var destinationRegEx = /test\(?[0-9]*\)?\.bin$/;
-
- // bug 945323: Download path isn't honoring download attribute
- ok(destinationRegEx.test(download.path),
- "Download path '" + download.path +
- "' should match '" + destinationRegEx + "' regexp.");
-
- ok(download.startTime >= todayDate,
- "Download start time should be greater than or equal to today");
-
- is(download.error, null, "Download does not have an error");
-
- is(download.url, expectedServeURL,
- "Download URL = " + expectedServeURL);
- ok(download.id !== null, "Download id is defined");
- is(download.contentType, "application/octet-stream",
- "Download content type is application/octet-stream");
-}
-
-function downloadChange(evt) {
- var download = evt.download;
- checkConsistentDownloadAttributes(download);
- is(download.totalBytes, 1024, "Download total size is 1024 bytes");
-
- if (download.state === "succeeded") {
- is(download.currentBytes, 1024, "Download current size is 1024 bytes");
- SimpleTest.finish();
- } else if (download.state === "downloading") {
- // Note that this case may or may not trigger, depending on whether the
- // download is initially reported with 0 bytes (we should happen) or with
- // 1024 bytes (we should not happen). If we do happen, an additional 8
- // TEST-PASS events should be logged.
- ok(download.currentBytes > lastKnownCurrentBytes,
- "Download current size is larger than last download change event");
- lastKnownCurrentBytes = download.currentBytes;
- } else {
- ok(false, "Unexpected download state = " + download.state);
- }
-}
-
-function downloadStart(evt) {
- var download = evt.download;
- checkConsistentDownloadAttributes(download);
-
- // We used to check that the currentBytes was 0. This was incorrect. It
- // is very common to first hear about the download already at 1024 bytes.
- is(download.state, "downloading", "Download state is downloading");
-
- download.onstatechange = downloadChange;
-}
-
-var steps = [
- // Start by setting the pref to true.
- function() {
- SpecialPowers.pushPrefEnv({
- set: [["dom.mozDownloads.enabled", true]]
- }, next);
- },
-
- // Setup the event listeners.
- function() {
- SpecialPowers.pushPermissions([
- {type: "downloads", allow: true, context: document}
- ], function() {
- navigator.mozDownloadManager.ondownloadstart = downloadStart;
- next();
- });
- },
-
- // Click on the <a download> to start the download.
- function() {
- document.getElementById("download1").click();
- }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
-
diff --git a/dom/downloads/tests/test_downloads_large.html b/dom/downloads/tests/test_downloads_large.html
deleted file mode 100644
index 9f7f73c19..000000000
--- a/dom/downloads/tests/test_downloads_large.html
+++ /dev/null
@@ -1,110 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
- <title>Test for Bug 938023 Downloads API</title>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="clear_all_done_helper.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=102400" download="test.bin" id="download1">Large Download</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing downloading a file, then checking getDownloads() and clearAllDone().
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next(args) {
- index += 1;
- if (index >= steps.length) {
- ok(false, "Shouldn't get here!");
- return;
- }
- try {
- steps[index](args);
- } catch(ex) {
- ok(false, "Caught exception", ex);
- }
-}
-
-// Catch all error function.
-function error() {
- ok(false, "API failure");
- SimpleTest.finish();
-}
-
-function getDownloads(downloads) {
- ok(downloads.length == 1, "One downloads after getDownloads");
- clearAllDoneHelper(true).then(clearAllDone, error);
-}
-
-function clearAllDone(downloads) {
- ok(downloads.length == 0, "No downloads after clearAllDone");
- SimpleTest.finish();
-}
-
-function downloadChange(evt) {
- var download = evt.download;
-
- if (download.state == "succeeded") {
- ok(download.totalBytes == 102400, "Download size is 100k bytes.");
- navigator.mozDownloadManager.getDownloads().then(getDownloads, error);
- }
-}
-
-var steps = [
- // Start by setting the pref to true.
- function() {
- SpecialPowers.pushPrefEnv({
- set: [["dom.mozDownloads.enabled", true]]
- }, next);
- },
-
- // Setup permission and clear current list.
- function() {
- SpecialPowers.pushPermissions([
- {type: "downloads", allow: true, context: document}
- ], function() {
- clearAllDoneHelper(true).then(next, error);
- });
- },
-
- function(downloads) {
- ok(downloads.length == 0, "Start with an empty download list.");
- next();
- },
-
- // Setup the event listeners.
- function() {
- navigator.mozDownloadManager.ondownloadstart =
- function(evt) {
- ok(true, "Download started");
- evt.download.addEventListener("statechange", downloadChange);
- }
- next();
- },
-
- // Click on the <a download> to start the download.
- function() {
- document.getElementById("download1").click();
- }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/downloads/tests/test_downloads_navigator_object.html b/dom/downloads/tests/test_downloads_navigator_object.html
deleted file mode 100644
index 1c38388b7..000000000
--- a/dom/downloads/tests/test_downloads_navigator_object.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
- <title>Test for Bug 938023 Downloads API</title>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-<iframe></iframe>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next() {
- index += 1;
- if (index >= steps.length) {
- ok(false, "Shouldn't get here!");
- return;
- }
- try {
- steps[index]();
- } catch(ex) {
- ok(false, "Caught exception", ex);
- }
-}
-
-var steps = [
- // Start by setting the pref to true.
- function() {
- SpecialPowers.pushPrefEnv({
- set: [["dom.mozDownloads.enabled", true]]
- }, next);
- },
-
- function() {
- SpecialPowers.pushPermissions([
- {type: "downloads", allow: 0, context: document}
- ], function() {
- is(frames[0].navigator.mozDownloadManager, null, "navigator.mozDownloadManager is null when the page doesn't have permissions");
- next();
- });
- },
-
- function() {
- SpecialPowers.pushPrefEnv({
- set: [["dom.mozDownloads.enabled", false]]
- }, function() {
- is(navigator.mozDownloadManager, undefined, "navigator.mozDownloadManager is undefined");
- next();
- });
- },
-
- function() {
- SimpleTest.finish();
- }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/downloads/tests/test_downloads_pause_remove.html b/dom/downloads/tests/test_downloads_pause_remove.html
deleted file mode 100644
index 3b410a667..000000000
--- a/dom/downloads/tests/test_downloads_pause_remove.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
- <title>Test for Bug 938023 Downloads API</title>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="clear_all_done_helper.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=102400&rate=1024" download="test.bin" id="download1">Large Download</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing pausing a download and then removing it.
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next(args) {
- index += 1;
- if (index >= steps.length) {
- ok(false, "Shouldn't get here!");
- return;
- }
- try {
- steps[index](args);
- } catch(ex) {
- ok(false, "Caught exception", ex);
- }
-}
-
-var pausing = false;
-
-// Catch all error function.
-function error() {
- ok(false, "API failure");
- SimpleTest.finish();
-}
-
-function checkDownloadList(downloads) {
- ok(downloads.length == 0, "No downloads left");
- SimpleTest.finish();
-}
-
-function checkRemoved(download) {
- ok(download.state == "finalized", "Download removed.");
- navigator.mozDownloadManager.getDownloads()
- .then(checkDownloadList, error);
-}
-
-function downloadChange(evt) {
- var download = evt.download;
-
- if (download.state == "downloading" && !pausing) {
- pausing = true;
- download.pause();
- } else if (download.state == "stopped") {
- ok(pausing, "Download stopped by pause()");
- navigator.mozDownloadManager.remove(download)
- .then(checkRemoved, error);
- }
-}
-
-var steps = [
- // Start by setting the pref to true.
- function() {
- SpecialPowers.pushPrefEnv({
- set: [["dom.mozDownloads.enabled", true]]
- }, next);
- },
-
- // Setup permission and clear current list.
- function() {
- SpecialPowers.pushPermissions([
- {type: "downloads", allow: true, context: document}
- ], function() {
- clearAllDoneHelper(true).then(next, error);
- });
- },
-
- function(downloads) {
- ok(downloads.length == 0, "Start with an empty download list.");
- next();
- },
-
- // Setup the event listeners.
- function() {
- navigator.mozDownloadManager.ondownloadstart =
- function(evt) {
- ok(true, "Download started");
- evt.download.addEventListener("statechange", downloadChange);
- }
- next();
- },
-
- // Click on the <a download> to start the download.
- function() {
- document.getElementById("download1").click();
- }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/downloads/tests/test_downloads_pause_resume.html b/dom/downloads/tests/test_downloads_pause_resume.html
deleted file mode 100644
index 76e249e5a..000000000
--- a/dom/downloads/tests/test_downloads_pause_resume.html
+++ /dev/null
@@ -1,121 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
- <title>Test for Bug 938023 Downloads API</title>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="clear_all_done_helper.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=102400&rate=1024" download="test.bin" id="download1">Large Download</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing pausing a download and then resuming it.
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next(args) {
- index += 1;
- if (index >= steps.length) {
- ok(false, "Shouldn't get here!");
- return;
- }
- try {
- steps[index](args);
- } catch(ex) {
- ok(false, "Caught exception", ex);
- }
-}
-
-var pausing = false;
-var resuming = false;
-
-// Catch all error function.
-function error() {
- ok(false, "API failure");
- SimpleTest.finish();
-}
-
-function checkDownloadList(downloads) {
- ok(downloads.length == 0, "No downloads left");
- SimpleTest.finish();
-}
-
-function checkResumeSucceeded(download) {
- ok(download.state == "succeeded", "Download resumed successfully.");
- clearAllDoneHelper(true).then(checkDownloadList, error);
-}
-
-function downloadChange(evt) {
- var download = evt.download;
-
- info("got download event, state: " + download.state +
- " current bytes: " + download.currentBytes +
- " pausing?: " + pausing + " resuming?: " + resuming);
- if (download.state == "downloading" && !pausing) {
- pausing = true;
- download.pause();
- } else if (download.state == "stopped" && !resuming) {
- resuming = true;
- ok(pausing, "Download stopped by pause()");
- download.resume()
- .then(function() { checkResumeSucceeded(download); }, error);
- }
-}
-
-var steps = [
- // Start by setting the pref to true.
- function() {
- SpecialPowers.pushPrefEnv({
- set: [["dom.mozDownloads.enabled", true]]
- }, next);
- },
-
- // Setup permission and clear current list.
- function() {
- SpecialPowers.pushPermissions([
- {type: "downloads", allow: true, context: document}
- ], function() {
- clearAllDoneHelper(true).then(next, error);
- });
- },
-
- function(downloads) {
- ok(downloads.length == 0, "Start with an empty download list.");
- next();
- },
-
- // Setup the event listeners.
- function() {
- navigator.mozDownloadManager.ondownloadstart =
- function(evt) {
- ok(true, "Download started");
- evt.download.addEventListener("statechange", downloadChange);
- }
- next();
- },
-
- // Click on the <a download> to start the download.
- function() {
- document.getElementById("download1").click();
- }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/encoding/FallbackEncoding.cpp b/dom/encoding/FallbackEncoding.cpp
index 93fe0f8cb..29411412e 100644
--- a/dom/encoding/FallbackEncoding.cpp
+++ b/dom/encoding/FallbackEncoding.cpp
@@ -55,8 +55,7 @@ FallbackEncoding::Get(nsACString& aFallback)
// Don't let the user break things by setting the override to unreasonable
// values via about:config
if (!EncodingUtils::FindEncodingForLabel(override, mFallback) ||
- !EncodingUtils::IsAsciiCompatible(mFallback) ||
- mFallback.EqualsLiteral("UTF-8")) {
+ !EncodingUtils::IsAsciiCompatible(mFallback)) {
mFallback.Truncate();
}
diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp
index 2546a81ad..f33bfa5a8 100755
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -280,16 +280,10 @@ Event::GetType(nsAString& aType)
return NS_OK;
}
-static EventTarget*
-GetDOMEventTarget(nsIDOMEventTarget* aTarget)
-{
- return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
-}
-
EventTarget*
Event::GetTarget() const
{
- return GetDOMEventTarget(mEvent->mTarget);
+ return mEvent->GetDOMEventTarget();
}
NS_IMETHODIMP
@@ -302,7 +296,7 @@ Event::GetTarget(nsIDOMEventTarget** aTarget)
EventTarget*
Event::GetCurrentTarget() const
{
- return GetDOMEventTarget(mEvent->mCurrentTarget);
+ return mEvent->GetCurrentDOMEventTarget();
}
NS_IMETHODIMP
@@ -349,11 +343,7 @@ Event::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget)
EventTarget*
Event::GetOriginalTarget() const
{
- if (mEvent->mOriginalTarget) {
- return GetDOMEventTarget(mEvent->mOriginalTarget);
- }
-
- return GetTarget();
+ return mEvent->GetOriginalDOMEventTarget();
}
NS_IMETHODIMP
@@ -855,6 +845,25 @@ Event::GetEventPopupControlState(WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent)
}
}
break;
+ case ePointerEventClass:
+ if (aEvent->IsTrusted() &&
+ aEvent->AsPointerEvent()->button == WidgetMouseEvent::eLeftButton) {
+ switch(aEvent->mMessage) {
+ case ePointerUp:
+ if (PopupAllowedForEvent("pointerup")) {
+ abuse = openControlled;
+ }
+ break;
+ case ePointerDown:
+ if (PopupAllowedForEvent("pointerdown")) {
+ abuse = openControlled;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
case eFormEventClass:
// For these following events only allow popups if they're
// triggered while handling user input. See
@@ -1127,16 +1136,11 @@ Event::TimeStampImpl() const
return perf->GetDOMTiming()->TimeStampToDOMHighRes(mEvent->mTimeStamp);
}
- // For dedicated workers, we should make times relative to the navigation
- // start of the document that created the worker, which is the same as the
- // timebase for performance.now().
workers::WorkerPrivate* workerPrivate =
workers::GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
- TimeDuration duration =
- mEvent->mTimeStamp - workerPrivate->NowBaseTimeStamp();
- return duration.ToMilliseconds();
+ return workerPrivate->TimeStampToDOMHighRes(mEvent->mTimeStamp);
}
bool
diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp
index a1d0675ae..65f01844b 100644
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -1056,6 +1056,11 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
LOG_EVENT_CREATION(STORAGEEVENT);
return NS_NewDOMStorageEvent(aOwner);
}
+ if (aEventType.LowerCaseEqualsLiteral("focusevent")) {
+ RefPtr<Event> event = NS_NewDOMFocusEvent(aOwner, aPresContext, nullptr);
+ event->MarkUninitialized();
+ return event.forget();
+ }
#undef LOG_EVENT_CREATION
diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp
index a8c48ede8..fe896870c 100644
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -13,9 +13,6 @@
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
-#ifdef MOZ_B2G
-#include "mozilla/Hal.h"
-#endif // #ifdef MOZ_B2G
#include "mozilla/HalSensor.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/JSEventHandler.h"
@@ -355,18 +352,10 @@ EventListenerManager::AddEventListenerInternal(
EnableDevice(eDeviceLight);
} else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
EnableDevice(eDeviceMotion);
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
} else if (aTypeAtom == nsGkAtoms::onorientationchange) {
EnableDevice(eOrientationChange);
#endif
-#ifdef MOZ_B2G
- } else if (aTypeAtom == nsGkAtoms::onmoztimechange) {
- EnableDevice(eTimeChange);
- } else if (aTypeAtom == nsGkAtoms::onmoznetworkupload) {
- EnableDevice(eNetworkUpload);
- } else if (aTypeAtom == nsGkAtoms::onmoznetworkdownload) {
- EnableDevice(eNetworkDownload);
-#endif // MOZ_B2G
} else if (aTypeAtom == nsGkAtoms::ontouchstart ||
aTypeAtom == nsGkAtoms::ontouchend ||
aTypeAtom == nsGkAtoms::ontouchmove ||
@@ -492,14 +481,9 @@ EventListenerManager::IsDeviceType(EventMessage aEventMessage)
case eDeviceLight:
case eDeviceProximity:
case eUserProximity:
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
case eOrientationChange:
#endif
-#ifdef MOZ_B2G
- case eTimeChange:
- case eNetworkUpload:
- case eNetworkDownload:
-#endif
return true;
default:
break;
@@ -545,20 +529,11 @@ EventListenerManager::EnableDevice(EventMessage aEventMessage)
window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
window->EnableDeviceSensor(SENSOR_GYROSCOPE);
break;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
case eOrientationChange:
window->EnableOrientationChangeListener();
break;
#endif
-#ifdef MOZ_B2G
- case eTimeChange:
- window->EnableTimeChangeNotifications();
- break;
- case eNetworkUpload:
- case eNetworkDownload:
- window->EnableNetworkEvent(aEventMessage);
- break;
-#endif
default:
NS_WARNING("Enabling an unknown device sensor.");
break;
@@ -600,20 +575,11 @@ EventListenerManager::DisableDevice(EventMessage aEventMessage)
case eDeviceLight:
window->DisableDeviceSensor(SENSOR_LIGHT);
break;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
case eOrientationChange:
window->DisableOrientationChangeListener();
break;
#endif
-#ifdef MOZ_B2G
- case eTimeChange:
- window->DisableTimeChangeNotifications();
- break;
- case eNetworkUpload:
- case eNetworkDownload:
- window->DisableNetworkEvent(aEventMessage);
- break;
-#endif // MOZ_B2G
default:
NS_WARNING("Disabling an unknown device sensor.");
break;
diff --git a/dom/events/EventNameList.h b/dom/events/EventNameList.h
index ba2427623..214b844e7 100644
--- a/dom/events/EventNameList.h
+++ b/dom/events/EventNameList.h
@@ -164,6 +164,10 @@ EVENT(change,
eFormChange,
EventNameType_HTMLXUL,
eBasicEventClass)
+EVENT(auxclick,
+ eMouseAuxClick,
+ EventNameType_All,
+ eMouseEventClass)
EVENT(click,
eMouseClick,
EventNameType_All,
@@ -559,7 +563,7 @@ WINDOW_EVENT(online,
eOnline,
EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly,
eBasicEventClass)
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
WINDOW_EVENT(orientationchange,
eOrientationChange,
EventNameType_HTMLBodyOrFramesetOnly,
@@ -633,22 +637,6 @@ WINDOW_ONLY_EVENT(appinstalled,
EventNameType_None,
eBasicEventClass)
-
-#ifdef MOZ_B2G
-WINDOW_ONLY_EVENT(moztimechange,
- eTimeChange,
- EventNameType_None,
- eBasicEventClass)
-WINDOW_ONLY_EVENT(moznetworkupload,
- eNetworkUpload,
- EventNameType_None,
- eBasicEventClass)
-WINDOW_ONLY_EVENT(moznetworkdownload,
- eNetworkDownload,
- EventNameType_None,
- eBasicEventClass)
-#endif // MOZ_B2G
-
TOUCH_EVENT(touchstart,
eTouchStart,
EventNameType_All,
@@ -1003,6 +991,10 @@ EVENT(transitionend,
eTransitionEnd,
EventNameType_All,
eTransitionEventClass)
+EVENT(transitioncancel,
+ eTransitionCancel,
+ EventNameType_All,
+ eTransitionEventClass)
EVENT(animationstart,
eAnimationStart,
EventNameType_All,
@@ -1015,6 +1007,10 @@ EVENT(animationiteration,
eAnimationIteration,
EventNameType_All,
eAnimationEventClass)
+EVENT(animationcancel,
+ eAnimationCancel,
+ EventNameType_All,
+ eAnimationEventClass)
// Webkit-prefixed versions of Transition & Animation events, for web compat:
EVENT(webkitAnimationEnd,
diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp
index c23cdb575..7bbfe21b7 100644
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -492,6 +492,7 @@ IsMessageMouseUserActivity(EventMessage aMessage)
return aMessage == eMouseMove ||
aMessage == eMouseUp ||
aMessage == eMouseDown ||
+ aMessage == eMouseAuxClick ||
aMessage == eMouseDoubleClick ||
aMessage == eMouseClick ||
aMessage == eMouseActivate ||
@@ -731,6 +732,9 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
FlushPendingEvents(aPresContext);
break;
}
+ case ePointerGotCapture:
+ GenerateMouseEnterExit(mouseEvent);
+ break;
case eDragStart:
if (Prefs::ClickHoldContextMenu()) {
// an external drag gesture event came in, not generated internally
@@ -3890,10 +3894,7 @@ CreateMouseOrPointerWidgetEvent(WidgetMouseEvent* aMouseEvent,
newPointerEvent->mWidth = sourcePointer->mWidth;
newPointerEvent->mHeight = sourcePointer->mHeight;
newPointerEvent->inputSource = sourcePointer->inputSource;
- newPointerEvent->relatedTarget =
- nsIPresShell::GetPointerCapturingContent(sourcePointer->pointerId)
- ? nullptr
- : aRelatedContent;
+ newPointerEvent->relatedTarget = aRelatedContent;
aNewEvent = newPointerEvent.forget();
} else {
aNewEvent =
@@ -4034,7 +4035,7 @@ public:
}
}
- ~EnterLeaveDispatcher()
+ void Dispatch()
{
if (mEventMessage == eMouseEnter || mEventMessage == ePointerEnter) {
for (int32_t i = mTargets.Count() - 1; i >= 0; --i) {
@@ -4106,19 +4107,14 @@ EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
SetContentState(nullptr, NS_EVENT_STATE_HOVER);
}
- // In case we go out from capturing element (retargetedByPointerCapture is true)
- // we should dispatch ePointerLeave event and only for capturing element.
- RefPtr<nsIContent> movingInto = aMouseEvent->retargetedByPointerCapture
- ? wrapper->mLastOverElement->GetParent()
- : aMovingInto;
-
EnterLeaveDispatcher leaveDispatcher(this, wrapper->mLastOverElement,
- movingInto, aMouseEvent,
+ aMovingInto, aMouseEvent,
isPointer ? ePointerLeave : eMouseLeave);
// Fire mouseout
DispatchMouseOrPointerEvent(aMouseEvent, isPointer ? ePointerOut : eMouseOut,
wrapper->mLastOverElement, aMovingInto);
+ leaveDispatcher.Dispatch();
wrapper->mLastOverFrame = nullptr;
wrapper->mLastOverElement = nullptr;
@@ -4133,13 +4129,9 @@ EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
{
NS_ASSERTION(aContent, "Mouse must be over something");
- // If pointer capture is set, we should suppress pointerover/pointerenter events
- // for all elements except element which have pointer capture.
- bool dispatch = !aMouseEvent->retargetedByPointerCapture;
-
OverOutElementsWrapper* wrapper = GetWrapperByEventID(aMouseEvent);
- if (wrapper->mLastOverElement == aContent && dispatch)
+ if (wrapper->mLastOverElement == aContent)
return;
// Before firing mouseover, check for recursion
@@ -4162,7 +4154,7 @@ EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
}
// Firing the DOM event in the parent document could cause all kinds
// of havoc. Reverify and take care.
- if (wrapper->mLastOverElement == aContent && dispatch)
+ if (wrapper->mLastOverElement == aContent)
return;
// Remember mLastOverElement as the related content for the
@@ -4171,11 +4163,9 @@ EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
bool isPointer = aMouseEvent->mClass == ePointerEventClass;
- Maybe<EnterLeaveDispatcher> enterDispatcher;
- if (dispatch) {
- enterDispatcher.emplace(this, aContent, lastOverElement, aMouseEvent,
- isPointer ? ePointerEnter : eMouseEnter);
- }
+ EnterLeaveDispatcher enterDispatcher(this, aContent, lastOverElement,
+ aMouseEvent,
+ isPointer ? ePointerEnter : eMouseEnter);
NotifyMouseOut(aMouseEvent, aContent);
@@ -4187,17 +4177,13 @@ EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
SetContentState(aContent, NS_EVENT_STATE_HOVER);
}
- if (dispatch) {
- // Fire mouseover
- wrapper->mLastOverFrame =
- DispatchMouseOrPointerEvent(aMouseEvent,
- isPointer ? ePointerOver : eMouseOver,
- aContent, lastOverElement);
- wrapper->mLastOverElement = aContent;
- } else {
- wrapper->mLastOverFrame = nullptr;
- wrapper->mLastOverElement = nullptr;
- }
+ // Fire mouseover
+ wrapper->mLastOverFrame =
+ DispatchMouseOrPointerEvent(aMouseEvent,
+ isPointer ? ePointerOver : eMouseOver,
+ aContent, lastOverElement);
+ enterDispatcher.Dispatch();
+ wrapper->mLastOverElement = aContent;
// Turn recursion protection back off
wrapper->mFirstOverEventElement = nullptr;
@@ -4290,6 +4276,7 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
MOZ_FALLTHROUGH;
case ePointerMove:
case ePointerDown:
+ case ePointerGotCapture:
{
// Get the target content target (mousemove target == mouseover target)
nsCOMPtr<nsIContent> targetElement = GetEventTargetContent(aMouseEvent);
@@ -4647,6 +4634,32 @@ EventStateManager::SetClickCount(WidgetMouseEvent* aEvent,
}
nsresult
+EventStateManager::InitAndDispatchClickEvent(WidgetMouseEvent* aEvent,
+ nsEventStatus* aStatus,
+ EventMessage aMessage,
+ nsIPresShell* aPresShell,
+ nsIContent* aMouseTarget,
+ nsWeakFrame aCurrentTarget,
+ bool aNoContentDispatch)
+{
+ WidgetMouseEvent event(aEvent->IsTrusted(), aMessage,
+ aEvent->mWidget, WidgetMouseEvent::eReal);
+
+ event.mRefPoint = aEvent->mRefPoint;
+ event.mClickCount = aEvent->mClickCount;
+ event.mModifiers = aEvent->mModifiers;
+ event.buttons = aEvent->buttons;
+ event.mTime = aEvent->mTime;
+ event.mTimeStamp = aEvent->mTimeStamp;
+ event.mFlags.mNoContentDispatch = aNoContentDispatch;
+ event.button = aEvent->button;
+ event.inputSource = aEvent->inputSource;
+
+ return aPresShell->HandleEventWithTarget(&event, aCurrentTarget,
+ aMouseTarget, aStatus);
+}
+
+nsresult
EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent,
nsEventStatus* aStatus)
{
@@ -4665,17 +4678,7 @@ EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent,
(aEvent->button == WidgetMouseEvent::eMiddleButton ||
aEvent->button == WidgetMouseEvent::eRightButton);
- WidgetMouseEvent event(aEvent->IsTrusted(), eMouseClick,
- aEvent->mWidget, WidgetMouseEvent::eReal);
- event.mRefPoint = aEvent->mRefPoint;
- event.mClickCount = aEvent->mClickCount;
- event.mModifiers = aEvent->mModifiers;
- event.buttons = aEvent->buttons;
- event.mTime = aEvent->mTime;
- event.mTimeStamp = aEvent->mTimeStamp;
- event.mFlags.mNoContentDispatch = notDispatchToContents;
- event.button = aEvent->button;
- event.inputSource = aEvent->inputSource;
+ bool fireAuxClick = notDispatchToContents;
nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
if (presShell) {
@@ -4694,23 +4697,22 @@ EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent,
// HandleEvent clears out mCurrentTarget which we might need again
nsWeakFrame currentTarget = mCurrentTarget;
- ret = presShell->HandleEventWithTarget(&event, currentTarget,
- mouseContent, aStatus);
+ ret = InitAndDispatchClickEvent(aEvent, aStatus, eMouseClick,
+ presShell, mouseContent, currentTarget,
+ notDispatchToContents);
+
if (NS_SUCCEEDED(ret) && aEvent->mClickCount == 2 &&
mouseContent && mouseContent->IsInComposedDoc()) {
//fire double click
- WidgetMouseEvent event2(aEvent->IsTrusted(), eMouseDoubleClick,
- aEvent->mWidget, WidgetMouseEvent::eReal);
- event2.mRefPoint = aEvent->mRefPoint;
- event2.mClickCount = aEvent->mClickCount;
- event2.mModifiers = aEvent->mModifiers;
- event2.buttons = aEvent->buttons;
- event2.mFlags.mNoContentDispatch = notDispatchToContents;
- event2.button = aEvent->button;
- event2.inputSource = aEvent->inputSource;
-
- ret = presShell->HandleEventWithTarget(&event2, currentTarget,
- mouseContent, aStatus);
+ ret = InitAndDispatchClickEvent(aEvent, aStatus, eMouseDoubleClick,
+ presShell, mouseContent, currentTarget,
+ notDispatchToContents);
+ }
+ if (NS_SUCCEEDED(ret) && mouseContent && fireAuxClick &&
+ mouseContent->IsInComposedDoc()) {
+ ret = InitAndDispatchClickEvent(aEvent, aStatus, eMouseAuxClick,
+ presShell, mouseContent, currentTarget,
+ false);
}
}
}
diff --git a/dom/events/EventStateManager.h b/dom/events/EventStateManager.h
index 49ecf0586..d0461e7fa 100644
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -415,6 +415,13 @@ protected:
*/
void UpdateDragDataTransfer(WidgetDragEvent* dragEvent);
+ static nsresult InitAndDispatchClickEvent(WidgetMouseEvent* aEvent,
+ nsEventStatus* aStatus,
+ EventMessage aMessage,
+ nsIPresShell* aPresShell,
+ nsIContent* aMouseTarget,
+ nsWeakFrame aCurrentTarget,
+ bool aNoContentDispatch);
nsresult SetClickCount(WidgetMouseEvent* aEvent, nsEventStatus* aStatus);
nsresult CheckForAndDispatchClick(WidgetMouseEvent* aEvent,
nsEventStatus* aStatus);
@@ -1046,6 +1053,7 @@ private:
#define NS_EVENT_NEEDS_FRAME(event) \
(!(event)->HasPluginActivationEventMessage() && \
(event)->mMessage != eMouseClick && \
- (event)->mMessage != eMouseDoubleClick)
+ (event)->mMessage != eMouseDoubleClick && \
+ (event)->mMessage != eMouseAuxClick)
#endif // mozilla_EventStateManager_h_
diff --git a/dom/events/KeyNameList.h b/dom/events/KeyNameList.h
index 35fbe2d5f..361122ec7 100644
--- a/dom/events/KeyNameList.h
+++ b/dom/events/KeyNameList.h
@@ -32,10 +32,6 @@ DEFINE_KEYNAME_INTERNAL(PrintableKey, "MozPrintableKey")
DEFINE_KEYNAME_INTERNAL(SoftLeft, "MozSoftLeft")
DEFINE_KEYNAME_INTERNAL(SoftRight, "MozSoftRight")
-#ifdef MOZ_B2G
-DEFINE_KEYNAME_INTERNAL(HomeScreen, "MozHomeScreen")
-#endif // #ifdef MOZ_B2G
-
/******************************************************************************
* Modifier Keys
*****************************************************************************/
diff --git a/dom/events/PointerEvent.cpp b/dom/events/PointerEvent.cpp
index f53739863..fbaa0f737 100644
--- a/dom/events/PointerEvent.cpp
+++ b/dom/events/PointerEvent.cpp
@@ -93,8 +93,10 @@ PointerEvent::Constructor(EventTarget* aOwner,
widgetEvent->mWidth = aParam.mWidth;
widgetEvent->mHeight = aParam.mHeight;
widgetEvent->pressure = aParam.mPressure;
+ widgetEvent->tangentialPressure = aParam.mTangentialPressure;
widgetEvent->tiltX = aParam.mTiltX;
widgetEvent->tiltY = aParam.mTiltY;
+ widgetEvent->twist = aParam.mTwist;
widgetEvent->inputSource = ConvertStringToPointerType(aParam.mPointerType);
widgetEvent->mIsPrimary = aParam.mIsPrimary;
widgetEvent->buttons = aParam.mButtons;
@@ -145,6 +147,12 @@ PointerEvent::Pressure()
return mEvent->AsPointerEvent()->pressure;
}
+float
+PointerEvent::TangentialPressure()
+{
+ return mEvent->AsPointerEvent()->tangentialPressure;
+}
+
int32_t
PointerEvent::TiltX()
{
@@ -157,6 +165,12 @@ PointerEvent::TiltY()
return mEvent->AsPointerEvent()->tiltY;
}
+int32_t
+PointerEvent::Twist()
+{
+ return mEvent->AsPointerEvent()->twist;
+}
+
bool
PointerEvent::IsPrimary()
{
diff --git a/dom/events/PointerEvent.h b/dom/events/PointerEvent.h
index 62c5a0c36..12d4941dc 100644
--- a/dom/events/PointerEvent.h
+++ b/dom/events/PointerEvent.h
@@ -44,8 +44,10 @@ public:
int32_t Width();
int32_t Height();
float Pressure();
+ float TangentialPressure();
int32_t TiltX();
int32_t TiltY();
+ int32_t Twist();
bool IsPrimary();
void GetPointerType(nsAString& aPointerType);
};
diff --git a/dom/events/TouchEvent.cpp b/dom/events/TouchEvent.cpp
index cc9684eb3..9b7a74ac2 100644
--- a/dom/events/TouchEvent.cpp
+++ b/dom/events/TouchEvent.cpp
@@ -203,7 +203,7 @@ TouchEvent::PrefEnabled(nsIDocShell* aDocShell)
enabled = false;
} else {
if (sPrefCacheValue == 2) {
-#if defined(MOZ_B2G) || defined(MOZ_WIDGET_ANDROID)
+#if defined(MOZ_WIDGET_ANDROID)
// Touch support is always enabled on B2G and android.
enabled = true;
#elif defined(XP_WIN) || MOZ_WIDGET_GTK == 3
diff --git a/dom/events/WheelHandlingHelper.cpp b/dom/events/WheelHandlingHelper.cpp
index 7665ee922..81f2b6bfa 100644
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -257,6 +257,7 @@ WheelTransaction::OnEvent(WidgetEvent* aEvent)
case eMouseUp:
case eMouseDown:
case eMouseDoubleClick:
+ case eMouseAuxClick:
case eMouseClick:
case eContextMenu:
case eDrop:
diff --git a/dom/events/moz.build b/dom/events/moz.build
index ee4946038..ec3813207 100644
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -153,10 +153,5 @@ LOCAL_INCLUDES += [
'/layout/xul/tree/',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- LOCAL_INCLUDES += [
- '/dom/wifi',
- ]
-
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']
diff --git a/dom/events/test/mochitest.ini b/dom/events/test/mochitest.ini
index e100e60a1..0397487bb 100644
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -184,3 +184,4 @@ skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
[test_wheel_default_action.html]
[test_bug687787.html]
[test_bug1298970.html]
+[test_bug1304044.html]
diff --git a/dom/events/test/pointerevents/mochitest.ini b/dom/events/test/pointerevents/mochitest.ini
index 58eae12fe..af762feb2 100644
--- a/dom/events/test/pointerevents/mochitest.ini
+++ b/dom/events/test/pointerevents/mochitest.ini
@@ -6,6 +6,14 @@ support-files =
pointerevent_styles.css
pointerevent_support.js
+[test_bug1285128.html]
+[test_bug1293174_implicit_pointer_capture_for_touch_1.html]
+ support-files = bug1293174_implicit_pointer_capture_for_touch_1.html
+[test_bug1293174_implicit_pointer_capture_for_touch_2.html]
+ support-files = bug1293174_implicit_pointer_capture_for_touch_2.html
+[test_bug1323158.html]
+[test_empty_file.html]
+ disabled = disabled # Bug 1150091 - Issue with support-files
[test_pointerevent_attributes_mouse-manual.html]
support-files = pointerevent_attributes_mouse-manual.html
[test_pointerevent_capture_mouse-manual.html]
@@ -143,10 +151,5 @@ support-files =
pointerevent_touch-action-span-test_touch-manual.html
pointerevent_touch-action-svg-test_touch-manual.html
pointerevent_touch-action-table-test_touch-manual.html
-[test_bug1285128.html]
-[test_bug1293174_implicit_pointer_capture_for_touch_1.html]
- support-files = bug1293174_implicit_pointer_capture_for_touch_1.html
-[test_bug1293174_implicit_pointer_capture_for_touch_2.html]
- support-files = bug1293174_implicit_pointer_capture_for_touch_2.html
-[test_empty_file.html]
- disabled = disabled # Bug 1150091 - Issue with support-files
+[test_trigger_fullscreen_by_pointer_events.html]
+[test_trigger_popup_by_pointer_events.html]
diff --git a/dom/events/test/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html b/dom/events/test/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html
index f4d5573ed..2614790f3 100644
--- a/dom/events/test/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html
+++ b/dom/events/test/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html
@@ -1,4 +1,4 @@
-<!doctype html>
+<!doctype html>
<html>
<head>
<title>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</title>
@@ -12,19 +12,27 @@
<script type="text/javascript" src="pointerevent_support.js"></script>
<script type="text/javascript" src="mochitest_support_internal.js"></script>
<script type="text/javascript">
+ var test_pointerEvent;
var detected_pointertypes = {};
- var test_pointerEvent = async_test("lostpointercapture: subsequent events to target."); // set up test harness
- var suppressedEventsFail = false;
- // showPointerTypes is defined in pointerevent_support.js
- // Requirements: the callback function will reference the test_pointerEvent object and
- // will fail unless the async_test is created with the var name "test_pointerEvent".
- add_completion_callback(showPointerTypes);
-
- var captured_event;
+ var captured_event = null;
+ var test_done = false;
+ var overEnterEventsFail = false;
+ var outLeaveEventsFail = false;
var f_gotPointerCapture = false;
var f_lostPointerCapture = false;
+ function resetTestState() {
+ captured_event = null;
+ test_done = false;
+ overEnterEventsFail = false;
+ outLeaveEventsFail = false;
+ f_gotPointerCapture = false;
+ f_lostPointerCapture = false;
+ }
+
function listenerEventHandler(event) {
+ if (test_done)
+ return;
detected_pointertypes[event.pointerType] = true;
if (event.type == "gotpointercapture") {
f_gotPointerCapture = true;
@@ -35,12 +43,20 @@
f_gotPointerCapture = false;
check_PointerEvent(event);
}
- else if(event.type == "pointerover" || event.type == "pointerenter" || event.type == "pointerout" || event.type == "pointerleave") {
- if(!suppressedEventsFail) {
+ else if(event.type == "pointerover" || event.type == "pointerenter") {
+ if(captured_event && !overEnterEventsFail) {
+ test(function() {
+ assert_false(f_gotPointerCapture, "pointerover/enter should be received before the target receives gotpointercapture even when the pointer is not over it.");
+ }, expectedPointerType + " pointerover/enter should be received before the target receives gotpointercapture even when the pointer is not over it.");
+ overEnterEventsFail = true;
+ }
+ }
+ else if(event.type == "pointerout" || event.type == "pointerleave") {
+ if(!outLeaveEventsFail) {
test(function() {
- assert_true(false, "Suppressed events were received");
- }, "Suppressed events were received");
- suppressedEventsFail = true;
+ assert_true(f_lostPointerCapture, "pointerout/leave should not be received unless the target just lost the capture.");
+ }, expectedPointerType + " pointerout/leave should not be received unless the target just lost the capture.");
+ outLeaveEventsFail = true;
}
}
else if (event.pointerId == captured_event.pointerId) {
@@ -50,19 +66,21 @@
}
else {
// if any other events are received after releaseCapture, then the test fails
- test_pointerEvent.step(function () {
- assert_true(false, event.target.id + "-" + event.type + " should be handled by target element handler");
- });
+ test(function () {
+ assert_unreached(event.target.id + "-" + event.type + " should be handled by target element handler");
+ }, expectedPointerType + " No other events should be recieved by capturing node after release");
}
}
}
function targetEventHandler(event) {
+ if (test_done)
+ return;
if (f_gotPointerCapture) {
if(event.type != "pointerout" && event.type != "pointerleave") {
- test_pointerEvent.step(function () {
- assert_true(false, "The Target element should not have received any events while capture is active. Event recieved:" + event.type + ". ");
- });
+ test(function () {
+ assert_unreached("The Target element should not have received any events while capture is active. Event recieved:" + event.type + ". ");
+ }, expectedPointerType + " The target element should not receive any events while capture is active");
}
}
@@ -77,12 +95,14 @@
assert_equals(event.pointerId, captured_event.pointerId, "pointerID is same for event captured and after release");
});
if (event.type == "pointerup") {
+ test_done = true;
test_pointerEvent.done(); // complete test
}
}
}
function run() {
+ test_pointerEvent = setup_pointerevent_test("got/lost pointercapture: subsequent events to target", ALL_POINTERS); // set up test harness
var listener = document.getElementById("listener");
var target0 = document.getElementById("target0");
target0.style["touchAction"] = "none";
@@ -96,18 +116,19 @@
</script>
</head>
<body onload="run()">
+ <h2 id="pointerTypeDescription"></h2>
<div id="listener"></div>
<h1>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</h1>
<!--
<h4>
Test Description:
+ Use your pointer and press down in the black box. Then move around in the box and release your pointer.
After invoking the releasePointerCapture method on an element, subsequent events for the specified
- pointer must follow normal hit testing mechanisms for determining the event target
+ pointer must follow normal hit testing mechanisms for determining the event target.
</h4>
<br />
-->
<div id="target0">
- Use mouse, touch or pen to contact here and move around.
</div>
<div id="complete-notice">
<p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
diff --git a/dom/events/test/pointerevents/test_bug1285128.html b/dom/events/test/pointerevents/test_bug1285128.html
index f7f1eb698..9577940c1 100644
--- a/dom/events/test/pointerevents/test_bug1285128.html
+++ b/dom/events/test/pointerevents/test_bug1285128.html
@@ -13,7 +13,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1285128
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1285128">Mozilla Bug 1285128</a>
<p id="display"></p>
-<div id="target0" style="width: 200px; height: 200px; background: green"></div>
+<div id="target0" style="width: 50px; height: 50px; background: green"></div>
+<div id="target1" style="width: 50px; height: 50px; background: red"></div>
<script type="text/javascript">
/** Test for Bug 1285128 **/
@@ -31,7 +32,7 @@ function runTests() {
}, false);
});
- target0.addEventListener("mouseenter", () => {
+ target1.addEventListener("mouseup", () => {
ok(!receivedPointerEvents, "synthesized mousemove should not trigger any pointer events");
SimpleTest.finish();
});
@@ -39,6 +40,8 @@ function runTests() {
synthesizeMouseAtCenter(target0, { type: "mousemove",
inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE,
isWidgetEventSynthesized: true });
+ synthesizeMouseAtCenter(target1, { type: "mousedown" });
+ synthesizeMouseAtCenter(target1, { type: "mouseup" });
}
SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.enabled", true]]}, runTests);
diff --git a/dom/events/test/pointerevents/test_bug1323158.html b/dom/events/test/pointerevents/test_bug1323158.html
new file mode 100644
index 000000000..fac96c97a
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1323158.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1323158
+-->
+<head>
+ <meta charset="utf-8">
+ <title>This is a test to check if target and relatedTarget of mouse events are the same as pointer events</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="content"></p>
+<script type="text/javascript">
+
+/** Test for Bug 1323158 **/
+SimpleTest.waitForExplicitFinish();
+
+function runTests() {
+ let content = document.getElementById('content');
+ let iframe = document.createElement('iframe');
+ iframe.width = 500;
+ iframe.height = 500;
+ content.appendChild(iframe);
+ iframe.contentDocument.body.innerHTML =
+ "<br><div id='target0' style='width: 30px; height: 30px; background: black;'></div>" +
+ "<br><div id='target1' style='width: 30px; height: 30px; background: red;'></div>" +
+ "<br><div id='done' style='width: 30px; height: 30px; background: green;'></div>";
+
+ let target0 = iframe.contentDocument.getElementById("target0");
+ let target1 = iframe.contentDocument.getElementById("target1");
+ let done = iframe.contentDocument.getElementById("done");
+ let pointerBoundaryEvents = ["pointerover", "pointerenter", "pointerleave", "pointerout"];
+ let mouseBoundaryEvents = ["mouseover", "mouseenter", "mouseleave", "mouseout"];
+ let receivedPointerBoundaryEvents = {};
+ let mouseEvent2pointerEvent = {"mouseover": "pointerover",
+ "mouseenter": "pointerenter",
+ "mouseleave": "pointerleave",
+ "mouseout": "pointerout"
+ };
+
+ pointerBoundaryEvents.forEach((event) => {
+ target1.addEventListener(event, (e) => {
+ receivedPointerBoundaryEvents[event] = e;
+ });
+ });
+
+ let attributes = ["target", "relatedTarget"];
+ mouseBoundaryEvents.forEach((event) => {
+ target1.addEventListener(event, (e) => {
+ let correspondingPointerEv = receivedPointerBoundaryEvents[mouseEvent2pointerEvent[event]];
+ ok(correspondingPointerEv, "Should receive " + mouseEvent2pointerEvent[event] + " before " + e.type);
+ if (correspondingPointerEv) {
+ attributes.forEach((attr) => {
+ ok(correspondingPointerEv[attr] == e[attr],
+ attr + " of " + e.type + " should be the same as the correcponding pointer event expect " +
+ correspondingPointerEv[attr] + " got " + e[attr]);
+ });
+ }
+ receivedPointerBoundaryEvents[mouseEvent2pointerEvent[event]] = null;
+ });
+ });
+ target0.addEventListener("pointerdown", (e) => {
+ target1.setPointerCapture(e.pointerId);
+ });
+ done.addEventListener("mouseup", () => {
+ SimpleTest.finish();
+ });
+ let source = SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE;
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target0, 5, 5, { type: "mousedown", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target0, 5, 5, { type: "mouseup", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(done, 5, 5, { type: "mousedown", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(done, 5, 5, { type: "mouseup", inputSource: source },
+ iframe.contentWindow);
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.enabled", true]]}, runTests);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_pointerevent_capture_suppressing_mouse-manual.html b/dom/events/test/pointerevents/test_pointerevent_capture_suppressing_mouse-manual.html
index dc3903592..2b08e2bb8 100644
--- a/dom/events/test/pointerevents/test_pointerevent_capture_suppressing_mouse-manual.html
+++ b/dom/events/test/pointerevents/test_pointerevent_capture_suppressing_mouse-manual.html
@@ -19,7 +19,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target1", "mousemove");
- sendMouseEvent(int_win, "btnCapture", "mousedown", {button:1});
+ sendMouseEvent(int_win, "btnCapture", "mousemove");
+ sendMouseEvent(int_win, "btnCapture", "mousedown");
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target1", "mousemove");
diff --git a/dom/events/test/pointerevents/test_pointerevent_releasepointercapture_events_to_original_target-manual.html b/dom/events/test/pointerevents/test_pointerevent_releasepointercapture_events_to_original_target-manual.html
index cbf91df74..35350e016 100644
--- a/dom/events/test/pointerevents/test_pointerevent_releasepointercapture_events_to_original_target-manual.html
+++ b/dom/events/test/pointerevents/test_pointerevent_releasepointercapture_events_to_original_target-manual.html
@@ -17,9 +17,30 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
runTestInNewWindow("pointerevent_releasepointercapture_events_to_original_target-manual.html");
}
function executeTest(int_win) {
- sendTouchEvent(int_win, "target0", "touchstart");
- sendTouchEvent(int_win, "target0", "touchmove");
- sendTouchEvent(int_win, "target0", "touchend");
+ // Synthesize mouse events to run this test.
+ sendMouseEvent(int_win, "target0", "mousemove");
+ sendMouseEvent(int_win, "target0", "mousedown");
+ sendMouseEvent(int_win, "target0", "mousemove", {buttons: 1});
+ sendMouseEvent(int_win, "target0", "mousemove", {buttons: 1});
+ sendMouseEvent(int_win, "target0", "mouseup");
+
+ window.addEventListener("message", function(aEvent) {
+ if (aEvent.data == "Test Touch") {
+ // Synthesize touch events to run this test.
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchmove");
+ sendTouchEvent(int_win, "target0", "touchend");
+ window.postMessage("Test Pen", "*");
+ } else if (aEvent.data == "Test Pen") {
+ // Synthesize pen events to run this test.
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mousedown", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN, buttons: 1});
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN, buttons: 1});
+ sendMouseEvent(int_win, "target0", "mouseup", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ }
+ });
+ window.postMessage("Test Touch", "*");
}
</script>
</head>
diff --git a/dom/events/test/pointerevents/test_pointerevent_setpointercapture_relatedtarget-manual.html b/dom/events/test/pointerevents/test_pointerevent_setpointercapture_relatedtarget-manual.html
index 0883d616b..09e97ec97 100644
--- a/dom/events/test/pointerevents/test_pointerevent_setpointercapture_relatedtarget-manual.html
+++ b/dom/events/test/pointerevents/test_pointerevent_setpointercapture_relatedtarget-manual.html
@@ -19,8 +19,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "btnCapture", "mousedown");
- sendMouseEvent(int_win, "target1", "mousemove");
- sendMouseEvent(int_win, "target1", "mouseup");
+ sendMouseEvent(int_win, "btnCapture", "mousemove");
+ sendMouseEvent(int_win, "btnCapture", "mouseup");
}
</script>
</head>
diff --git a/dom/events/test/pointerevents/test_trigger_fullscreen_by_pointer_events.html b/dom/events/test/pointerevents/test_trigger_fullscreen_by_pointer_events.html
new file mode 100644
index 000000000..53d390996
--- /dev/null
+++ b/dom/events/test/pointerevents/test_trigger_fullscreen_by_pointer_events.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for triggering Fullscreen by pointer events</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script>
+
+SimpleTest.waitForExplicitFinish();
+
+function startTest() {
+ let win = window.open("data:text/html,<body><div id='target' style='width: 50px; height: 50px; background: green'></div></body>", "_blank");
+ win.addEventListener("load", () => {
+ let target = win.document.getElementById("target");
+ target.addEventListener("pointerdown", () => {
+ target.requestFullscreen();
+ target.addEventListener("pointerdown", () => {
+ win.document.exitFullscreen();
+ }, {once: true});
+ }, {once: true});
+
+ win.document.addEventListener("fullscreenchange", () => {
+ if (win.document.fullscreenElement) {
+ ok(win.document.fullscreenElement, target, "fullscreenElement should be the div element");
+ // synthesize mouse events to generate pointer events and leave full screen.
+ synthesizeMouseAtCenter(target, { type: "mousedown" }, win);
+ synthesizeMouseAtCenter(target, { type: "mouseup" }, win);
+ } else {
+ win.close();
+ SimpleTest.finish();
+ }
+ });
+ // Make sure our window is focused before starting the test
+ SimpleTest.waitForFocus(() => {
+ // synthesize mouse events to generate pointer events and enter full screen.
+ synthesizeMouseAtCenter(target, { type: "mousedown" }, win);
+ synthesizeMouseAtCenter(target, { type: "mouseup" }, win);
+ }, win);
+ });
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["full-screen-api.unprefix.enabled", true],
+ ["full-screen-api.allow-trusted-requests-only", false],
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, startTest);
+});
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_trigger_popup_by_pointer_events.html b/dom/events/test/pointerevents/test_trigger_popup_by_pointer_events.html
new file mode 100644
index 000000000..cda279e26
--- /dev/null
+++ b/dom/events/test/pointerevents/test_trigger_popup_by_pointer_events.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for triggering popup by pointer events</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="target" style="width: 50px; height: 50px; background: green"></div>
+<script>
+
+SimpleTest.waitForExplicitFinish();
+
+function sendMouseEvent(element, eventName, listenEventName, handler) {
+ element.addEventListener(listenEventName, handler, {once: true});
+ synthesizeMouseAtCenter(element, {type: eventName});
+}
+
+function checkAllowOpenPopup(e) {
+ let w = window.open("about:blank");
+ ok(w, "Should allow popup in the " + e.type + " listener");
+ if (w) {
+ w.close();
+ }
+}
+
+function checkBlockOpenPopup(e) {
+ let w = window.open("about:blank");
+ ok(!w, "Should block popup in the " + e.type + " listener");
+ if (w) {
+ w.close();
+ }
+}
+
+function startTest() {
+ let target = document.getElementById("target");
+ // By default, only allow opening popup in the pointerup listener.
+ sendMouseEvent(target, "mousemove", "pointermove", checkBlockOpenPopup);
+ sendMouseEvent(target, "mousedown", "pointerdown", checkBlockOpenPopup);
+ sendMouseEvent(target, "mousemove", "pointermove", checkBlockOpenPopup);
+ sendMouseEvent(target, "mouseup", "pointerup", checkAllowOpenPopup);
+ SpecialPowers.pushPrefEnv({"set": [["dom.popup_allowed_events",
+ "pointerdown pointerup"]]}, () => {
+ // Adding pointerdown to preference should work
+ sendMouseEvent(target, "mousemove", "pointermove", checkBlockOpenPopup);
+ sendMouseEvent(target, "mousedown", "pointerdown", checkAllowOpenPopup);
+ sendMouseEvent(target, "mousemove", "pointermove", checkBlockOpenPopup);
+ sendMouseEvent(target, "mouseup", "pointerup", checkAllowOpenPopup);
+ SpecialPowers.pushPrefEnv({"set": [["dom.popup_allowed_events",
+ "pointerdown pointerup pointermove"]]}, () => {
+ // Adding pointermove to preference should be no effect.
+ sendMouseEvent(target, "mousemove", "pointermove", checkBlockOpenPopup);
+ sendMouseEvent(target, "mousedown", "pointerdown", checkAllowOpenPopup);
+ sendMouseEvent(target, "mousemove", "pointermove", checkBlockOpenPopup);
+ sendMouseEvent(target, "mouseup", "pointerup", checkAllowOpenPopup);
+ SimpleTest.finish();
+ });
+ });
+}
+
+const DENY_ACTION = SpecialPowers.Ci.nsIPermissionManager.DENY_ACTION;
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPermissions([{'type': 'popup', 'allow': DENY_ACTION,
+ 'context': document}], () => {
+ SpecialPowers.pushPrefEnv({
+ "set": [["dom.w3c_pointer_events.enabled", true]]
+ }, startTest);
+ });
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/test_bug1304044.html b/dom/events/test/test_bug1304044.html
new file mode 100644
index 000000000..0911dcf73
--- /dev/null
+++ b/dom/events/test/test_bug1304044.html
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1304044
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1304044</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+ var eventsFired = [];
+ var target;
+ var eventsExpected;
+
+ function GetNodeString(node) {
+ if (node == window)
+ return "window";
+ if (node == document)
+ return "document";
+ if (node.id)
+ return node.id;
+ if (node.nodeName)
+ return node.nodeName;
+ return node;
+ }
+
+ function TargetAndListener(listener, target) {
+ this.listener = listener;
+ this.target = target;
+ }
+
+ TargetAndListener.prototype.toString = function() {
+ var targetName = GetNodeString(this.target);
+ var listenerName = GetNodeString(this.listener);
+ return "(listener: " + listenerName + ", target: " + targetName + ")";
+ }
+
+ var tests = [
+ TestAuxClickBubblesForEventListener,
+ TestAuxClickBubblesForOnAuxClick,
+ ];
+
+ function CompareEvents(evt, expected) {
+ return evt && expected && evt.listener == expected.listener &&
+ evt.target == expected.target;
+ }
+
+ function ResetEventsFired() {
+ eventsFired = [];
+ }
+
+ function ClearEventListeners() {
+ for (i in arguments) {
+ arguments[i].removeEventListener("auxclick", log_event);
+ }
+ }
+
+ function ClickTarget(tgt) {
+ synthesizeMouseAtCenter(tgt, {type : "mousedown", button: 2}, window);
+ synthesizeMouseAtCenter(tgt, {type : "mouseup", button: 2}, window);
+ }
+
+ function log_event(e) {
+ eventsFired[eventsFired.length] = new TargetAndListener(this, e.target);
+ }
+
+ function CompareEventsToExpected(expected, actual) {
+ for (var i = 0; i < expected.length || i < actual.length; i++) {
+ ok(CompareEvents(actual[i], expected[i]),
+ "Auxclick receiver's don't match: TargetAndListener " +
+ i + ": Expected: " + expected[i] + ", Actual: " + actual[i]);
+ }
+ }
+
+ function TestAuxClickBubblesForEventListener() {
+ target.addEventListener("auxclick", log_event);
+ document.addEventListener("auxclick", log_event);
+ window.addEventListener("auxclick", log_event);
+
+ ClickTarget(target)
+ CompareEventsToExpected(eventsExpected, eventsFired);
+ ResetEventsFired();
+ ClearEventListeners(target, document, window);
+ }
+
+ function TestAuxClickBubblesForOnAuxClick() {
+ target.onauxclick = log_event;
+ document.onauxclick = log_event;
+ window.onauxclick = log_event;
+
+ ClickTarget(target);
+ CompareEventsToExpected(eventsExpected, eventsFired);
+ ResetEventsFired();
+ }
+
+ function RunTests(){
+ for (var i = 0; i < tests.length; i++) {
+ tests[i]();
+ }
+ }
+
+ function Begin() {
+ target = document.getElementById("target");
+ eventsExpected = [
+ new TargetAndListener(target, target),
+ new TargetAndListener(document, target),
+ new TargetAndListener(window, target),
+ ];
+ RunTests();
+ target.remove();
+ SimpleTest.finish();
+ }
+
+ window.onload = function() {
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.executeSoon(Begin);
+ }
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1304044">Mozilla Bug 1304044</a>
+<p id="display">
+ <div id="target">Target</div>
+</p>
+<div id="content" style:"display:none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/events/test/test_eventTimeStamp.html b/dom/events/test/test_eventTimeStamp.html
index 107a21f87..056203e92 100644
--- a/dom/events/test/test_eventTimeStamp.html
+++ b/dom/events/test/test_eventTimeStamp.html
@@ -17,7 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=77992
<script type="text/js-worker" id="worker-src">
// Simply returns the event timestamp
onmessage = function(evt) {
- postMessage(evt.timeStamp);
+ postMessage(evt.timeStamp + performance.timeOrigin);
}
</script>
<script type="text/js-worker" id="shared-worker-src">
@@ -25,7 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=77992
onconnect = function(evt) {
var port = evt.ports[0];
port.onmessage = function(messageEvt) {
- port.postMessage(messageEvt.timeStamp);
+ port.postMessage(messageEvt.timeStamp + performance.timeOrigin);
};
};
</script>
@@ -57,9 +57,9 @@ function testRegularEvents() {
finishTests();
return;
}
- var timeBeforeEvent = window.performance.now();
- window.addEventListener("load", function(evt) {
- var timeAfterEvent = window.performance.now();
+ var timeBeforeEvent = performance.now();
+ addEventListener("load", function(evt) {
+ var timeAfterEvent = performance.now();
ok(evt.timeStamp >= timeBeforeEvent &&
evt.timeStamp <= timeAfterEvent,
"Event timestamp (" + evt.timeStamp + ") is in expected range: (" +
@@ -71,19 +71,18 @@ function testRegularEvents() {
function testWorkerEvents() {
var blob = new Blob([ document.getElementById("worker-src").textContent ],
{ type: "text/javascript" });
- var worker = new Worker(window.URL.createObjectURL(blob));
+ var worker = new Worker(URL.createObjectURL(blob));
worker.onmessage = function(evt) {
- var timeAfterEvent = window.performance.now();
- // Comparing times across timelines may break now
- // ok(evt.data >= timeBeforeEvent &&
- // evt.data <= timeAfterEvent,
+ var timeAfterEvent = performance.now() + performance.timeOrigin;
+ ok(evt.data >= timeBeforeEvent &&
+ evt.data <= timeAfterEvent,
// "Event timestamp in dedicated worker (" + evt.data +
// ") is in expected range: (" +
// timeBeforeEvent + ", " + timeAfterEvent + ")");
worker.terminate();
testSharedWorkerEvents();
};
- var timeBeforeEvent = window.performance.now();
+ var timeBeforeEvent = performance.now() + performance.timeOrigin;
worker.postMessage("");
}
@@ -93,17 +92,16 @@ function testSharedWorkerEvents() {
{ type: "text/javascript" });
// Delay creation of worker slightly so it is easier to distinguish
// shared worker creation time from this document's navigation start
- window.setTimeout(function() {
- var timeBeforeWorkerCreation = window.performance.now();
- var worker = new SharedWorker(window.URL.createObjectURL(blob));
+ setTimeout(function() {
+ var timeBeforeEvent = performance.now() + performance.timeOrigin;
+ var worker = new SharedWorker(URL.createObjectURL(blob));
worker.port.onmessage = function(evt) {
- var timeAfterEvent = window.performance.now();
- // Comparing times across timelines may break now
- // ok(evt.data >= 0 &&
- // evt.data <= timeAfterEvent - timeBeforeWorkerCreation,
+ var timeAfterEvent = performance.now() + performance.timeOrigin;
+ ok(evt.data >= timeBeforeEvent &&
+ evt.data <= timeAfterEvent,
// "Event timestamp in shared worker (" + evt.data +
// ") is in expected range: (0, " +
- // (timeAfterEvent - timeBeforeWorkerCreation) + ")");
+ // timeBeforeEvent + ", " + timeAfterEvent + ")");
worker.port.close();
finishTests();
};
diff --git a/dom/events/test/test_legacy_event.html b/dom/events/test/test_legacy_event.html
index d772be106..b2105a6df 100644
--- a/dom/events/test/test_legacy_event.html
+++ b/dom/events/test/test_legacy_event.html
@@ -73,22 +73,15 @@ function triggerShortAnimation(node) {
node.style.animation = "anim1 1ms linear";
}
-// This function triggers a long animation with two iterations, which is
-// *nearly* at the end of its first iteration. It will hit the end of that
-// iteration (firing an event) almost immediately, 1ms in the future.
+// This function triggers a very short (10ms long) animation with many
+// iterations, which will cause a start event followed by an iteration event
+// on each subsequent tick, to fire.
//
-// NOTE: It's important that this animation have a *long* duration. If it were
-// short (e.g. 1ms duration), then we might jump past all its iterations in
-// a single refresh-driver tick. And if that were to happens, we'd *never* fire
-// any animationiteration events -- the CSS Animations spec says this event
-// must not be fired "...when an animationend event would fire at the same time"
-// (which would be the case in this example with a 1ms duration). So, to make
-// sure our event does fire, we use a long duration and a nearly-as-long
-// negative delay. This ensures we hit the end of the first iteration right
-// away, and that we don't risk hitting the end of the second iteration at the
-// same time.
+// NOTE: We need the many iterations since if an animation frame coincides
+// with the animation starting or ending we dispatch only the start or end
+// event and not the iteration event.
function triggerAnimationIteration(node) {
- node.style.animation = "anim1 300s -299.999s linear 2";
+ node.style.animation = "anim1 10ms linear 20000";
}
// GENERAL UTILITY FUNCTIONS
diff --git a/dom/fetch/InternalHeaders.cpp b/dom/fetch/InternalHeaders.cpp
index e81863173..11585615e 100644
--- a/dom/fetch/InternalHeaders.cpp
+++ b/dom/fetch/InternalHeaders.cpp
@@ -21,12 +21,14 @@ InternalHeaders::InternalHeaders(const nsTArray<Entry>&& aHeaders,
HeadersGuardEnum aGuard)
: mGuard(aGuard)
, mList(aHeaders)
+ , mListDirty(true)
{
}
InternalHeaders::InternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
HeadersGuardEnum aGuard)
: mGuard(aGuard)
+ , mListDirty(true)
{
for (const HeadersEntry& headersEntry : aHeadersEntryList) {
mList.AppendElement(Entry(headersEntry.name(), headersEntry.value()));
@@ -56,6 +58,8 @@ InternalHeaders::Append(const nsACString& aName, const nsACString& aValue,
return;
}
+ SetListDirty();
+
mList.AppendElement(Entry(lowerName, aValue));
}
@@ -69,6 +73,8 @@ InternalHeaders::Delete(const nsACString& aName, ErrorResult& aRv)
return;
}
+ SetListDirty();
+
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (lowerName == mList[i].mName) {
@@ -155,6 +161,8 @@ InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorRes
return;
}
+ SetListDirty();
+
int32_t firstIndex = INT32_MAX;
// remove in reverse order to minimize copying
@@ -177,6 +185,7 @@ InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorRes
void
InternalHeaders::Clear()
{
+ SetListDirty();
mList.Clear();
}
@@ -419,5 +428,54 @@ InternalHeaders::GetUnsafeHeaders(nsTArray<nsCString>& aNames) const
}
}
+void
+InternalHeaders::MaybeSortList()
+{
+ class Comparator {
+ public:
+ bool Equals(const Entry& aA, const Entry& aB) const
+ {
+ return aA.mName == aB.mName;
+ }
+
+ bool LessThan(const Entry& aA, const Entry& aB) const
+ {
+ return aA.mName < aB.mName;
+ }
+ };
+
+ if (!mListDirty) {
+ return;
+ }
+
+ mListDirty = false;
+
+ Comparator comparator;
+
+ mSortedList.Clear();
+ for (const Entry& entry : mList) {
+ bool found = false;
+ for (Entry& sortedEntry : mSortedList) {
+ if (sortedEntry.mName == entry.mName) {
+ sortedEntry.mValue += ", ";
+ sortedEntry.mValue += entry.mValue;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ mSortedList.InsertElementSorted(entry, comparator);
+ }
+ }
+}
+
+void
+InternalHeaders::SetListDirty()
+{
+ mSortedList.Clear();
+ mListDirty = true;
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/fetch/InternalHeaders.h b/dom/fetch/InternalHeaders.h
index e47066669..9a6d6dae7 100644
--- a/dom/fetch/InternalHeaders.h
+++ b/dom/fetch/InternalHeaders.h
@@ -45,14 +45,23 @@ private:
HeadersGuardEnum mGuard;
nsTArray<Entry> mList;
+ nsTArray<Entry> mSortedList;
+
+ // This boolean is set to true at any writing operation to mList. It's set to
+ // false when mSortedList is regenerated. This happens when the header is
+ // iterated.
+ bool mListDirty;
+
public:
explicit InternalHeaders(HeadersGuardEnum aGuard = HeadersGuardEnum::None)
: mGuard(aGuard)
+ , mListDirty(false)
{
}
explicit InternalHeaders(const InternalHeaders& aOther)
: mGuard(HeadersGuardEnum::None)
+ , mListDirty(true)
{
ErrorResult result;
Fill(aOther, result);
@@ -79,19 +88,22 @@ public:
bool Has(const nsACString& aName, ErrorResult& aRv) const;
void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
- uint32_t GetIterableLength() const
+ uint32_t GetIterableLength()
{
- return mList.Length();
+ MaybeSortList();
+ return mSortedList.Length();
}
- const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex) const
+ const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex)
{
- MOZ_ASSERT(aIndex < mList.Length());
- return NS_ConvertASCIItoUTF16(mList[aIndex].mName);
+ MaybeSortList();
+ MOZ_ASSERT(aIndex < mSortedList.Length());
+ return NS_ConvertASCIItoUTF16(mSortedList[aIndex].mName);
}
- const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex) const
+ const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex)
{
- MOZ_ASSERT(aIndex < mList.Length());
- return NS_ConvertASCIItoUTF16(mList[aIndex].mValue);
+ MaybeSortList();
+ MOZ_ASSERT(aIndex < mSortedList.Length());
+ return NS_ConvertASCIItoUTF16(mSortedList[aIndex].mValue);
}
void Clear();
@@ -152,6 +164,9 @@ private:
const nsACString& aValue);
static bool IsRevalidationHeader(const nsACString& aName);
+
+ void MaybeSortList();
+ void SetListDirty();
};
} // namespace dom
diff --git a/dom/fetch/InternalRequest.cpp b/dom/fetch/InternalRequest.cpp
index 85feabde3..b2631da6a 100644
--- a/dom/fetch/InternalRequest.cpp
+++ b/dom/fetch/InternalRequest.cpp
@@ -320,6 +320,9 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
case nsIContentPolicy::TYPE_WEB_MANIFEST:
context = RequestContext::Manifest;
break;
+ case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
+ context = RequestContext::Internal;
+ break;
default:
MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
break;
diff --git a/dom/fetch/InternalRequest.h b/dom/fetch/InternalRequest.h
index 84ee0bf69..966490675 100644
--- a/dom/fetch/InternalRequest.h
+++ b/dom/fetch/InternalRequest.h
@@ -53,7 +53,7 @@ namespace dom {
* image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD, TYPE_INTERNAL_IMAGE_FAVICON
* imageset | TYPE_IMAGESET
* import | Not supported by Gecko
- * internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER
+ * internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER, TYPE_SAVEAS_DOWNLOAD
* location |
* manifest | TYPE_WEB_MANIFEST
* object | TYPE_INTERNAL_OBJECT
diff --git a/dom/fetch/Request.cpp b/dom/fetch/Request.cpp
index bc17afae3..7ca5b43c4 100644
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -327,7 +327,7 @@ Request::Constructor(const GlobalObject& aGlobal,
RequestCache fallbackCache = RequestCache::EndGuard_;
if (aInput.IsUSVString()) {
fallbackMode = RequestMode::Cors;
- fallbackCredentials = RequestCredentials::Omit;
+ fallbackCredentials = RequestCredentials::Same_origin;
fallbackCache = RequestCache::Default;
}
@@ -338,8 +338,7 @@ Request::Constructor(const GlobalObject& aGlobal,
if (mode == RequestMode::Navigate ||
(aInit.IsAnyMemberPresent() && request->Mode() == RequestMode::Navigate)) {
- aRv.ThrowTypeError<MSG_INVALID_REQUEST_MODE>(NS_LITERAL_STRING("navigate"));
- return nullptr;
+ mode = RequestMode::Same_origin;
}
if (aInit.IsAnyMemberPresent()) {
@@ -374,11 +373,7 @@ Request::Constructor(const GlobalObject& aGlobal,
nsresult rv = principal->CheckMayLoad(uri, /* report */ false,
/* allowIfInheritsPrincipal */ false);
if (NS_FAILED(rv)) {
- nsAutoCString globalOrigin;
- principal->GetOrigin(globalOrigin);
- aRv.ThrowTypeError<MSG_CROSS_ORIGIN_REFERRER_URL>(referrer,
- NS_ConvertUTF8toUTF16(globalOrigin));
- return nullptr;
+ referrerURL.AssignLiteral(kFETCH_CLIENT_REFERRER_STR);
}
}
}
@@ -403,11 +398,10 @@ Request::Constructor(const GlobalObject& aGlobal,
// this work in a single sync loop.
RefPtr<ReferrerSameOriginChecker> checker =
new ReferrerSameOriginChecker(worker, referrerURL, rv);
- checker->Dispatch(aRv);
- if (aRv.Failed() || NS_FAILED(rv)) {
- aRv.ThrowTypeError<MSG_CROSS_ORIGIN_REFERRER_URL>(referrer,
- worker->GetLocationInfo().mOrigin);
- return nullptr;
+ IgnoredErrorResult error;
+ checker->Dispatch(Terminating, error);
+ if (error.Failed() || NS_FAILED(rv)) {
+ referrerURL.AssignLiteral(kFETCH_CLIENT_REFERRER_STR);
}
}
}
diff --git a/dom/fetch/Response.cpp b/dom/fetch/Response.cpp
index a76071bf8..3b3ada6d3 100644
--- a/dom/fetch/Response.cpp
+++ b/dom/fetch/Response.cpp
@@ -104,7 +104,7 @@ Response::Redirect(const GlobalObject& aGlobal, const nsAString& aUrl,
return nullptr;
}
- Optional<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams> body;
+ Optional<Nullable<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>> body;
ResponseInit init;
init.mStatus = aStatus;
RefPtr<Response> r = Response::Constructor(aGlobal, body, init, aRv);
@@ -125,7 +125,7 @@ Response::Redirect(const GlobalObject& aGlobal, const nsAString& aUrl,
/*static*/ already_AddRefed<Response>
Response::Constructor(const GlobalObject& aGlobal,
- const Optional<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& aBody,
+ const Optional<Nullable<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>>& aBody,
const ResponseInit& aInit, ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
@@ -191,7 +191,7 @@ Response::Constructor(const GlobalObject& aGlobal,
}
}
- if (aBody.WasPassed()) {
+ if (aBody.WasPassed() && !aBody.Value().IsNull()) {
if (aInit.mStatus == 204 || aInit.mStatus == 205 || aInit.mStatus == 304) {
aRv.ThrowTypeError<MSG_RESPONSE_NULL_STATUS_WITH_BODY>();
return nullptr;
@@ -200,7 +200,7 @@ Response::Constructor(const GlobalObject& aGlobal,
nsCOMPtr<nsIInputStream> bodyStream;
nsCString contentType;
uint64_t bodySize = 0;
- aRv = ExtractByteStreamFromBody(aBody.Value(),
+ aRv = ExtractByteStreamFromBody(aBody.Value().Value(),
getter_AddRefs(bodyStream),
contentType,
bodySize);
diff --git a/dom/fetch/Response.h b/dom/fetch/Response.h
index 64b3c5f45..de367bef6 100644
--- a/dom/fetch/Response.h
+++ b/dom/fetch/Response.h
@@ -114,7 +114,7 @@ public:
static already_AddRefed<Response>
Constructor(const GlobalObject& aGlobal,
- const Optional<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& aBody,
+ const Optional<Nullable<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>>& aBody,
const ResponseInit& aInit, ErrorResult& rv);
nsIGlobalObject* GetParentObject() const
diff --git a/dom/filesystem/tests/test_webkitdirectory.html b/dom/filesystem/tests/test_webkitdirectory.html
index 825f5e8fb..591619e45 100644
--- a/dom/filesystem/tests/test_webkitdirectory.html
+++ b/dom/filesystem/tests/test_webkitdirectory.html
@@ -152,6 +152,7 @@ function test_changeDataWhileWorking() {
function test_setup() {
SpecialPowers.pushPrefEnv({"set": [["dom.input.dirpicker", true],
+ ["dom.filesystem.pathcheck.disabled", true],
["dom.webkitBlink.dirPicker.enabled", true]]}, next);
}
diff --git a/dom/geolocation/moz.build b/dom/geolocation/moz.build
index bb3fcb583..4339d5a7f 100644
--- a/dom/geolocation/moz.build
+++ b/dom/geolocation/moz.build
@@ -30,10 +30,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
LOCAL_INCLUDES += [
'/dom/system/android',
]
-elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- LOCAL_INCLUDES += [
- '/dom/system/gonk',
- ]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/dom/system/mac',
diff --git a/dom/geolocation/nsGeolocation.cpp b/dom/geolocation/nsGeolocation.cpp
index 9fcdb350a..2d84a3e11 100644
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/nsGeolocation.cpp
@@ -33,10 +33,6 @@ class nsIPrincipal;
#include "AndroidLocationProvider.h"
#endif
-#ifdef MOZ_WIDGET_GONK
-#include "GonkGPSGeolocationProvider.h"
-#endif
-
#ifdef MOZ_GPSD
#include "GpsdLocationProvider.h"
#endif
@@ -688,15 +684,6 @@ nsresult nsGeolocationService::Init()
mProvider = new AndroidLocationProvider();
#endif
-#ifdef MOZ_WIDGET_GONK
- // GonkGPSGeolocationProvider can be started at boot up time for initialization reasons.
- // do_getService gets hold of the already initialized component and starts
- // processing location requests immediately.
- // do_Createinstance will create multiple instances of the provider which is not right.
- // bug 993041
- mProvider = do_GetService(GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID);
-#endif
-
#ifdef MOZ_WIDGET_GTK
#ifdef MOZ_GPSD
if (Preferences::GetBool("geo.provider.use_gpsd", false)) {
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index d46eccdbc..e9086933b 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -114,15 +114,12 @@
#include <limits>
#include "nsIColorPicker.h"
-#include "nsIDatePicker.h"
#include "nsIStringEnumerator.h"
#include "HTMLSplitOnSpacesTokenizer.h"
#include "nsIController.h"
#include "nsIMIMEInfo.h"
#include "nsFrameSelection.h"
-#include "nsIConsoleService.h"
-
// input type=date
#include "js/Date.h"
@@ -543,9 +540,8 @@ GetDOMFileOrDirectoryPath(const OwningFileOrDirectory& aData,
bool
HTMLInputElement::ValueAsDateEnabled(JSContext* cx, JSObject* obj)
{
- return Preferences::GetBool("dom.experimental_forms", false) ||
- Preferences::GetBool("dom.forms.datepicker", false) ||
- Preferences::GetBool("dom.forms.datetime", false);
+ return IsExperimentalFormsEnabled() || IsInputDateTimeEnabled() ||
+ IsInputDateTimeOthersEnabled();
}
NS_IMETHODIMP
@@ -628,7 +624,7 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
RefPtr<DispatchChangeEventCallback> dispatchChangeEventCallback =
new DispatchChangeEventCallback(mInput);
- if (Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
+ if (IsWebkitDirPickerEnabled() &&
mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory)) {
ErrorResult error;
GetFilesHelper* helper = mInput->GetOrCreateGetFilesHelper(true, error);
@@ -747,59 +743,6 @@ nsColorPickerShownCallback::Done(const nsAString& aColor)
NS_IMPL_ISUPPORTS(nsColorPickerShownCallback, nsIColorPickerShownCallback)
-class DatePickerShownCallback final : public nsIDatePickerShownCallback
-{
- ~DatePickerShownCallback() {}
-public:
- DatePickerShownCallback(HTMLInputElement* aInput,
- nsIDatePicker* aDatePicker)
- : mInput(aInput)
- , mDatePicker(aDatePicker)
- {}
-
- NS_DECL_ISUPPORTS
-
- NS_IMETHOD Done(const nsAString& aDate) override;
- NS_IMETHOD Cancel() override;
-
-private:
- RefPtr<HTMLInputElement> mInput;
- nsCOMPtr<nsIDatePicker> mDatePicker;
-};
-
-NS_IMETHODIMP
-DatePickerShownCallback::Cancel()
-{
- mInput->PickerClosed();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DatePickerShownCallback::Done(const nsAString& aDate)
-{
- nsAutoString oldValue;
-
- mInput->PickerClosed();
- mInput->GetValue(oldValue);
-
- if(!oldValue.Equals(aDate)){
- mInput->SetValue(aDate);
- nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
- static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
- NS_LITERAL_STRING("input"), true,
- false);
- return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
- static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
- NS_LITERAL_STRING("change"), true,
- false);
- }
-
- return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(DatePickerShownCallback, nsIDatePickerShownCallback)
-
-
bool
HTMLInputElement::IsPopupBlocked() const
{
@@ -825,56 +768,6 @@ HTMLInputElement::IsPopupBlocked() const
}
nsresult
-HTMLInputElement::InitDatePicker()
-{
- if (!Preferences::GetBool("dom.forms.datepicker", false)) {
- return NS_OK;
- }
-
- if (mPickerRunning) {
- NS_WARNING("Just one nsIDatePicker is allowed");
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDocument> doc = OwnerDoc();
-
- nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
- if (!win) {
- return NS_ERROR_FAILURE;
- }
-
- if (IsPopupBlocked()) {
- win->FirePopupBlockedEvent(doc, nullptr, EmptyString(), EmptyString());
- return NS_OK;
- }
-
- // Get Loc title
- nsXPIDLString title;
- nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
- "DatePicker", title);
-
- nsresult rv;
- nsCOMPtr<nsIDatePicker> datePicker = do_CreateInstance("@mozilla.org/datepicker;1", &rv);
- if (!datePicker) {
- return rv;
- }
-
- nsAutoString initialValue;
- GetValueInternal(initialValue);
- rv = datePicker->Init(win, title, initialValue);
-
- nsCOMPtr<nsIDatePickerShownCallback> callback =
- new DatePickerShownCallback(this, datePicker);
-
- rv = datePicker->Open(callback);
- if (NS_SUCCEEDED(rv)) {
- mPickerRunning = true;
- }
-
- return rv;
-}
-
-nsresult
HTMLInputElement::InitColorPicker()
{
if (mPickerRunning) {
@@ -1066,13 +959,6 @@ UploadLastDir::FetchDirectoryAndDisplayPicker(nsIDocument* aDoc,
nsCOMPtr<nsIContentPrefCallback2> prefCallback =
new UploadLastDir::ContentPrefCallback(aFilePicker, aFpCallback);
-#ifdef MOZ_B2G
- if (XRE_IsContentProcess()) {
- prefCallback->HandleCompletion(nsIContentPrefCallback2::COMPLETE_ERROR);
- return NS_OK;
- }
-#endif
-
// Attempt to get the CPS, if it's not present we'll fallback to use the Desktop folder
nsCOMPtr<nsIContentPrefService2> contentPrefService =
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
@@ -1097,12 +983,6 @@ UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir)
return NS_OK;
}
-#ifdef MOZ_B2G
- if (XRE_IsContentProcess()) {
- return NS_OK;
- }
-#endif
-
nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI();
NS_PRECONDITION(docURI, "docURI is null");
@@ -1919,6 +1799,22 @@ HTMLInputElement::ConvertStringToNumber(nsAString& aValue,
aResultValue = Decimal::fromDouble(days * kMsPerDay);
return true;
}
+ case NS_FORM_INPUT_DATETIME_LOCAL:
+ {
+ uint32_t year, month, day, timeInMs;
+ if (!ParseDateTimeLocal(aValue, &year, &month, &day, &timeInMs)) {
+ return false;
+ }
+
+ JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, day,
+ timeInMs));
+ if (!time.isValid()) {
+ return false;
+ }
+
+ aResultValue = Decimal::fromDouble(time.toDouble());
+ return true;
+ }
default:
MOZ_ASSERT(false, "Unrecognized input type");
return false;
@@ -2108,21 +2004,17 @@ HTMLInputElement::ConvertNumberToString(Decimal aValue,
}
case NS_FORM_INPUT_TIME:
{
+ aValue = aValue.floor();
// Per spec, we need to truncate |aValue| and we should only represent
// times inside a day [00:00, 24:00[, which means that we should do a
// modulo on |aValue| using the number of milliseconds in a day (86400000).
- uint32_t value = NS_floorModulo(aValue.floor(), Decimal(86400000)).toDouble();
-
- uint16_t milliseconds = value % 1000;
- value /= 1000;
+ uint32_t value =
+ NS_floorModulo(aValue, Decimal::fromDouble(kMsPerDay)).toDouble();
- uint8_t seconds = value % 60;
- value /= 60;
-
- uint8_t minutes = value % 60;
- value /= 60;
-
- uint8_t hours = value;
+ uint16_t milliseconds, seconds, minutes, hours;
+ if (!GetTimeFromMs(value, &hours, &minutes, &seconds, &milliseconds)) {
+ return false;
+ }
if (milliseconds != 0) {
aResultString.AppendPrintf("%02d:%02d:%02d.%03d",
@@ -2192,6 +2084,42 @@ HTMLInputElement::ConvertNumberToString(Decimal aValue,
aResultString.AppendPrintf("%04.0f-W%02d", year, week);
return true;
}
+ case NS_FORM_INPUT_DATETIME_LOCAL:
+ {
+ aValue = aValue.floor();
+
+ uint32_t timeValue =
+ NS_floorModulo(aValue, Decimal::fromDouble(kMsPerDay)).toDouble();
+
+ uint16_t milliseconds, seconds, minutes, hours;
+ if (!GetTimeFromMs(timeValue,
+ &hours, &minutes, &seconds, &milliseconds)) {
+ return false;
+ }
+
+ double year = JS::YearFromTime(aValue.toDouble());
+ double month = JS::MonthFromTime(aValue.toDouble());
+ double day = JS::DayFromTime(aValue.toDouble());
+
+ if (IsNaN(year) || IsNaN(month) || IsNaN(day)) {
+ return false;
+ }
+
+ if (milliseconds != 0) {
+ aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d:%02d.%03d",
+ year, month + 1, day, hours, minutes,
+ seconds, milliseconds);
+ } else if (seconds != 0) {
+ aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d:%02d",
+ year, month + 1, day, hours, minutes,
+ seconds);
+ } else {
+ aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d",
+ year, month + 1, day, hours, minutes);
+ }
+
+ return true;
+ }
default:
MOZ_ASSERT(false, "Unrecognized input type");
return false;
@@ -2202,8 +2130,7 @@ HTMLInputElement::ConvertNumberToString(Decimal aValue,
Nullable<Date>
HTMLInputElement::GetValueAsDate(ErrorResult& aRv)
{
- // TODO: this is temporary until bug 888331 is fixed.
- if (!IsDateTimeInputType(mType) || mType == NS_FORM_INPUT_DATETIME_LOCAL) {
+ if (!IsDateTimeInputType(mType)) {
return Nullable<Date>();
}
@@ -2261,6 +2188,19 @@ HTMLInputElement::GetValueAsDate(ErrorResult& aRv)
return Nullable<Date>(Date(time));
}
+ case NS_FORM_INPUT_DATETIME_LOCAL:
+ {
+ uint32_t year, month, day, timeInMs;
+ nsAutoString value;
+ GetValueInternal(value);
+ if (!ParseDateTimeLocal(value, &year, &month, &day, &timeInMs)) {
+ return Nullable<Date>();
+ }
+
+ JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, day,
+ timeInMs));
+ return Nullable<Date>(Date(time));
+ }
}
MOZ_ASSERT(false, "Unrecognized input type");
@@ -2271,8 +2211,7 @@ HTMLInputElement::GetValueAsDate(ErrorResult& aRv)
void
HTMLInputElement::SetValueAsDate(Nullable<Date> aDate, ErrorResult& aRv)
{
- // TODO: this is temporary until bug 888331 is fixed.
- if (!IsDateTimeInputType(mType) || mType == NS_FORM_INPUT_DATETIME_LOCAL) {
+ if (!IsDateTimeInputType(mType)) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
@@ -2380,11 +2319,8 @@ HTMLInputElement::GetMaximum() const
Decimal
HTMLInputElement::GetStepBase() const
{
- MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER ||
- mType == NS_FORM_INPUT_DATE ||
- mType == NS_FORM_INPUT_TIME ||
- mType == NS_FORM_INPUT_MONTH ||
- mType == NS_FORM_INPUT_WEEK ||
+ MOZ_ASSERT(IsDateTimeInputType(mType) ||
+ mType == NS_FORM_INPUT_NUMBER ||
mType == NS_FORM_INPUT_RANGE,
"Check that kDefaultStepBase is correct for this new type");
@@ -2515,11 +2451,8 @@ HTMLInputElement::ApplyStep(int32_t aStep)
bool
HTMLInputElement::IsExperimentalMobileType(uint8_t aType)
{
- return (aType == NS_FORM_INPUT_DATE &&
- !Preferences::GetBool("dom.forms.datetime", false) &&
- !Preferences::GetBool("dom.forms.datepicker", false)) ||
- (aType == NS_FORM_INPUT_TIME &&
- !Preferences::GetBool("dom.forms.datetime", false));
+ return (aType == NS_FORM_INPUT_DATE || aType == NS_FORM_INPUT_TIME) &&
+ !IsInputDateTimeEnabled();
}
bool
@@ -2832,7 +2765,8 @@ HTMLInputElement::GetOwnerDateTimeControl()
HTMLInputElement::FromContentOrNull(
GetParent()->GetParent()->GetParent()->GetParent());
if (ownerDateTimeControl &&
- ownerDateTimeControl->mType == NS_FORM_INPUT_TIME) {
+ (ownerDateTimeControl->mType == NS_FORM_INPUT_TIME ||
+ ownerDateTimeControl->mType == NS_FORM_INPUT_DATE)) {
return ownerDateTimeControl;
}
}
@@ -3024,8 +2958,8 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
nsXPIDLString value;
if (mFilesOrDirectories.IsEmpty()) {
- if ((Preferences::GetBool("dom.input.dirpicker", false) && Allowdirs()) ||
- (Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
+ if ((IsDirPickerEnabled() && Allowdirs()) ||
+ (IsWebkitDirPickerEnabled() &&
HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory))) {
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
"NoDirSelected", value);
@@ -3054,7 +2988,7 @@ HTMLInputElement::SetFilesOrDirectories(const nsTArray<OwningFileOrDirectory>& a
{
ClearGetFilesHelpers();
- if (Preferences::GetBool("dom.webkitBlink.filesystem.enabled", false)) {
+ if (IsWebkitFileSystemEnabled()) {
HTMLInputElementBinding::ClearCachedWebkitEntriesValue(this);
mEntries.Clear();
}
@@ -3073,7 +3007,7 @@ HTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
mFilesOrDirectories.Clear();
ClearGetFilesHelpers();
- if (Preferences::GetBool("dom.webkitBlink.filesystem.enabled", false)) {
+ if (IsWebkitFileSystemEnabled()) {
HTMLInputElementBinding::ClearCachedWebkitEntriesValue(this);
mEntries.Clear();
}
@@ -3096,14 +3030,14 @@ HTMLInputElement::MozSetDndFilesAndDirectories(const nsTArray<OwningFileOrDirect
{
SetFilesOrDirectories(aFilesOrDirectories, true);
- if (Preferences::GetBool("dom.webkitBlink.filesystem.enabled", false)) {
+ if (IsWebkitFileSystemEnabled()) {
UpdateEntries(aFilesOrDirectories);
}
RefPtr<DispatchChangeEventCallback> dispatchChangeEventCallback =
new DispatchChangeEventCallback(this);
- if (Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
+ if (IsWebkitDirPickerEnabled() &&
HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory)) {
ErrorResult rv;
GetFilesHelper* helper = GetOrCreateGetFilesHelper(true /* recursionFlag */,
@@ -3181,8 +3115,8 @@ HTMLInputElement::GetFiles()
return nullptr;
}
- if (Preferences::GetBool("dom.input.dirpicker", false) && Allowdirs() &&
- (!Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) ||
+ if (IsDirPickerEnabled() && Allowdirs() &&
+ (!IsWebkitDirPickerEnabled() ||
!HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory))) {
return nullptr;
}
@@ -3282,7 +3216,8 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue, uint32_t aFlags)
if (frame) {
frame->UpdateForValueChange();
}
- } else if (mType == NS_FORM_INPUT_TIME &&
+ } else if ((mType == NS_FORM_INPUT_TIME ||
+ mType == NS_FORM_INPUT_DATE) &&
!IsExperimentalMobileType(mType)) {
nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
@@ -3591,7 +3526,8 @@ HTMLInputElement::Blur(ErrorResult& aError)
}
}
- if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType)) {
+ if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
+ !IsExperimentalMobileType(mType)) {
nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
frame->HandleBlurEvent();
@@ -3610,7 +3546,8 @@ HTMLInputElement::Focus(ErrorResult& aError)
nsNumberControlFrame* numberControlFrame =
do_QueryFrame(GetPrimaryFrame());
if (numberControlFrame) {
- HTMLInputElement* textControl = numberControlFrame->GetAnonTextControl();
+ RefPtr<HTMLInputElement> textControl =
+ numberControlFrame->GetAnonTextControl();
if (textControl) {
textControl->Focus(aError);
return;
@@ -3618,7 +3555,8 @@ HTMLInputElement::Focus(ErrorResult& aError)
}
}
- if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType)) {
+ if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
+ !IsExperimentalMobileType(mType)) {
nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
frame->HandleFocusEvent();
@@ -3956,7 +3894,7 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
}
}
- if (mType == NS_FORM_INPUT_TIME &&
+ if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
!IsExperimentalMobileType(mType) &&
aVisitor.mEvent->mMessage == eFocus &&
aVisitor.mEvent->mOriginalTarget == this) {
@@ -4083,7 +4021,8 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
// Stop the event if the related target's first non-native ancestor is the
// same as the original target's first non-native ancestor (we are moving
// inside of the same element).
- if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType) &&
+ if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
+ !IsExperimentalMobileType(mType) &&
(aVisitor.mEvent->mMessage == eFocus ||
aVisitor.mEvent->mMessage == eFocusIn ||
aVisitor.mEvent->mMessage == eFocusOut ||
@@ -4361,8 +4300,8 @@ HTMLInputElement::MaybeInitPickers(EventChainPostVisitor& aVisitor)
do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
if (target &&
target->FindFirstNonChromeOnlyAccessContent() == this &&
- ((Preferences::GetBool("dom.input.dirpicker", false) && Allowdirs()) ||
- (Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
+ ((IsDirPickerEnabled() && Allowdirs()) ||
+ (IsWebkitDirPickerEnabled() &&
HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory)))) {
type = FILE_PICKER_DIRECTORY;
}
@@ -4371,9 +4310,6 @@ HTMLInputElement::MaybeInitPickers(EventChainPostVisitor& aVisitor)
if (mType == NS_FORM_INPUT_COLOR) {
return InitColorPicker();
}
- if (mType == NS_FORM_INPUT_DATE) {
- return InitDatePicker();
- }
return NS_OK;
}
@@ -5383,6 +5319,29 @@ HTMLInputElement::MaximumWeekInYear(uint32_t aYear) const
}
bool
+HTMLInputElement::GetTimeFromMs(double aValue, uint16_t* aHours,
+ uint16_t* aMinutes, uint16_t* aSeconds,
+ uint16_t* aMilliseconds) const {
+ MOZ_ASSERT(aValue >= 0 && aValue < kMsPerDay,
+ "aValue must be milliseconds within a day!");
+
+ uint32_t value = floor(aValue);
+
+ *aMilliseconds = value % 1000;
+ value /= 1000;
+
+ *aSeconds = value % 60;
+ value /= 60;
+
+ *aMinutes = value % 60;
+ value /= 60;
+
+ *aHours = value;
+
+ return true;
+}
+
+bool
HTMLInputElement::IsValidWeek(const nsAString& aValue) const
{
uint32_t year, week;
@@ -5730,20 +5689,131 @@ HTMLInputElement::ParseTime(const nsAString& aValue, uint32_t* aResult)
return true;
}
-static bool
-IsDateTimeEnabled(int32_t aNewType)
+/* static */ bool
+HTMLInputElement::IsDateTimeTypeSupported(uint8_t aDateTimeInputType)
+{
+ return ((aDateTimeInputType == NS_FORM_INPUT_DATE ||
+ aDateTimeInputType == NS_FORM_INPUT_TIME) &&
+ (IsInputDateTimeEnabled() || IsExperimentalFormsEnabled())) ||
+ ((aDateTimeInputType == NS_FORM_INPUT_MONTH ||
+ aDateTimeInputType == NS_FORM_INPUT_WEEK ||
+ aDateTimeInputType == NS_FORM_INPUT_DATETIME_LOCAL) &&
+ IsInputDateTimeOthersEnabled());
+}
+
+/* static */ bool
+HTMLInputElement::IsWebkitDirPickerEnabled()
{
- return (aNewType == NS_FORM_INPUT_DATE &&
- (Preferences::GetBool("dom.forms.datetime", false) ||
- Preferences::GetBool("dom.experimental_forms", false) ||
- Preferences::GetBool("dom.forms.datepicker", false))) ||
- (aNewType == NS_FORM_INPUT_TIME &&
- (Preferences::GetBool("dom.forms.datetime", false) ||
- Preferences::GetBool("dom.experimental_forms", false))) ||
- ((aNewType == NS_FORM_INPUT_MONTH ||
- aNewType == NS_FORM_INPUT_WEEK ||
- aNewType == NS_FORM_INPUT_DATETIME_LOCAL) &&
- Preferences::GetBool("dom.forms.datetime", false));
+ static bool sWebkitDirPickerEnabled = false;
+ static bool sWebkitDirPickerPrefCached = false;
+ if (!sWebkitDirPickerPrefCached) {
+ sWebkitDirPickerPrefCached = true;
+ Preferences::AddBoolVarCache(&sWebkitDirPickerEnabled,
+ "dom.webkitBlink.dirPicker.enabled",
+ false);
+ }
+
+ return sWebkitDirPickerEnabled;
+}
+
+/* static */ bool
+HTMLInputElement::IsWebkitFileSystemEnabled()
+{
+ static bool sWebkitFileSystemEnabled = false;
+ static bool sWebkitFileSystemPrefCached = false;
+ if (!sWebkitFileSystemPrefCached) {
+ sWebkitFileSystemPrefCached = true;
+ Preferences::AddBoolVarCache(&sWebkitFileSystemEnabled,
+ "dom.webkitBlink.filesystem.enabled",
+ false);
+ }
+
+ return sWebkitFileSystemEnabled;
+}
+
+/* static */ bool
+HTMLInputElement::IsDirPickerEnabled()
+{
+ static bool sDirPickerEnabled = false;
+ static bool sDirPickerPrefCached = false;
+ if (!sDirPickerPrefCached) {
+ sDirPickerPrefCached = true;
+ Preferences::AddBoolVarCache(&sDirPickerEnabled, "dom.input.dirpicker",
+ false);
+ }
+
+ return sDirPickerEnabled;
+}
+
+/* static */ bool
+HTMLInputElement::IsExperimentalFormsEnabled()
+{
+ static bool sExperimentalFormsEnabled = false;
+ static bool sExperimentalFormsPrefCached = false;
+ if (!sExperimentalFormsPrefCached) {
+ sExperimentalFormsPrefCached = true;
+ Preferences::AddBoolVarCache(&sExperimentalFormsEnabled,
+ "dom.experimental_forms",
+ false);
+ }
+
+ return sExperimentalFormsEnabled;
+}
+
+/* static */ bool
+HTMLInputElement::IsInputDateTimeEnabled()
+{
+ static bool sDateTimeEnabled = false;
+ static bool sDateTimePrefCached = false;
+ if (!sDateTimePrefCached) {
+ sDateTimePrefCached = true;
+ Preferences::AddBoolVarCache(&sDateTimeEnabled, "dom.forms.datetime",
+ false);
+ }
+
+ return sDateTimeEnabled;
+}
+
+/* static */ bool
+HTMLInputElement::IsInputDateTimeOthersEnabled()
+{
+ static bool sDateTimeOthersEnabled = false;
+ static bool sDateTimeOthersPrefCached = false;
+ if (!sDateTimeOthersPrefCached) {
+ sDateTimeOthersPrefCached = true;
+ Preferences::AddBoolVarCache(&sDateTimeOthersEnabled,
+ "dom.forms.datetime.others", false);
+ }
+
+ return sDateTimeOthersEnabled;
+}
+
+/* static */ bool
+HTMLInputElement::IsInputNumberEnabled()
+{
+ static bool sInputNumberEnabled = false;
+ static bool sInputNumberPrefCached = false;
+ if (!sInputNumberPrefCached) {
+ sInputNumberPrefCached = true;
+ Preferences::AddBoolVarCache(&sInputNumberEnabled, "dom.forms.number",
+ false);
+ }
+
+ return sInputNumberEnabled;
+}
+
+/* static */ bool
+HTMLInputElement::IsInputColorEnabled()
+{
+ static bool sInputColorEnabled = false;
+ static bool sInputColorPrefCached = false;
+ if (!sInputColorPrefCached) {
+ sInputColorPrefCached = true;
+ Preferences::AddBoolVarCache(&sInputColorEnabled, "dom.forms.color",
+ false);
+ }
+
+ return sInputColorEnabled;
}
bool
@@ -5760,13 +5830,9 @@ HTMLInputElement::ParseAttribute(int32_t aNamespaceID,
bool success = aResult.ParseEnumValue(aValue, kInputTypeTable, false);
if (success) {
newType = aResult.GetEnumValue();
- if ((IsExperimentalMobileType(newType) &&
- !Preferences::GetBool("dom.experimental_forms", false)) ||
- (newType == NS_FORM_INPUT_NUMBER &&
- !Preferences::GetBool("dom.forms.number", false)) ||
- (newType == NS_FORM_INPUT_COLOR &&
- !Preferences::GetBool("dom.forms.color", false)) ||
- (IsDateTimeInputType(newType) && !IsDateTimeEnabled(newType))) {
+ if ((newType == NS_FORM_INPUT_NUMBER && !IsInputNumberEnabled()) ||
+ (newType == NS_FORM_INPUT_COLOR && !IsInputColorEnabled()) ||
+ (IsDateTimeInputType(newType) && !IsDateTimeTypeSupported(newType))) {
newType = kInputDefaultType->value;
aResult.SetTo(newType, &aValue);
}
@@ -5935,7 +6001,7 @@ HTMLInputElement::ChooseDirectory(ErrorResult& aRv)
// "Pick Folder..." button on platforms that don't have a directory picker
// we have to redirect to the file picker here.
InitFilePicker(
-#if defined(ANDROID) || defined(MOZ_B2G)
+#if defined(ANDROID)
// No native directory picker - redirect to plain file picker
FILE_PICKER_FILE
#else
@@ -7161,13 +7227,15 @@ HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t*
if (mType == NS_FORM_INPUT_FILE ||
mType == NS_FORM_INPUT_NUMBER ||
- mType == NS_FORM_INPUT_TIME) {
+ mType == NS_FORM_INPUT_TIME ||
+ mType == NS_FORM_INPUT_DATE) {
if (aTabIndex) {
// We only want our native anonymous child to be tabable to, not ourself.
*aTabIndex = -1;
}
if (mType == NS_FORM_INPUT_NUMBER ||
- mType == NS_FORM_INPUT_TIME) {
+ mType == NS_FORM_INPUT_TIME ||
+ mType == NS_FORM_INPUT_DATE) {
*aIsFocusable = true;
} else {
*aIsFocusable = defaultFocusable;
@@ -7650,8 +7718,7 @@ HTMLInputElement::HasPatternMismatch() const
bool
HTMLInputElement::IsRangeOverflow() const
{
- // TODO: this is temporary until bug 888331 is fixed.
- if (!DoesMinMaxApply() || mType == NS_FORM_INPUT_DATETIME_LOCAL) {
+ if (!DoesMinMaxApply()) {
return false;
}
@@ -7671,8 +7738,7 @@ HTMLInputElement::IsRangeOverflow() const
bool
HTMLInputElement::IsRangeUnderflow() const
{
- // TODO: this is temporary until bug 888331 is fixed.
- if (!DoesMinMaxApply() || mType == NS_FORM_INPUT_DATETIME_LOCAL) {
+ if (!DoesMinMaxApply()) {
return false;
}
@@ -8622,6 +8688,7 @@ HTMLInputElement::GetStepScaleFactor() const
case NS_FORM_INPUT_RANGE:
return kStepScaleFactorNumberRange;
case NS_FORM_INPUT_TIME:
+ case NS_FORM_INPUT_DATETIME_LOCAL:
return kStepScaleFactorTime;
case NS_FORM_INPUT_MONTH:
return kStepScaleFactorMonth;
@@ -8646,6 +8713,7 @@ HTMLInputElement::GetDefaultStep() const
case NS_FORM_INPUT_RANGE:
return kDefaultStep;
case NS_FORM_INPUT_TIME:
+ case NS_FORM_INPUT_DATETIME_LOCAL:
return kDefaultStepTime;
default:
MOZ_ASSERT(false, "Unrecognized input type");
@@ -8680,8 +8748,7 @@ HTMLInputElement::UpdateHasRange()
mHasRange = false;
- // TODO: this is temporary until bug 888331 is fixed.
- if (!DoesMinMaxApply() || mType == NS_FORM_INPUT_DATETIME_LOCAL) {
+ if (!DoesMinMaxApply()) {
return;
}
diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h
index 9ca876aee..98a590443 100644
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -796,6 +796,15 @@ public:
void UpdateDateTimePicker(const DateTimeValue& aValue);
void CloseDateTimePicker();
+ /*
+ * The following are called from datetime input box binding to get the
+ * corresponding computed values.
+ */
+ double GetStepAsDouble() { return GetStep().toDouble(); }
+ double GetStepBaseAsDouble() { return GetStepBase().toDouble(); }
+ double GetMinimumAsDouble() { return GetMinimum().toDouble(); }
+ double GetMaximumAsDouble() { return GetMaximum().toDouble(); }
+
HTMLInputElement* GetOwnerNumberControl();
HTMLInputElement* GetOwnerDateTimeControl();
@@ -1061,11 +1070,7 @@ protected:
/**
* Returns if the step attribute apply for the current type.
*/
- bool DoesStepApply() const
- {
- // TODO: this is temporary until bug 888331 is fixed.
- return DoesMinMaxApply() && mType != NS_FORM_INPUT_DATETIME_LOCAL;
- }
+ bool DoesStepApply() const { return DoesMinMaxApply(); }
/**
* Returns if stepDown and stepUp methods apply for the current type.
@@ -1075,11 +1080,7 @@ protected:
/**
* Returns if valueAsNumber attribute applies for the current type.
*/
- bool DoesValueAsNumberApply() const
- {
- // TODO: this is temporary until bug 888331 is fixed.
- return DoesMinMaxApply() && mType != NS_FORM_INPUT_DATETIME_LOCAL;
- }
+ bool DoesValueAsNumberApply() const { return DoesMinMaxApply(); }
/**
* Returns if autocomplete attribute applies for the current type.
@@ -1287,6 +1288,7 @@ protected:
* https://html.spec.whatwg.org/multipage/infrastructure.html#valid-normalised-local-date-and-time-string
*/
void NormalizeDateTimeLocal(nsAString& aValue) const;
+
/**
* This methods returns the number of days since epoch for a given year and
* week.
@@ -1318,6 +1320,13 @@ protected:
uint32_t MaximumWeekInYear(uint32_t aYear) const;
/**
+ * This method converts aValue (milliseconds within a day) to hours, minutes,
+ * seconds and milliseconds.
+ */
+ bool GetTimeFromMs(double aValue, uint16_t* aHours, uint16_t* aMinutes,
+ uint16_t* aSeconds, uint16_t* aMilliseconds) const;
+
+ /**
* This methods returns true if it's a leap year.
*/
bool IsLeapYear(uint32_t aYear) const;
@@ -1442,7 +1451,6 @@ protected:
};
nsresult InitFilePicker(FilePickerType aType);
nsresult InitColorPicker();
- nsresult InitDatePicker();
/**
* Use this function before trying to open a picker.
@@ -1632,9 +1640,73 @@ private:
return IsSingleLineTextControl(false, aType) ||
aType == NS_FORM_INPUT_RANGE ||
aType == NS_FORM_INPUT_NUMBER ||
- aType == NS_FORM_INPUT_TIME;
+ aType == NS_FORM_INPUT_TIME ||
+ aType == NS_FORM_INPUT_DATE;
}
+ /**
+ * Checks if aDateTimeInputType should be supported based on "dom.forms.datetime",
+ * and "dom.experimental_forms".
+ */
+ static bool
+ IsDateTimeTypeSupported(uint8_t aDateTimeInputType);
+
+ /**
+ * Checks preference "dom.webkitBlink.dirPicker.enabled" to determine if
+ * webkitdirectory should be supported.
+ */
+ static bool
+ IsWebkitDirPickerEnabled();
+
+ /**
+ * Checks preference "dom.webkitBlink.filesystem.enabled" to determine if
+ * webkitEntries should be supported.
+ */
+ static bool
+ IsWebkitFileSystemEnabled();
+
+ /**
+ * Checks preference "dom.input.dirpicker" to determine if file and directory
+ * entries API should be supported.
+ */
+ static bool
+ IsDirPickerEnabled();
+
+ /**
+ * Checks preference "dom.experimental_forms" to determine if experimental
+ * implementation of input element should be enabled.
+ */
+ static bool
+ IsExperimentalFormsEnabled();
+
+ /**
+ * Checks preference "dom.forms.datetime" to determine if input date and time
+ * should be supported.
+ */
+ static bool
+ IsInputDateTimeEnabled();
+
+ /**
+ * Checks preference "dom.forms.datetime.others" to determine if input week,
+ * month and datetime-local should be supported.
+ */
+ static bool
+ IsInputDateTimeOthersEnabled();
+
+ /**
+ * Checks preference "dom.forms.number" to determine if input type=number
+ * should be supported.
+ */
+ static bool
+ IsInputNumberEnabled();
+
+ /**
+ * Checks preference "dom.forms.color" to determine if date/time related
+ * types should be supported.
+ */
+ static bool
+ IsInputColorEnabled();
+
struct nsFilePickerFilter {
nsFilePickerFilter()
: mFilterMask(0) {}
diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp
index 1f1a545fa..0b9f606f1 100644
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -817,6 +817,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mErrorSink->mError)
for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream);
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mPreCreatedTracks);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
@@ -1020,6 +1021,17 @@ void HTMLMediaElement::ShutdownDecoder()
RemoveMediaElementFromURITable();
NS_ASSERTION(mDecoder, "Must have decoder to shut down");
mWaitingForKeyListener.DisconnectIfExists();
+ for (OutputMediaStream& out : mOutputStreams) {
+ if (!out.mCapturingDecoder) {
+ continue;
+ }
+ if (!out.mStream) {
+ continue;
+ }
+ out.mNextAvailableTrackID = std::max<TrackID>(
+ mDecoder->NextAvailableTrackIDFor(out.mStream->GetInputStream()),
+ out.mNextAvailableTrackID);
+ }
mDecoder->Shutdown();
mDecoder = nullptr;
}
@@ -2730,6 +2742,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
if (mDecoder) {
out->mCapturingDecoder = true;
mDecoder->AddOutputStream(out->mStream->GetInputStream()->AsProcessedStream(),
+ out->mNextAvailableTrackID,
aFinishWhenEnded);
} else if (mSrcStream) {
out->mCapturingMediaStream = true;
@@ -2743,23 +2756,26 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
if (mDecoder) {
if (HasAudio()) {
- TrackID audioTrackId = mMediaInfo.mAudio.mTrackId;
+ TrackID audioTrackId = out->mNextAvailableTrackID++;
RefPtr<MediaStreamTrackSource> trackSource =
getter->GetMediaStreamTrackSource(audioTrackId);
RefPtr<MediaStreamTrack> track =
- out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO,
+ out->mStream->CreateDOMTrack(audioTrackId,
+ MediaSegment::AUDIO,
trackSource);
+ out->mPreCreatedTracks.AppendElement(track);
out->mStream->AddTrackInternal(track);
LOG(LogLevel::Debug,
("Created audio track %d for captured decoder", audioTrackId));
}
if (IsVideo() && HasVideo() && !out->mCapturingAudioOnly) {
- TrackID videoTrackId = mMediaInfo.mVideo.mTrackId;
+ TrackID videoTrackId = out->mNextAvailableTrackID++;
RefPtr<MediaStreamTrackSource> trackSource =
getter->GetMediaStreamTrackSource(videoTrackId);
RefPtr<MediaStreamTrack> track =
out->mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO,
trackSource);
+ out->mPreCreatedTracks.AppendElement(track);
out->mStream->AddTrackInternal(track);
LOG(LogLevel::Debug,
("Created video track %d for captured decoder", videoTrackId));
@@ -2848,6 +2864,25 @@ NS_IMETHODIMP HTMLMediaElement::GetMozAudioCaptured(bool* aCaptured)
return NS_OK;
}
+void
+HTMLMediaElement::EndPreCreatedCapturedDecoderTracks()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ for (OutputMediaStream& ms : mOutputStreams) {
+ if (!ms.mCapturingDecoder) {
+ continue;
+ }
+ for (RefPtr<MediaStreamTrack>& t : ms.mPreCreatedTracks) {
+ if (t->Ended()) {
+ continue;
+ }
+ NS_DispatchToMainThread(NewRunnableMethod(
+ t, &MediaStreamTrack::OverrideEnded));
+ }
+ ms.mPreCreatedTracks.Clear();
+ }
+}
+
class MediaElementSetForURI : public nsURIHashKey {
public:
explicit MediaElementSetForURI(const nsIURI* aKey) : nsURIHashKey(aKey) {}
@@ -3380,11 +3415,12 @@ HTMLMediaElement::WakeLockRelease()
}
HTMLMediaElement::OutputMediaStream::OutputMediaStream()
- : mFinishWhenEnded(false)
+ : mNextAvailableTrackID(1)
+ , mFinishWhenEnded(false)
, mCapturingAudioOnly(false)
, mCapturingDecoder(false)
, mCapturingMediaStream(false)
- , mNextAvailableTrackID(1) {}
+{}
HTMLMediaElement::OutputMediaStream::~OutputMediaStream()
{
@@ -4008,6 +4044,7 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
ms.mCapturingDecoder = true;
aDecoder->AddOutputStream(ms.mStream->GetInputStream()->AsProcessedStream(),
+ ms.mNextAvailableTrackID,
ms.mFinishWhenEnded);
}
diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h
index b65049206..af944a318 100644
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -675,6 +675,11 @@ public:
return mAudioCaptured;
}
+ /**
+ * Ensures any MediaStreamTracks captured from a MediaDecoder are ended.
+ */
+ void EndPreCreatedCapturedDecoderTracks();
+
void MozGetMetadata(JSContext* aCx, JS::MutableHandle<JSObject*> aResult,
ErrorResult& aRv);
@@ -815,13 +820,18 @@ protected:
~OutputMediaStream();
RefPtr<DOMMediaStream> mStream;
+ TrackID mNextAvailableTrackID;
bool mFinishWhenEnded;
bool mCapturingAudioOnly;
bool mCapturingDecoder;
bool mCapturingMediaStream;
+ // The following members are keeping state for a captured MediaDecoder.
+ // Tracks that were created on main thread before MediaDecoder fed them
+ // to the MediaStreamGraph.
+ nsTArray<RefPtr<MediaStreamTrack>> mPreCreatedTracks;
+
// The following members are keeping state for a captured MediaStream.
- TrackID mNextAvailableTrackID;
nsTArray<Pair<nsString, RefPtr<MediaInputPort>>> mTrackPorts;
};
diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
index be5a34d41..69e710242 100644
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -2149,26 +2149,10 @@ NS_IMETHODIMP
nsHTMLDocument::GetSelection(nsISelection** aReturn)
{
ErrorResult rv;
- NS_IF_ADDREF(*aReturn = GetSelection(rv));
+ NS_IF_ADDREF(*aReturn = nsDocument::GetSelection(rv));
return rv.StealNSResult();
}
-Selection*
-nsHTMLDocument::GetSelection(ErrorResult& aRv)
-{
- nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetScopeObject());
- if (!window) {
- return nullptr;
- }
-
- NS_ASSERTION(window->IsInnerWindow(), "Should have inner window here!");
- if (!window->IsCurrentInnerWindow()) {
- return nullptr;
- }
-
- return nsGlobalWindow::Cast(window)->GetSelection(aRv);
-}
-
NS_IMETHODIMP
nsHTMLDocument::CaptureEvents()
{
diff --git a/dom/html/nsHTMLDocument.h b/dom/html/nsHTMLDocument.h
index 426ebddc5..1fa81f6cd 100644
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -242,7 +242,6 @@ public:
{
// Deprecated
}
- mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aRv);
// The XPCOM CaptureEvents works fine for us.
// The XPCOM ReleaseEvents works fine for us.
// We're picking up GetLocation from Document
diff --git a/dom/html/nsIFormControl.h b/dom/html/nsIFormControl.h
index aaa92146c..34380bc67 100644
--- a/dom/html/nsIFormControl.h
+++ b/dom/html/nsIFormControl.h
@@ -267,11 +267,11 @@ nsIFormControl::IsSingleLineTextControl(bool aExcludePassword, uint32_t aType)
aType == NS_FORM_INPUT_TEL ||
aType == NS_FORM_INPUT_URL ||
// TODO: those are temporary until bug 773205 is fixed.
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
- // On Android/B2G, date/time input appears as a normal text box.
+#if defined(MOZ_WIDGET_ANDROID)
+ // On Android, date/time input appears as a normal text box.
aType == NS_FORM_INPUT_TIME ||
-#endif
aType == NS_FORM_INPUT_DATE ||
+#endif
aType == NS_FORM_INPUT_MONTH ||
aType == NS_FORM_INPUT_WEEK ||
aType == NS_FORM_INPUT_DATETIME_LOCAL ||
diff --git a/dom/html/nsTextEditorState.cpp b/dom/html/nsTextEditorState.cpp
index d70199362..187afb66d 100644
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -1418,19 +1418,16 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
}
}
- if (shouldInitializeEditor) {
- // Initialize the plaintext editor
- nsCOMPtr<nsIPlaintextEditor> textEditor(do_QueryInterface(newEditor));
- if (textEditor) {
+ // Initialize the plaintext editor
+ nsCOMPtr<nsIPlaintextEditor> textEditor = do_QueryInterface(newEditor);
+ if (textEditor) {
+ if (shouldInitializeEditor) {
// Set up wrapping
textEditor->SetWrapColumn(GetWrapCols());
-
- // Set max text field length
- int32_t maxLength;
- if (GetMaxLength(&maxLength)) {
- textEditor->SetMaxTextLength(maxLength);
- }
}
+
+ // Set max text field length
+ textEditor->SetMaxTextLength(GetMaxLength());
}
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
@@ -1895,22 +1892,22 @@ be called if @placeholder is the empty string when trimmed from line breaks");
return NS_OK;
}
-bool
-nsTextEditorState::GetMaxLength(int32_t* aMaxLength)
+int32_t
+nsTextEditorState::GetMaxLength()
{
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
nsGenericHTMLElement* element =
nsGenericHTMLElement::FromContentOrNull(content);
- NS_ENSURE_TRUE(element, false);
+ if (NS_WARN_IF(!element)) {
+ return -1;
+ }
const nsAttrValue* attr = element->GetParsedAttr(nsGkAtoms::maxlength);
if (attr && attr->Type() == nsAttrValue::eInteger) {
- *aMaxLength = attr->GetIntegerValue();
-
- return true;
+ return attr->GetIntegerValue();
}
- return false;
+ return -1;
}
void
diff --git a/dom/html/nsTextEditorState.h b/dom/html/nsTextEditorState.h
index 11494f155..caf5e8eed 100644
--- a/dom/html/nsTextEditorState.h
+++ b/dom/html/nsTextEditorState.h
@@ -203,7 +203,7 @@ public:
* @param aMaxLength the value of the max length attr
* @returns false if attr not defined
*/
- bool GetMaxLength(int32_t* aMaxLength);
+ int32_t GetMaxLength();
void ClearValueCache() { mCachedValue.Truncate(); }
diff --git a/dom/html/test/forms/mochitest.ini b/dom/html/test/forms/mochitest.ini
index 35955b189..199e4baf8 100644
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -30,8 +30,14 @@ skip-if = os == "android" # up/down arrow keys not supported on android
skip-if = android_version == '18' # Android, bug 1147974
[test_input_color_picker_update.html]
skip-if = android_version == '18' # Android, bug 1147974
+[test_input_date_key_events.html]
+skip-if = os == "android"
+[test_input_datetime_input_change_events.html]
+skip-if = os == "android"
[test_input_datetime_focus_blur.html]
skip-if = os == "android"
+[test_input_datetime_focus_blur_events.html]
+skip-if = os == "android"
[test_input_datetime_tabindex.html]
skip-if = os == "android"
[test_input_defaultValue.html]
@@ -61,8 +67,6 @@ skip-if = os == "android"
[test_input_textarea_set_value_no_scroll.html]
[test_input_time_key_events.html]
skip-if = os == "android"
-[test_input_time_focus_blur_events.html]
-skip-if = os == "android"
[test_input_types_pref.html]
[test_input_typing_sanitization.html]
[test_input_untrusted_key_events.html]
diff --git a/dom/html/test/forms/test_input_date_key_events.html b/dom/html/test/forms/test_input_date_key_events.html
new file mode 100644
index 000000000..f502d6a4d
--- /dev/null
+++ b/dom/html/test/forms/test_input_date_key_events.html
@@ -0,0 +1,228 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1286182
+-->
+<head>
+ <title>Test key events for time control</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1286182">Mozilla Bug 1286182</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="date">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+// Turn off Spatial Navigation because it hijacks arrow keydown events:
+SimpleTest.waitForFocus(function() {
+ SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
+ test();
+ SimpleTest.finish();
+ });
+});
+
+var testData = [
+ /**
+ * keys: keys to send to the input element.
+ * initialVal: initial value set to the input element.
+ * expectedVal: expected value of the input element after sending the keys.
+ */
+ {
+ // Type 11222016, default order is month, day, year.
+ keys: ["11222016"],
+ initialVal: "",
+ expectedVal: "2016-11-22"
+ },
+ {
+ // Type 3 in the month field will automatically advance to the day field,
+ // then type 5 in the day field will automatically advance to the year
+ // field.
+ keys: ["352016"],
+ initialVal: "",
+ expectedVal: "2016-03-05"
+ },
+ {
+ // Type 13 in the month field will set it to the maximum month, which is
+ // 12.
+ keys: ["13012016"],
+ initialVal: "",
+ expectedVal: "2016-12-01"
+ },
+ {
+ // Type 00 in the month field will set it to the minimum month, which is 1.
+ keys: ["00012016"],
+ initialVal: "",
+ expectedVal: "2016-01-01"
+ },
+ {
+ // Type 33 in the day field will set it to the maximum day, which is 31.
+ keys: ["12332016"],
+ initialVal: "",
+ expectedVal: "2016-12-31"
+ },
+ {
+ // Type 00 in the day field will set it to the minimum day, which is 1.
+ keys: ["12002016"],
+ initialVal: "",
+ expectedVal: "2016-12-01"
+ },
+ {
+ // Type 275769 in the year field will set it to the maximum year, which is
+ // 275760.
+ keys: ["0101275769"],
+ initialVal: "",
+ expectedVal: "275760-01-01"
+ },
+ {
+ // Type 000000 in the year field will set it to the minimum year, which is
+ // 0001.
+ keys: ["0101000000"],
+ initialVal: "",
+ expectedVal: "0001-01-01"
+ },
+ {
+ // Advance to year field and decrement.
+ keys: ["VK_TAB", "VK_TAB", "VK_DOWN"],
+ initialVal: "2016-11-25",
+ expectedVal: "2015-11-25"
+ },
+ {
+ // Right key should do the same thing as TAB key.
+ keys: ["VK_RIGHT", "VK_RIGHT", "VK_DOWN"],
+ initialVal: "2016-11-25",
+ expectedVal: "2015-11-25"
+ },
+ {
+ // Advance to day field then back to month field and decrement.
+ keys: ["VK_RIGHT", "VK_LEFT", "VK_DOWN"],
+ initialVal: "2000-05-01",
+ expectedVal: "2000-04-01"
+ },
+ {
+ // Focus starts on the first field, month in this case, and increment.
+ keys: ["VK_UP"],
+ initialVal: "2000-03-01",
+ expectedVal: "2000-04-01"
+ },
+ {
+ // Advance to day field and decrement.
+ keys: ["VK_TAB", "VK_DOWN"],
+ initialVal: "1234-01-01",
+ expectedVal: "1234-01-31"
+ },
+ {
+ // Advance to day field and increment.
+ keys: ["VK_TAB", "VK_UP"],
+ initialVal: "1234-01-01",
+ expectedVal: "1234-01-02"
+ },
+ {
+ // PageUp on month field increments month by 3.
+ keys: ["VK_PAGE_UP"],
+ initialVal: "1999-01-01",
+ expectedVal: "1999-04-01"
+ },
+ {
+ // PageDown on month field decrements month by 3.
+ keys: ["VK_PAGE_DOWN"],
+ initialVal: "1999-01-01",
+ expectedVal: "1999-10-01"
+ },
+ {
+ // PageUp on day field increments day by 7.
+ keys: ["VK_TAB", "VK_PAGE_UP"],
+ initialVal: "1999-01-01",
+ expectedVal: "1999-01-08"
+ },
+ {
+ // PageDown on day field decrements day by 7.
+ keys: ["VK_TAB", "VK_PAGE_DOWN"],
+ initialVal: "1999-01-01",
+ expectedVal: "1999-01-25"
+ },
+ {
+ // PageUp on year field increments year by 10.
+ keys: ["VK_TAB", "VK_TAB", "VK_PAGE_UP"],
+ initialVal: "1999-01-01",
+ expectedVal: "2009-01-01"
+ },
+ {
+ // PageDown on year field decrements year by 10.
+ keys: ["VK_TAB", "VK_TAB", "VK_PAGE_DOWN"],
+ initialVal: "1999-01-01",
+ expectedVal: "1989-01-01"
+ },
+ {
+ // Home key on month field sets it to the minimum month, which is 01.
+ keys: ["VK_HOME"],
+ initialVal: "2016-06-01",
+ expectedVal: "2016-01-01"
+ },
+ {
+ // End key on month field sets it to the maximum month, which is 12.
+ keys: ["VK_END"],
+ initialVal: "2016-06-01",
+ expectedVal: "2016-12-01"
+ },
+ {
+ // Home key on day field sets it to the minimum day, which is 01.
+ keys: ["VK_TAB", "VK_HOME"],
+ initialVal: "2016-01-10",
+ expectedVal: "2016-01-01"
+ },
+ {
+ // End key on day field sets it to the maximum day, which is 31.
+ keys: ["VK_TAB", "VK_END"],
+ initialVal: "2016-01-10",
+ expectedVal: "2016-01-31"
+ },
+ {
+ // Home key should have no effect on year field.
+ keys: ["VK_TAB", "VK_TAB", "VK_HOME"],
+ initialVal: "2016-01-01",
+ expectedVal: "2016-01-01"
+ },
+ {
+ // End key should have no effect on year field.
+ keys: ["VK_TAB", "VK_TAB", "VK_END"],
+ initialVal: "2016-01-01",
+ expectedVal: "2016-01-01"
+ },
+];
+
+function sendKeys(aKeys) {
+ for (let i = 0; i < aKeys.length; i++) {
+ let key = aKeys[i];
+ if (key.startsWith("VK")) {
+ synthesizeKey(key, {});
+ } else {
+ sendString(key);
+ }
+ }
+}
+
+function test() {
+ var elem = document.getElementById("input");
+
+ for (let { keys, initialVal, expectedVal } of testData) {
+ elem.focus();
+ elem.value = initialVal;
+ sendKeys(keys);
+ elem.blur();
+ is(elem.value, expectedVal,
+ "Test with " + keys + ", result should be " + expectedVal);
+ elem.value = "";
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_datetime_focus_blur.html b/dom/html/test/forms/test_input_datetime_focus_blur.html
index 5b8d95b25..85f7b4bb4 100644
--- a/dom/html/test/forms/test_input_datetime_focus_blur.html
+++ b/dom/html/test/forms/test_input_datetime_focus_blur.html
@@ -4,7 +4,7 @@
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
-->
<head>
- <title>Test focus/blur behaviour for &lt;input type='time'&gt;</title>
+ <title>Test focus/blur behaviour for date/time input types</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
@@ -12,7 +12,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
<p id="display"></p>
<div id="content">
- <input id="input" type="time">
+ <input id="input_time" type="time">
+ <input id="input_date" type="date">
</div>
<pre id="test">
<script type="application/javascript">
@@ -30,15 +31,15 @@ SimpleTest.waitForFocus(function() {
SimpleTest.finish();
});
-function test() {
- let time = document.getElementById("input");
- time.focus();
+function testFocusBlur(type) {
+ let input = document.getElementById("input_" + type);
+ input.focus();
- // The active element returns the input type=time.
+ // The active element returns the date/time input element.
let activeElement = document.activeElement;
- is(activeElement, time, "activeElement should be the time element");
+ is(activeElement, input, "activeElement should be the date/time input element");
is(activeElement.localName, "input", "activeElement should be an input element");
- is(activeElement.type, "time", "activeElement should be of type time");
+ is(activeElement.type, type, "activeElement should be of type " + type);
// Use FocusManager to check that the actual focus is on the anonymous
// text control.
@@ -48,10 +49,17 @@ function test() {
is(focusedElement.localName, "input", "focusedElement should be an input element");
is(focusedElement.type, "text", "focusedElement should be of type text");
- time.blur();
- isnot(document.activeElement, time, "activeElement should no longer be the time element");
+ input.blur();
+ isnot(document.activeElement, input, "activeElement should no longer be the datetime input element");
}
+function test() {
+ let inputTypes = ["time", "date"];
+
+ for (let i = 0; i < inputTypes.length; i++) {
+ testFocusBlur(inputTypes[i]);
+ }
+}
</script>
</pre>
</body>
diff --git a/dom/html/test/forms/test_input_datetime_focus_blur_events.html b/dom/html/test/forms/test_input_datetime_focus_blur_events.html
new file mode 100644
index 000000000..873dda627
--- /dev/null
+++ b/dom/html/test/forms/test_input_datetime_focus_blur_events.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1301306
+-->
+<head>
+<title>Test for Bug 1301306</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301306">Mozilla Bug 722599</a>
+<p id="display"></p>
+<div id="content">
+<input type="time" id="input_time" onfocus="++focusEvents[0]"
+ onblur="++blurEvents[0]" onfocusin="++focusInEvents[0]"
+ onfocusout="++focusOutEvents[0]">
+<input type="date" id="input_date" onfocus="++focusEvents[1]"
+ onblur="++blurEvents[1]" onfocusin="++focusInEvents[1]"
+ onfocusout="++focusOutEvents[1]">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/**
+ * Test for Bug 1301306.
+ * This test checks that when moving inside the time input element, e.g. jumping
+ * through the inner text boxes, does not fire extra focus/blur events.
+ **/
+
+var inputTypes = ["time", "date"];
+var focusEvents = [0, 0];
+var focusInEvents = [0, 0];
+var focusOutEvents = [0, 0];
+var blurEvents = [0, 0];
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function test() {
+ for (var i = 0; i < inputTypes.length; i++) {
+ var input = document.getElementById("input_" + inputTypes[i]);
+
+ input.focus();
+ is(focusEvents[i], 1, inputTypes[i] + " input element should have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
+
+ // Move around inside the input element's input box.
+ synthesizeKey("VK_TAB", {});
+ is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " time input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_RIGHT", {});
+ is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_LEFT", {});
+ is(focusEvents[i], 1,inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_RIGHT", {});
+ is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
+
+ input.blur();
+ is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 1, inputTypes[i] + " input element should have dispatched focusout event.");
+ is(blurEvents[i], 1, inputTypes[i] + " input element should have dispatched blur event.");
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_datetime_input_change_events.html b/dom/html/test/forms/test_input_datetime_input_change_events.html
new file mode 100644
index 000000000..e636995d3
--- /dev/null
+++ b/dom/html/test/forms/test_input_datetime_input_change_events.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1370858
+-->
+<head>
+<title>Test for Bug 1370858</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1370858">Mozilla Bug 722599</a>
+<p id="display"></p>
+<div id="content">
+<input type="time" id="input_time" onchange="++changeEvents[0]"
+ oninput="++inputEvents[0]">
+<input type="date" id="input_date" onchange="++changeEvents[1]"
+ oninput="++inputEvents[1]">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/**
+ * Test for Bug 1370858.
+ * Test that change and input events are (not) fired for date/time inputs.
+ **/
+
+var inputTypes = ["time", "date"];
+var changeEvents = [0, 0];
+var inputEvents = [0, 0];
+var values = ["10:30", "2017-06-08"];
+var expectedValues = [["09:30", "01:30"], ["2017-05-08", "2017-01-08"]];
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function test() {
+ for (var i = 0; i < inputTypes.length; i++) {
+ var input = document.getElementById("input_" + inputTypes[i]);
+ var inputRect = input.getBoundingClientRect();
+
+ // Points over the input's reset button
+ var resetButton_X = inputRect.width - 15;
+ var resetButton_Y = inputRect.height / 2;
+
+ is(changeEvents[i], 0, "Number of change events should be 0 at start.");
+ is(inputEvents[i], 0, "Number of input events should be 0 at start.");
+
+ // Test that change and input events are not dispatched setting .value by
+ // script.
+ input.value = values[i];
+ is(input.value, values[i], "Check that value was set correctly (0).");
+ is(changeEvents[i], 0, "Change event should not have dispatched (0).");
+ is(inputEvents[i], 0, "Input event should not have dispatched (0).");
+
+ // Test that change and input events are fired when changing the value using
+ // up/down keys.
+ input.focus();
+ synthesizeKey("VK_DOWN", {});
+ is(input.value, expectedValues[i][0], "Check that value was set correctly (1).");
+ is(changeEvents[i], 1, "Change event should be dispatched (1).");
+ is(inputEvents[i], 1, "Input event should ne dispatched (1).");
+
+ // Test that change and input events are fired when changing the value with
+ // the keyboard.
+ synthesizeKey("0", {});
+ synthesizeKey("1", {});
+ is(input.value, expectedValues[i][1], "Check that value was set correctly (2).");
+ is(changeEvents[i], 2, "Change event should be dispatched (2).");
+ is(inputEvents[i], 2, "Input event should be dispatched (2).");
+
+ // Test that change and input events are fired when clearing the value using
+ // the reset button.
+ synthesizeMouse(input, resetButton_X, resetButton_Y, {});
+ is(input.value, "", "Check that value was set correctly (3).");
+ is(changeEvents[i], 3, "Change event should be dispatched (3).");
+ is(inputEvents[i], 3, "Input event should be dispatched (3).");
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_datetime_tabindex.html b/dom/html/test/forms/test_input_datetime_tabindex.html
index fb7c9b2f1..8023ccf9b 100644
--- a/dom/html/test/forms/test_input_datetime_tabindex.html
+++ b/dom/html/test/forms/test_input_datetime_tabindex.html
@@ -4,7 +4,7 @@
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
-->
<head>
- <title>Test tabindex attribute for &lt;input type='time'&gt;</title>
+ <title>Test tabindex attribute for date/time input types</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
@@ -16,13 +16,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
<input id="time1" type="time" tabindex="0">
<input id="time2" type="time" tabindex="-1">
<input id="time3" type="time" tabindex="0">
+ <input id="date1" type="date" tabindex="0">
+ <input id="date2" type="date" tabindex="-1">
+ <input id="date3" type="date" tabindex="0">
</div>
<pre id="test">
<script type="application/javascript">
/**
* Test for Bug 1288591.
- * This test checks whether date/time input types' tabindex attribute works
+ * This test checks whether date/time input types tabindex attribute works
* correctly.
**/
SimpleTest.waitForExplicitFinish();
@@ -31,41 +34,49 @@ SimpleTest.waitForFocus(function() {
SimpleTest.finish();
});
-function test() {
- let time1 = document.getElementById("time1");
- let time2 = document.getElementById("time2");
- let time3 = document.getElementById("time3");
+function testTabindex(type) {
+ let input1 = document.getElementById(type + "1");
+ let input2 = document.getElementById(type + "2");
+ let input3 = document.getElementById(type + "3");
- time1.focus();
- is(document.activeElement, time1,
+ input1.focus();
+ is(document.activeElement, input1,
"input element with tabindex=0 is focusable");
- // Advance to time1 minute field
+ // Advance to next inner field
synthesizeKey("VK_TAB", {});
- is(document.activeElement, time1,
+ is(document.activeElement, input1,
"input element with tabindex=0 is tabbable");
- // Advance to time1 AM/PM field
+ // Advance to next inner field
synthesizeKey("VK_TAB", {});
- is(document.activeElement, time1,
+ is(document.activeElement, input1,
"input element with tabindex=0 is tabbable");
// Advance to next element
synthesizeKey("VK_TAB", {});
- is(document.activeElement, time3,
+ is(document.activeElement, input3,
"input element with tabindex=-1 is not tabbable");
- time2.focus();
- is(document.activeElement, time2,
+ input2.focus();
+ is(document.activeElement, input2,
"input element with tabindex=-1 is still focusable");
// Changing the tabindex attribute dynamically.
- time3.setAttribute("tabindex", "-1");
- synthesizeKey("VK_TAB", {}); // need only one TAB since time2 is not tabbable
- isnot(document.activeElement, time3,
+ input3.setAttribute("tabindex", "-1");
+ synthesizeKey("VK_TAB", {}); // need only one TAB since input2 is not tabbable
+ isnot(document.activeElement, input3,
"element with tabindex changed to -1 should not be tabbable");
}
+function test() {
+ let inputTypes = ["time", "date"];
+
+ for (let i = 0; i < inputTypes.length; i++) {
+ testTabindex(inputTypes[i]);
+ }
+}
+
</script>
</pre>
</body>
diff --git a/dom/html/test/forms/test_input_time_focus_blur_events.html b/dom/html/test/forms/test_input_time_focus_blur_events.html
deleted file mode 100644
index 483741477..000000000
--- a/dom/html/test/forms/test_input_time_focus_blur_events.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1301306
--->
-<head>
-<title>Test for Bug 1301306</title>
-<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301306">Mozilla Bug 722599</a>
-<p id="display"></p>
-<div id="content">
-<input type="time" id="input_time" onfocus="++focusEvent" onblur="++blurEvent"
- onfocusin="++focusInEvent" onfocusout="++focusOutEvent">
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/**
- * Test for Bug 1301306.
- * This test checks that when moving inside the time input element, e.g. jumping
- * through the inner text boxes, does not fire extra focus/blur events.
- **/
-
-var focusEvent = 0;
-var focusInEvent = 0;
-var focusOutEvent = 0;
-var blurEvent = 0;
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- test();
- SimpleTest.finish();
-});
-
-function test() {
- var time = document.getElementById("input_time");
- time.focus();
- is(focusEvent, 1, "time input element should have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- // Move around inside the input element's input box.
- synthesizeKey("VK_TAB", {});
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- synthesizeKey("VK_RIGHT", {});
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- synthesizeKey("VK_LEFT", {});
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- synthesizeKey("VK_RIGHT", {});
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- time.blur();
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 1, "time input element should not have dispatched focusout event.");
- is(blurEvent, 1, "time input element should have dispatched blur event.");
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/html/test/forms/test_input_types_pref.html b/dom/html/test/forms/test_input_types_pref.html
index 243836f34..5279d6a2a 100644
--- a/dom/html/test/forms/test_input_types_pref.html
+++ b/dom/html/test/forms/test_input_types_pref.html
@@ -37,47 +37,63 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=764481
inputType: "color",
expectedType: "color"
}, {
- prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", false],
- ["dom.forms.datetime", false]],
+ prefs: [["dom.experimental_forms", false], ["dom.forms.datetime", false]],
inputType: "date",
expectedType: "text"
}, {
- prefs: [["dom.experimental_forms", true], ["dom.forms.datepicker", false],
- ["dom.forms.datetime", false]],
+ prefs: [["dom.experimental_forms", true], ["dom.forms.datetime", false]],
inputType: "date",
expectedType: "date"
}, {
- prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", true],
- ["dom.forms.datetime", false]],
+ prefs: [["dom.experimental_forms", false], ["dom.forms.datetime", true]],
inputType: "date",
expectedType: "date"
}, {
- prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", false],
- ["dom.forms.datetime", true]],
- inputType: "date",
- expectedType: "date"
+ prefs: [["dom.experimental_forms", false], ["dom.forms.datetime", false]],
+ inputType: "time",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.experimental_forms", true], ["dom.forms.datetime", false]],
+ inputType: "time",
+ expectedType: "time"
+ }, {
+ prefs: [["dom.experimental_forms", false], ["dom.forms.datetime", true]],
+ inputType: "time",
+ expectedType: "time"
+ }, {
+ prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", false]],
+ inputType: "month",
+ expectedType: "text"
}, {
- prefs: [["dom.forms.datetime", false]],
+ prefs: [["dom.forms.datetime", true], ["dom.forms.datetime.others", false]],
inputType: "month",
expectedType: "text"
}, {
- prefs: [["dom.forms.datetime", true]],
+ prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", true]],
inputType: "month",
expectedType: "month"
}, {
- prefs: [["dom.forms.datetime", false]],
+ prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", false]],
+ inputType: "week",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.forms.datetime", true], ["dom.forms.datetime.others", false]],
inputType: "week",
expectedType: "text"
}, {
- prefs: [["dom.forms.datetime", true]],
+ prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", true]],
inputType: "week",
expectedType: "week"
}, {
- prefs: [["dom.forms.datetime", false]],
+ prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", false]],
+ inputType: "datetime-local",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.forms.datetime", true], ["dom.forms.datetime.others", false]],
inputType: "datetime-local",
expectedType: "text"
}, {
- prefs: [["dom.forms.datetime", true]],
+ prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", true]],
inputType: "datetime-local",
expectedType: "datetime-local"
}
diff --git a/dom/html/test/forms/test_input_typing_sanitization.html b/dom/html/test/forms/test_input_typing_sanitization.html
index 0896f19df..eee300b33 100644
--- a/dom/html/test/forms/test_input_typing_sanitization.html
+++ b/dom/html/test/forms/test_input_typing_sanitization.html
@@ -26,6 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=765772
* This test checks that when a user types in some input types, it will not be
* in a state where the value will be un-sanitized and usable (by a script).
*/
+const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
var input = document.getElementById('i');
var form = document.getElementById('f');
@@ -143,6 +144,7 @@ function runTest()
]
},
{
+ mobileOnly: true,
type: 'date',
validData: [
'0001-01-01',
@@ -161,6 +163,28 @@ function runTest()
]
},
{
+ mobileOnly: true,
+ type: 'time',
+ validData: [
+ '00:00',
+ '09:09:00',
+ '08:23:23.1',
+ '21:43:56.12',
+ '23:12:45.100',
+ ],
+ invalidData: [
+ '00:',
+ '00:00:',
+ '25:00',
+ '-00:00',
+ '00:00:00.',
+ '00:60',
+ '10:58:99',
+ ':19:10',
+ '23:08:09.1012',
+ ]
+ },
+ {
type: 'month',
validData: [
'0001-01',
@@ -218,6 +242,10 @@ function runTest()
for (test of data) {
gCurrentTest = test;
+ if (gCurrentTest.mobileOnly && isDesktop) {
+ continue;
+ }
+
input.type = test.type;
gValidData = test.validData;
gInvalidData = test.invalidData;
diff --git a/dom/html/test/forms/test_max_attribute.html b/dom/html/test/forms/test_max_attribute.html
index 4007cfad6..091ad321b 100644
--- a/dom/html/test/forms/test_max_attribute.html
+++ b/dom/html/test/forms/test_max_attribute.html
@@ -31,8 +31,7 @@ var data = [
{ type: 'month', apply: true },
{ type: 'week', apply: true },
{ type: 'time', apply: true },
- // TODO: temporary set to false until bug 888331 is fixed.
- { type: 'datetime-local', apply: false },
+ { type: 'datetime-local', apply: true },
{ type: 'number', apply: true },
{ type: 'range', apply: true },
{ type: 'color', apply: false },
@@ -71,7 +70,8 @@ function checkValidity(aElement, aValidity, aApply, aRangeApply)
"element overflow status should be " + !aValidity);
var overflowMsg =
(aElement.type == "date" || aElement.type == "time" ||
- aElement.type == "month" || aElement.type == "week") ?
+ aElement.type == "month" || aElement.type == "week" ||
+ aElement.type == "datetime-local") ?
("Please select a value that is no later than " + aElement.max + ".") :
("Please select a value that is no more than " + aElement.max + ".");
is(aElement.validationMessage,
@@ -148,7 +148,7 @@ for (var test of data) {
input.max = '2016-W39';
break;
case 'datetime-local':
- // TODO: this is temporary until bug 888331 is fixed.
+ input.max = '2016-12-31T23:59:59';
break;
default:
ok(false, 'please, add a case for this new type (' + input.type + ')');
@@ -421,7 +421,44 @@ for (var test of data) {
break;
case 'datetime-local':
- // TODO: this is temporary until bug 888331 is fixed.
+ input.value = '2016-01-01T12:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-12-31T23:59:59';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-12-31T23:59:59.123';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '2017-01-01T10:00';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '2017-01-01T10:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2017-01-01T10:00:30';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '1000-01-01T12:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2100-01-01T12:00';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '0050-12-31T23:59:59.999';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '0050-12-31T23:59:59';
+ checkValidity(input, true, apply, apply);
+
+ input.max = '';
+ checkValidity(input, true, apply, false);
+
+ input.max = 'foo';
+ checkValidity(input, true, apply, false);
break;
}
diff --git a/dom/html/test/forms/test_min_attribute.html b/dom/html/test/forms/test_min_attribute.html
index 1258babec..22f21de39 100644
--- a/dom/html/test/forms/test_min_attribute.html
+++ b/dom/html/test/forms/test_min_attribute.html
@@ -31,8 +31,7 @@ var data = [
{ type: 'month', apply: true },
{ type: 'week', apply: true },
{ type: 'time', apply: true },
- // TODO: temporary set to false until bug 888331 is fixed.
- { type: 'datetime-local', apply: false },
+ { type: 'datetime-local', apply: true },
{ type: 'number', apply: true },
{ type: 'range', apply: true },
{ type: 'color', apply: false },
@@ -71,7 +70,8 @@ function checkValidity(aElement, aValidity, aApply, aRangeApply)
"element underflow status should be " + !aValidity);
var underflowMsg =
(aElement.type == "date" || aElement.type == "time" ||
- aElement.type == "month" || aElement.type == "week") ?
+ aElement.type == "month" || aElement.type == "week" ||
+ aElement.type == "datetime-local") ?
("Please select a value that is no earlier than " + aElement.min + ".") :
("Please select a value that is no less than " + aElement.min + ".");
is(aElement.validationMessage,
@@ -146,10 +146,10 @@ for (var test of data) {
input.min = '2016-06';
break;
case 'week':
- input.min = "2016-W39";
+ input.min = '2016-W39';
break;
case 'datetime-local':
- // TODO: this is temporary until bug 888331 is fixed.
+ input.min = '2017-01-01T00:00';
break;
default:
ok(false, 'please, add a case for this new type (' + input.type + ')');
@@ -420,7 +420,44 @@ for (var test of data) {
checkValidity(input, true, apply, false);
break;
case 'datetime-local':
- // TODO: this is temporary until bug 888331 is fixed.
+ input.value = '2017-12-31T23:59';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2017-01-01T00:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2017-01-01T00:00:00.123';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-12-31T23:59';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '2016-01-01T00:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2015-12-31T23:59';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '1000-01-01T00:00';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '10000-01-01T00:00';
+ checkValidity(input, true, apply, apply);
+
+ input.min = '0010-01-01T12:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '0010-01-01T10:00';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '';
+ checkValidity(input, true, apply, false);
+
+ input.min = 'foo';
+ checkValidity(input, true, apply, false);
break;
default:
ok(false, 'write tests for ' + input.type);
diff --git a/dom/html/test/forms/test_step_attribute.html b/dom/html/test/forms/test_step_attribute.html
index 31277860c..a14afa461 100644
--- a/dom/html/test/forms/test_step_attribute.html
+++ b/dom/html/test/forms/test_step_attribute.html
@@ -31,8 +31,7 @@ var data = [
{ type: 'month', apply: true },
{ type: 'week', apply: true },
{ type: 'time', apply: true },
- // TODO: temporary set to false until bug 888331 is fixed.
- { type: 'datetime-local', apply: false },
+ { type: 'datetime-local', apply: true },
{ type: 'number', apply: true },
{ type: 'range', apply: true },
{ type: 'color', apply: false },
@@ -950,7 +949,104 @@ for (var test of data) {
break;
case 'datetime-local':
- // TODO: this is temporary until bug 888331 is fixed.
+ // When step is invalid, every datetime is valid
+ input.step = 0;
+ input.value = '2017-02-06T12:00';
+ checkValidity(input, true, apply);
+
+ input.step = 'foo';
+ input.value = '1970-01-01T00:00';
+ checkValidity(input, true, apply);
+
+ input.step = '-1';
+ input.value = '1969-12-12 00:10';
+ checkValidity(input, true, apply);
+
+ input.removeAttribute('step');
+ input.value = '1500-01-01T12:00';
+ checkValidity(input, true, apply);
+
+ input.step = 'any';
+ input.value = '1966-12-12T12:00';
+ checkValidity(input, true, apply);
+
+ input.step = 'ANY';
+ input.value = '2017-01-01 12:00';
+ checkValidity(input, true, apply);
+
+ // When min is set to a valid datetime, there is a step base.
+ input.min = '2017-01-01T00:00:00';
+ input.step = '2';
+ input.value = '2017-01-01T00:00:02';
+ checkValidity(input, true, apply);
+
+ input.value = '2017-01-01T00:00:03';
+ checkValidity(input, false, apply,
+ { low: "2017-01-01T00:00:02", high: "2017-01-01T00:00:04" });
+
+ input.min = '2017-01-01T00:00:05';
+ input.value = '2017-01-01T00:00:08';
+ checkValidity(input, false, apply,
+ { low: "2017-01-01T00:00:07", high: "2017-01-01T00:00:09" });
+
+ input.min = '2000-01-01T00:00';
+ input.step = '120';
+ input.value = '2000-01-01T00:02';
+ checkValidity(input, true, apply);
+
+ // Without any step attribute the datetime is valid
+ input.removeAttribute('step');
+ checkValidity(input, true, apply);
+
+ input.min = '1950-01-01T00:00';
+ input.step = '129600'; // 1.5 day
+ input.value = '1950-01-02T00:00';
+ checkValidity(input, false, apply,
+ { low: "1950-01-01T00:00", high: "1950-01-02T12:00" });
+
+ input.step = '259200'; // 3 days
+ input.value = '1950-01-04T12:00';
+ checkValidity(input, false, apply,
+ { low: "1950-01-04T00:00", high: "1950-01-07T00:00" });
+
+ input.value = '1950-01-10T00:00';
+ checkValidity(input, true, apply);
+
+ input.step = '0.5'; // half a second
+ input.value = '1950-01-01T00:00:00.123';
+ checkValidity(input, false, apply,
+ { low: "1950-01-01T00:00", high: "1950-01-01T00:00:00.500" });
+
+ input.value = '2000-01-01T12:30:30.600';
+ checkValidity(input, false, apply,
+ { low: "2000-01-01T12:30:30.500", high: "2000-01-01T12:30:31" });
+
+ input.value = '1950-01-05T00:00:00.500';
+ checkValidity(input, true, apply);
+
+ input.step = '2.1';
+ input.min = '1991-01-01T12:00';
+ input.value = '1991-01-01T12:00';
+ checkValidity(input, true, apply);
+
+ input.value = '1991-01-01T12:00:03';
+ checkValidity(input, false, apply,
+ { low: "1991-01-01T12:00:02.100", high: "1991-01-01T12:00:04.200" });
+
+ input.value = '1991-01-01T12:00:06.3';
+ checkValidity(input, true, apply);
+
+ input.step = '2.1';
+ input.min = '1969-12-20T10:00:05';
+ input.value = '1969-12-20T10:00:05';
+ checkValidity(input, true, apply);
+
+ input.value = '1969-12-20T10:00:08';
+ checkValidity(input, false, apply,
+ { low: "1969-12-20T10:00:07.100", high: "1969-12-20T10:00:09.200" });
+
+ input.value = '1969-12-20T10:00:09.200';
+ checkValidity(input, true, apply);
break;
default:
diff --git a/dom/html/test/forms/test_stepup_stepdown.html b/dom/html/test/forms/test_stepup_stepdown.html
index d96895180..21cde58aa 100644
--- a/dom/html/test/forms/test_stepup_stepdown.html
+++ b/dom/html/test/forms/test_stepup_stepdown.html
@@ -52,13 +52,8 @@ function checkAvailability()
["time", true],
["month", true],
["week", true],
- ["color", false],
- ];
-
- var todoList =
- [
- ["datetime", true],
["datetime-local", true],
+ ["color", false],
];
var element = document.createElement("input");
@@ -82,27 +77,6 @@ function checkAvailability()
}
is(exceptionCaught, !data[1], "stepUp() availability is not correct");
}
-
- for (data of todoList) {
- var exceptionCaught = false;
- element.type = data[0];
- try {
- element.stepDown();
- } catch (e) {
- exceptionCaught = true;
- }
- todo_is(exceptionCaught, !data[1],
- "stepDown() availability is not correct");
-
- exceptionCaught = false;
- try {
- element.stepUp();
- } catch (e) {
- exceptionCaught = true;
- }
- todo_is(exceptionCaught, !data[1],
- "stepUp() availability is not correct");
- }
}
function checkStepDown()
@@ -509,6 +483,80 @@ function checkStepDown()
[ '2016-W01', 'AnY', null, null, 1, null, true ],
[ '2016-W01', 'aNy', null, null, 1, null, true ],
]},
+ { type: 'datetime-local', data: [
+ // Regular case.
+ [ '2017-02-07T09:30', null, null, null, null, '2017-02-07T09:29', false ],
+ // Argument testing.
+ [ '2017-02-07T09:30', null, null, null, 1, '2017-02-07T09:29', false ],
+ [ '2017-02-07T09:30', null, null, null, 5, '2017-02-07T09:25', false ],
+ [ '2017-02-07T09:30', null, null, null, -1, '2017-02-07T09:31', false ],
+ [ '2017-02-07T09:30', null, null, null, 0, '2017-02-07T09:30', false ],
+ // hour/minutes/seconds wrapping.
+ [ '2000-01-01T05:00', null, null, null, null, '2000-01-01T04:59', false ],
+ [ '2000-01-01T05:00:00', 1, null, null, null, '2000-01-01T04:59:59', false ],
+ [ '2000-01-01T05:00:00', 0.1, null, null, null, '2000-01-01T04:59:59.900', false ],
+ [ '2000-01-01T05:00:00', 0.01, null, null, null, '2000-01-01T04:59:59.990', false ],
+ [ '2000-01-01T05:00:00', 0.001, null, null, null, '2000-01-01T04:59:59.999', false ],
+ // month/year wrapping.
+ [ '2012-08-01T12:00', null, null, null, 1440, '2012-07-31T12:00', false ],
+ [ '1969-01-02T12:00', null, null, null, 5760, '1968-12-29T12:00', false ],
+ [ '1969-12-31T00:00', null, null, null, -1440, '1970-01-01T00:00', false ],
+ [ '2012-02-29T00:00', null, null, null, -1440, '2012-03-01T00:00', false ],
+ // stepDown() on '00:00' gives '23:59'.
+ [ '2017-02-07T00:00', null, null, null, 1, '2017-02-06T23:59', false ],
+ [ '2017-02-07T00:00', null, null, null, 3, '2017-02-06T23:57', false ],
+ // Some random step values..
+ [ '2017-02-07T16:07', '0.5', null, null, null, '2017-02-07T16:06:59.500', false ],
+ [ '2017-02-07T16:07', '2', null, null, null, '2017-02-07T16:06:58', false ],
+ [ '2017-02-07T16:07', '0.25', null, null, 4, '2017-02-07T16:06:59', false ],
+ [ '2017-02-07T16:07', '1.1', '2017-02-07T16:00', null, 1, '2017-02-07T16:06:59.100', false ],
+ [ '2017-02-07T16:07', '1.1', '2017-02-07T16:00', null, 2, '2017-02-07T16:06:58', false ],
+ [ '2017-02-07T16:07', '1.1', '2017-02-07T16:00', null, 10, '2017-02-07T16:06:49.200', false ],
+ [ '2017-02-07T16:07', '129600', '2017-02-01T00:00', null, 2, '2017-02-05T12:00', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '2017-02-07T10:15', '0', null, null, null, '2017-02-07T10:14', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '2017-02-07T10:15', '-1', null, null, null, '2017-02-07T10:14', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '2017-02-07T10:15', 'foo', null, null, null, '2017-02-07T10:14', false ],
+ // Min values testing.
+ [ '2012-02-02T17:02', '60', 'foo', null, 2, '2012-02-02T17:00', false ],
+ [ '2012-02-02T17:10', '60', '2012-02-02T17:09', null, null, '2012-02-02T17:09', false ],
+ [ '2012-02-02T17:10', '60', '2012-02-02T17:10', null, null, '2012-02-02T17:10', false ],
+ [ '2012-02-02T17:10', '60', '2012-02-02T17:30', null, 1, '2012-02-02T17:10', false ],
+ [ '2012-02-02T17:10', '180', '2012-02-02T17:05', null, null, '2012-02-02T17:08', false ],
+ [ '2012-02-03T20:05', '86400', '2012-02-02T17:05', null, null, '2012-02-03T17:05', false ],
+ [ '2012-02-03T18:00', '129600', '2012-02-01T00:00', null, null, '2012-02-02T12:00', false ],
+ // Max values testing.
+ [ '2012-02-02T17:15', '60', null, 'foo', null, '2012-02-02T17:14', false ],
+ [ '2012-02-02T17:15', null, null, '2012-02-02T17:20', null, '2012-02-02T17:14', false ],
+ [ '2012-02-02T17:15', null, null, '2012-02-02T17:15', null, '2012-02-02T17:14', false ],
+ [ '2012-02-02T17:15', null, null, '2012-02-02T17:13', 4, '2012-02-02T17:11', false ],
+ [ '2012-02-02T17:15', '120', null, '2012-02-02T17:13', 3, '2012-02-02T17:09', false ],
+ [ '2012-02-03T20:05', '86400', null, '2012-02-03T20:05', null, '2012-02-02T20:05', false ],
+ [ '2012-02-03T18:00', '129600', null, '2012-02-03T20:00', null, '2012-02-02T06:00', false ],
+ // Step mismatch.
+ [ '2017-02-07T17:19', '120', '2017-02-07T17:10', null, null, '2017-02-07T17:18', false ],
+ [ '2017-02-07T17:19', '120', '2017-02-07T17:10', null, 2, '2017-02-07T17:16', false ],
+ [ '2017-02-07T17:19', '120', '2017-02-07T17:18', '2017-02-07T17:25', null, '2017-02-07T17:18', false ],
+ [ '2017-02-07T17:19', '120', null, null, null, '2017-02-07T17:17', false ],
+ [ '2017-02-07T17:19', '180', null, null, null, '2017-02-07T17:16', false ],
+ [ '2017-02-07T17:19', '172800', '2017-02-02T17:19', '2017-02-10T17:19', null, '2017-02-06T17:19', false ],
+ // Clamping.
+ [ '2017-02-07T17:22', null, null, '2017-02-07T17:11', null, '2017-02-07T17:11', false ],
+ [ '2017-02-07T17:22', '120', '2017-02-07T17:20', '2017-02-07T17:22', null, '2017-02-07T17:20', false ],
+ [ '2017-02-07T17:22', '300', '2017-02-07T17:12', '2017-02-07T17:20', 10, '2017-02-07T17:12', false ],
+ [ '2017-02-07T17:22', '300', '2017-02-07T17:18', '2017-02-07T17:20', 2, '2017-02-07T17:18', false ],
+ [ '2017-02-07T17:22', '600', '2017-02-02T17:00', '2017-02-07T17:00', 15, '2017-02-07T15:00', false ],
+ [ '2017-02-07T17:22', '600', '2017-02-02T17:00', '2017-02-07T17:00', 2, '2017-02-07T17:00', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1969-12-31T23:59', false ],
+ // With step = 'any'.
+ [ '2017-02-07T15:20', 'any', null, null, 1, null, true ],
+ [ '2017-02-07T15:20', 'ANY', null, null, 1, null, true ],
+ [ '2017-02-07T15:20', 'AnY', null, null, 1, null, true ],
+ [ '2017-02-07T15:20', 'aNy', null, null, 1, null, true ],
+ ]},
];
for (var test of testData) {
@@ -958,6 +1006,78 @@ function checkStepUp()
[ '2016-W01', 'AnY', null, null, 1, null, true ],
[ '2016-W01', 'aNy', null, null, 1, null, true ],
]},
+ { type: 'datetime-local', data: [
+ // Regular case.
+ [ '2017-02-07T17:09', null, null, null, null, '2017-02-07T17:10', false ],
+ // Argument testing.
+ [ '2017-02-07T17:10', null, null, null, 1, '2017-02-07T17:11', false ],
+ [ '2017-02-07T17:10', null, null, null, 5, '2017-02-07T17:15', false ],
+ [ '2017-02-07T17:10', null, null, null, -1, '2017-02-07T17:09', false ],
+ [ '2017-02-07T17:10', null, null, null, 0, '2017-02-07T17:10', false ],
+ // hour/minutes/seconds wrapping.
+ [ '2000-01-01T04:59', null, null, null, null, '2000-01-01T05:00', false ],
+ [ '2000-01-01T04:59:59', 1, null, null, null, '2000-01-01T05:00', false ],
+ [ '2000-01-01T04:59:59.900', 0.1, null, null, null, '2000-01-01T05:00', false ],
+ [ '2000-01-01T04:59:59.990', 0.01, null, null, null, '2000-01-01T05:00', false ],
+ [ '2000-01-01T04:59:59.999', 0.001, null, null, null, '2000-01-01T05:00', false ],
+ // month/year wrapping.
+ [ '2012-07-31T12:00', null, null, null, 1440, '2012-08-01T12:00', false ],
+ [ '1968-12-29T12:00', null, null, null, 5760, '1969-01-02T12:00', false ],
+ [ '1970-01-01T00:00', null, null, null, -1440, '1969-12-31T00:00', false ],
+ [ '2012-03-01T00:00', null, null, null, -1440, '2012-02-29T00:00', false ],
+ // stepUp() on '23:59' gives '00:00'.
+ [ '2017-02-07T23:59', null, null, null, 1, '2017-02-08T00:00', false ],
+ [ '2017-02-07T23:59', null, null, null, 3, '2017-02-08T00:02', false ],
+ // Some random step values..
+ [ '2017-02-07T17:40', '0.5', null, null, null, '2017-02-07T17:40:00.500', false ],
+ [ '2017-02-07T17:40', '2', null, null, null, '2017-02-07T17:40:02', false ],
+ [ '2017-02-07T17:40', '0.25', null, null, 4, '2017-02-07T17:40:01', false ],
+ [ '2017-02-07T17:40', '1.1', '2017-02-07T17:00', null, 1, '2017-02-07T17:40:00.200', false ],
+ [ '2017-02-07T17:40', '1.1', '2017-02-07T17:00', null, 2, '2017-02-07T17:40:01.300', false ],
+ [ '2017-02-07T17:40', '1.1', '2017-02-07T17:00', null, 10, '2017-02-07T17:40:10.100', false ],
+ [ '2017-02-07T17:40', '129600', '2017-02-01T00:00', null, 2, '2017-02-10T00:00', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '2017-02-07T17:39', '0', null, null, null, '2017-02-07T17:40', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '2017-02-07T17:39', '-1', null, null, null, '2017-02-07T17:40', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '2017-02-07T17:39', 'foo', null, null, null, '2017-02-07T17:40', false ],
+ // Min values testing.
+ [ '2012-02-02T17:00', '60', 'foo', null, 2, '2012-02-02T17:02', false ],
+ [ '2012-02-02T17:10', '60', '2012-02-02T17:10', null, null, '2012-02-02T17:11', false ],
+ [ '2012-02-02T17:10', '60', '2012-02-02T17:30', null, 1, '2012-02-02T17:30', false ],
+ [ '2012-02-02T17:10', '180', '2012-02-02T17:05', null, null, '2012-02-02T17:11', false ],
+ [ '2012-02-02T17:10', '86400', '2012-02-02T17:05', null, null, '2012-02-03T17:05', false ],
+ [ '2012-02-02T17:10', '129600', '2012-02-01T00:00', null, null, '2012-02-04T00:00', false ],
+ // Max values testing.
+ [ '2012-02-02T17:15', '60', null, 'foo', null, '2012-02-02T17:16', false ],
+ [ '2012-02-02T17:15', null, null, '2012-02-02T17:20', null, '2012-02-02T17:16', false ],
+ [ '2012-02-02T17:15', null, null, '2012-02-02T17:15', null, '2012-02-02T17:15', false ],
+ [ '2012-02-02T17:15', null, null, '2012-02-02T17:13', 4, '2012-02-02T17:15', false ],
+ [ '2012-02-02T20:05', '86400', null, '2012-02-03T20:05', null, '2012-02-03T20:05', false ],
+ [ '2012-02-02T18:00', '129600', null, '2012-02-04T20:00', null, '2012-02-04T06:00', false ],
+ // Step mismatch.
+ [ '2017-02-07T17:19', '120', '2017-02-07T17:10', null, null, '2017-02-07T17:20', false ],
+ [ '2017-02-07T17:19', '120', '2017-02-07T17:10', null, 2, '2017-02-07T17:22', false ],
+ [ '2017-02-07T17:19', '120', '2017-02-07T17:18', '2017-02-07T17:25', null, '2017-02-07T17:20', false ],
+ [ '2017-02-07T17:19', '120', null, null, null, '2017-02-07T17:21', false ],
+ [ '2017-02-07T17:19', '180', null, null, null, '2017-02-07T17:22', false ],
+ [ '2017-02-03T17:19', '172800', '2017-02-02T17:19', '2017-02-10T17:19', null, '2017-02-04T17:19', false ],
+ // Clamping.
+ [ '2017-02-07T17:22', null, null, '2017-02-07T17:11', null, '2017-02-07T17:22', false ],
+ [ '2017-02-07T17:22', '120', '2017-02-07T17:20', '2017-02-07T17:22', null, '2017-02-07T17:22', false ],
+ [ '2017-02-07T17:22', '300', '2017-02-07T17:12', '2017-02-07T17:20', 10, '2017-02-07T17:22', false ],
+ [ '2017-02-07T17:22', '300', '2017-02-07T17:18', '2017-02-07T17:20', 2, '2017-02-07T17:22', false ],
+ [ '2017-02-06T17:22', '600', '2017-02-02T17:00', '2017-02-07T17:20', 15, '2017-02-06T19:50', false ],
+ [ '2017-02-06T17:22', '600', '2017-02-02T17:10', '2017-02-07T17:20', 2, '2017-02-06T17:40', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1970-01-01T00:01', false ],
+ // With step = 'any'.
+ [ '2017-02-07T17:30', 'any', null, null, 1, null, true ],
+ [ '2017-02-07T17:30', 'ANY', null, null, 1, null, true ],
+ [ '2017-02-07T17:30', 'AnY', null, null, 1, null, true ],
+ [ '2017-02-07T17:30', 'aNy', null, null, 1, null, true ],
+ ]},
];
for (var test of testData) {
diff --git a/dom/html/test/forms/test_valueAsDate_pref.html b/dom/html/test/forms/test_valueAsDate_pref.html
index 8518c291b..0369980e4 100644
--- a/dom/html/test/forms/test_valueAsDate_pref.html
+++ b/dom/html/test/forms/test_valueAsDate_pref.html
@@ -12,8 +12,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=874640
/** Test for Bug 874640 **/
var states = [
- // dom.experimental_forms, dom.forms.datepicker, dom.forms.datetime, expectedValueAsDate
- [ 'true', 'true', 'true', 'true' ],
+ // dom.experimental_forms, dom.forms.datetime, dom.forms.datetime.others, expectedValueAsDate
+ [ 'true', 'true', ,'true', 'true' ],
[ 'true', 'false', 'false', 'true' ],
[ 'false', 'true', 'false', 'true' ],
[ 'false', 'false', 'true', 'true' ],
@@ -33,8 +33,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=874640
SpecialPowers.pushPrefEnv({"set":[
["dom.experimental_forms", state[0] === 'true'],
- ["dom.forms.datepicker", state[1] === 'true'],
- ["dom.forms.datetime", state[2] === 'true']]},
+ ["dom.forms.datetime", state[1] === 'true'],
+ ["dom.forms.datetime.others", state[2] === 'true']]},
function() {
iframe.src = 'data:text/html,<script>' +
'parent.is("valueAsDate" in document.createElement("input"), ' +
diff --git a/dom/html/test/forms/test_valueasdate_attribute.html b/dom/html/test/forms/test_valueasdate_attribute.html
index 8c19fefd9..65cab3b8e 100644
--- a/dom/html/test/forms/test_valueasdate_attribute.html
+++ b/dom/html/test/forms/test_valueasdate_attribute.html
@@ -47,8 +47,7 @@ var validTypes =
["color", false],
["month", true],
["week", true],
- // TODO: temporary set to false until bug 888331 is fixed.
- ["datetime-local", false],
+ ["datetime-local", true],
];
function checkAvailability()
@@ -622,6 +621,107 @@ function checkWeekSet()
}
}
+function checkDatetimeLocalGet()
+{
+ var validData =
+ [
+ // Simple cases.
+ [ "2016-12-27T10:30", Date.UTC(2016, 11, 27, 10, 30, 0) ],
+ [ "2016-12-27T10:30:40", Date.UTC(2016, 11, 27, 10, 30, 40) ],
+ [ "2016-12-27T10:30:40.567", Date.UTC(2016, 11, 27, 10, 30, 40, 567) ],
+ [ "1969-12-31T12:00:00", Date.UTC(1969, 11, 31, 12, 0, 0) ],
+ [ "1970-01-01T00:00", 0 ],
+ // Leap years.
+ [ "1804-02-29 12:34", Date.UTC(1804, 1, 29, 12, 34, 0) ],
+ [ "2016-02-29T12:34", Date.UTC(2016, 1, 29, 12, 34, 0) ],
+ [ "2016-12-31T12:34:56", Date.UTC(2016, 11, 31, 12, 34, 56) ],
+ [ "2016-01-01T12:34:56.789", Date.UTC(2016, 0, 1, 12, 34, 56, 789) ],
+ [ "2017-01-01 12:34:56.789", Date.UTC(2017, 0, 1, 12, 34, 56, 789) ],
+ // Maximum valid datetime-local (limited by the ecma date object range).
+ [ "275760-09-13T00:00", 8640000000000000 ],
+ // Minimum valid datetime-local (limited by the input element minimum valid value).
+ [ "0001-01-01T00:00", -62135596800000 ],
+ ];
+
+ var invalidData =
+ [
+ [ "invaliddateime-local" ],
+ [ "0000-01-01T00:00" ],
+ [ "2016-12-25T00:00Z" ],
+ [ "2015-02-29T12:34" ],
+ [ "1-1-1T12:00" ],
+ [ "" ],
+ // This datetime-local is valid for the input element, but is out of the
+ // date object range. In this case, on getting valueAsDate, a Date object
+ // will be created, but it will have a NaN internal value, and will return
+ // the string "Invalid Date".
+ [ "275760-09-13T12:00", true ],
+ ];
+
+ element.type = "datetime-local";
+ for (let data of validData) {
+ element.value = data[0];
+ is(element.valueAsDate.valueOf(), data[1],
+ "valueAsDate should return the " +
+ "valid date object representing this datetime-local");
+ }
+
+ for (let data of invalidData) {
+ element.value = data[0];
+ if (data[1]) {
+ is(String(element.valueAsDate), "Invalid Date",
+ "valueAsDate should return an invalid Date object " +
+ "when the element value is not a valid datetime-local");
+ } else {
+ is(element.valueAsDate, null,
+ "valueAsDate should return null " +
+ "when the element value is not a valid datetime-local");
+ }
+ }
+}
+
+function checkDatetimeLocalSet()
+{
+ var testData =
+ [
+ // Simple cases.
+ [ Date.UTC(2016, 11, 27, 10, 30, 0), "2016-12-27T10:30" ],
+ [ Date.UTC(2016, 11, 27, 10, 30, 30), "2016-12-27T10:30:30" ],
+ [ Date.UTC(1999, 11, 31, 23, 59, 59), "1999-12-31T23:59:59" ],
+ [ Date.UTC(1999, 11, 31, 23, 59, 59, 999), "1999-12-31T23:59:59.999" ],
+ [ Date.UTC(123456, 7, 8, 9, 10), "123456-08-08T09:10" ],
+ [ 0, "1970-01-01T00:00" ],
+ // Maximum valid datetime-local (limited by the ecma date object range).
+ [ 8640000000000000, "275760-09-13T00:00" ],
+ // Minimum valid datetime-local (limited by the input element minimum valid value).
+ [ -62135596800000, "0001-01-01T00:00" ],
+ // Leap years.
+ [ Date.UTC(1804, 1, 29, 12, 34, 0), "1804-02-29T12:34" ],
+ [ Date.UTC(2016, 1, 29, 12, 34, 0), "2016-02-29T12:34" ],
+ [ Date.UTC(2016, 11, 31, 12, 34, 56), "2016-12-31T12:34:56" ],
+ [ Date.UTC(2016, 0, 1, 12, 34, 56, 789), "2016-01-01T12:34:56.789" ],
+ [ Date.UTC(2017, 0, 1, 12, 34, 56, 789), "2017-01-01T12:34:56.789" ],
+ // "Values must be truncated to valid datetime-local"
+ [ 123.123456789123, "1970-01-01T00:00:00.123" ],
+ [ 1e-1, "1970-01-01T00:00" ],
+ [ -1.1, "1969-12-31T23:59:59.999" ],
+ [ -345600000, "1969-12-28T00:00" ],
+ // Negative years, this is out of range for the input element,
+ // the corresponding datetime-local string is the empty string
+ [ -62135596800001, "" ],
+ ];
+
+ element.type = "datetime-local";
+ for (let data of testData) {
+ element.valueAsDate = new Date(data[0]);
+ is(element.value, data[1], "valueAsDate should set the value to " +
+ data[1]);
+ element.valueAsDate = new testFrame.Date(data[0]);
+ is(element.value, data[1], "valueAsDate with other-global date should " +
+ "set the value to " + data[1]);
+ }
+}
+
checkAvailability();
checkGarbageValues();
checkWithBustedPrototype();
@@ -642,6 +742,10 @@ checkMonthSet();
checkWeekGet();
checkWeekSet();
+// Test <input type='datetime-local'>.
+checkDatetimeLocalGet();
+checkDatetimeLocalSet();
+
</script>
</pre>
</body>
diff --git a/dom/html/test/forms/test_valueasnumber_attribute.html b/dom/html/test/forms/test_valueasnumber_attribute.html
index d7471502b..2660fc7ed 100644
--- a/dom/html/test/forms/test_valueasnumber_attribute.html
+++ b/dom/html/test/forms/test_valueasnumber_attribute.html
@@ -46,8 +46,7 @@ function checkAvailability()
["color", false],
["month", true],
["week", true],
- // TODO: temporary set to false until bug 888331 is fixed.
- ["datetime-local", false],
+ ["datetime-local", true],
];
var element = document.createElement('input');
@@ -612,7 +611,6 @@ function checkWeekGet()
var element = document.createElement('input');
element.type = "week";
for (let data of validData) {
- dump("Test: " + data[0]);
element.value = data[0];
is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
"integer value representing this week");
@@ -698,7 +696,120 @@ function checkWeekSet()
try {
element.valueAsNumber = data[0];
- is(element.value, data[1], "valueAsNumber should set the value to " + data[1]);
+ is(element.value, data[1], "valueAsNumber should set the value to " +
+ data[1]);
+ } catch(e) {
+ caught = true;
+ }
+
+ if (data[2]) {
+ ok(caught, "valueAsNumber should have thrown");
+ is(element.value, data[1], "the value should not have changed");
+ } else {
+ ok(!caught, "valueAsNumber should not have thrown");
+ }
+ }
+}
+
+function checkDatetimeLocalGet() {
+ var validData =
+ [
+ // Simple cases.
+ [ "2016-12-20T09:58", Date.UTC(2016, 11, 20, 9, 58) ],
+ [ "2016-12-20T09:58:30", Date.UTC(2016, 11, 20, 9, 58, 30) ],
+ [ "2016-12-20T09:58:30.123", Date.UTC(2016, 11, 20, 9, 58, 30, 123) ],
+ [ "2017-01-01T10:00", Date.UTC(2017, 0, 1, 10, 0, 0) ],
+ [ "1969-12-31T12:00:00", Date.UTC(1969, 11, 31, 12, 0, 0) ],
+ [ "1970-01-01T00:00", 0 ],
+ // Leap years.
+ [ "1804-02-29 12:34", Date.UTC(1804, 1, 29, 12, 34, 0) ],
+ [ "2016-02-29T12:34", Date.UTC(2016, 1, 29, 12, 34, 0) ],
+ [ "2016-12-31T12:34:56", Date.UTC(2016, 11, 31, 12, 34, 56) ],
+ [ "2016-01-01T12:34:56.789", Date.UTC(2016, 0, 1, 12, 34, 56, 789) ],
+ [ "2017-01-01 12:34:56.789", Date.UTC(2017, 0, 1, 12, 34, 56, 789) ],
+ // Maximum valid datetime-local (limited by the ecma date object range).
+ [ "275760-09-13T00:00", 8640000000000000 ],
+ // Minimum valid datetime-local (limited by the input element minimum valid value).
+ [ "0001-01-01T00:00", -62135596800000 ],
+ ];
+
+ var invalidData =
+ [
+ "invaliddatetime-local",
+ "0000-01-01T00:00",
+ "2016-12-25T00:00Z",
+ "2015-02-29T12:34",
+ "1-1-1T12:00",
+ // Out of range.
+ "275760-09-13T12:00",
+ ];
+
+ var element = document.createElement('input');
+ element.type = "datetime-local";
+ for (let data of validData) {
+ element.value = data[0];
+ is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
+ "integer value representing this datetime-local");
+ }
+
+ for (let data of invalidData) {
+ element.value = data;
+ ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
+ "when the element value is not a valid datetime-local");
+ }
+}
+
+function checkDatetimeLocalSet()
+{
+ var testData =
+ [
+ // Simple cases.
+ [ Date.UTC(2016, 11, 20, 9, 58, 0), "2016-12-20T09:58", ],
+ [ Date.UTC(2016, 11, 20, 9, 58, 30), "2016-12-20T09:58:30" ],
+ [ Date.UTC(2016, 11, 20, 9, 58, 30, 123), "2016-12-20T09:58:30.123" ],
+ [ Date.UTC(2017, 0, 1, 10, 0, 0), "2017-01-01T10:00" ],
+ [ Date.UTC(1969, 11, 31, 12, 0, 0), "1969-12-31T12:00" ],
+ [ 0, "1970-01-01T00:00" ],
+ // Maximum valid week (limited by the ecma date object range).
+ [ 8640000000000000, "275760-09-13T00:00" ],
+ // Minimum valid datetime-local (limited by the input element minimum valid value).
+ [ -62135596800000, "0001-01-01T00:00" ],
+ // Leap years.
+ [ Date.UTC(1804, 1, 29, 12, 34, 0), "1804-02-29T12:34" ],
+ [ Date.UTC(2016, 1, 29, 12, 34, 0), "2016-02-29T12:34" ],
+ [ Date.UTC(2016, 11, 31, 12, 34, 56), "2016-12-31T12:34:56" ],
+ [ Date.UTC(2016, 0, 1, 12, 34, 56, 789), "2016-01-01T12:34:56.789" ],
+ [ Date.UTC(2017, 0, 1, 12, 34, 56, 789), "2017-01-01T12:34:56.789" ],
+ // "Values must be truncated to valid datetime-local"
+ [ 0.3, "1970-01-01T00:00" ],
+ [ 1e-1, "1970-01-01T00:00" ],
+ [ -1 , "1969-12-31T23:59:59.999" ],
+ [ -345600000, "1969-12-28T00:00" ],
+ // Invalid numbers.
+ // Those are implicitly converted to numbers
+ [ "", "1970-01-01T00:00" ],
+ [ true, "1970-01-01T00:00:00.001" ],
+ [ false, "1970-01-01T00:00" ],
+ [ null, "1970-01-01T00:00" ],
+ // Those are converted to NaN, the corresponding week string is the empty string
+ [ "invaliddatetime-local", "" ],
+ [ NaN, "" ],
+ [ undefined, "" ],
+ // Infinity will keep the current value and throw (so we need to set a current value).
+ [ Date.UTC(2016, 11, 27, 15, 10, 0), "2016-12-27T15:10" ],
+ [ Infinity, "2016-12-27T15:10", true ],
+ [ -Infinity, "2016-12-27T15:10", true ],
+ ];
+
+ var element = document.createElement('input');
+ element.type = "datetime-local";
+ for (let data of testData) {
+ var caught = false;
+
+ try {
+ element.valueAsNumber = data[0];
+ is(element.value, data[1], "valueAsNumber should set the value to " +
+ data[1]);
} catch(e) {
caught = true;
}
@@ -738,6 +849,10 @@ checkMonthSet();
checkWeekGet();
checkWeekSet();
+// <input type='datetime-local'> test
+checkDatetimeLocalGet();
+checkDatetimeLocalSet();
+
</script>
</pre>
</body>
diff --git a/dom/html/test/test_anchor_ping.html b/dom/html/test/test_anchor_ping.html
index 4a39bcefe..6a1832ad1 100644
--- a/dom/html/test/test_anchor_ping.html
+++ b/dom/html/test/test_anchor_ping.html
@@ -40,15 +40,10 @@ let tests = [
function* setup() {
Services.prefs.setBoolPref("browser.send_pings", true);
Services.prefs.setIntPref("browser.send_pings.max_per_link", -1);
- Services.prefs.setBoolPref("security.mixed_content.block_active_content", false);
- // The server we create can't handle the priming HEAD requests
- Services.prefs.setBoolPref("security.mixed_content.send_hsts_priming", false);
SimpleTest.registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.send_pings");
Services.prefs.clearUserPref("browser.send_pings.max_per_link");
- Services.prefs.clearUserPref("security.mixed_content.block_active_content");
- Services.prefs.clearUserPref("security.mixed_content.send_hsts_priming");
});
},
@@ -151,7 +146,7 @@ let tests = [
// The referrer will be loaded using a secure channel.
navigate("https://example.com/chrome/dom/html/test/" +
- "file_anchor_ping.html?" + "http://localhost:" +
+ "file_anchor_ping.html?" + "http://127.0.0.1:" +
server.identity.primaryPort + ping);
// Wait until the ping has been sent.
diff --git a/dom/html/test/test_bug558788-1.html b/dom/html/test/test_bug558788-1.html
index 94b7a5f00..4db61ed73 100644
--- a/dom/html/test/test_bug558788-1.html
+++ b/dom/html/test/test_bug558788-1.html
@@ -154,13 +154,14 @@ function checkInputURL()
sendString("ttp://mozilla.org");
checkValidApplies(element);
- for (var i=0; i<13; ++i) {
+ for (var i=0; i<10; ++i) {
synthesizeKey("VK_BACK_SPACE", {});
checkValidApplies(element);
}
synthesizeKey("VK_BACK_SPACE", {});
- for (var i=0; i<4; ++i) {
+ // "http://" is now invalid
+ for (var i=0; i<7; ++i) {
checkInvalidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
}
diff --git a/dom/html/test/test_fullscreen-api-race.html b/dom/html/test/test_fullscreen-api-race.html
index 03c6c6da3..6664e2ab5 100644
--- a/dom/html/test/test_fullscreen-api-race.html
+++ b/dom/html/test/test_fullscreen-api-race.html
@@ -35,7 +35,9 @@ addLoadEvent(function () {
SpecialPowers.pushPrefEnv({
"set": [
["full-screen-api.unprefix.enabled", true],
- ["full-screen-api.allow-trusted-requests-only", false]
+ ["full-screen-api.allow-trusted-requests-only", false],
+ // Use legacy data: URI behavior to run test.
+ ["security.data_uri.block_toplevel_data_uri_navigations", false]
]
}, next);
});
diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
index 9d4e72f2f..e6fe9e2a8 100644
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -121,7 +121,7 @@
LogLevel::Debug, \
_args )
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
#define IDB_MOBILE
#endif
@@ -3694,8 +3694,6 @@ UpgradeSchemaFrom18_0To19_0(mozIStorageConnection* aConnection)
return NS_OK;
}
-#if !defined(MOZ_B2G)
-
class NormalJSContext;
class UpgradeFileIdsFunction final
@@ -3731,8 +3729,6 @@ private:
nsIVariant** aResult) override;
};
-#endif // MOZ_B2G
-
nsresult
UpgradeSchemaFrom19_0To20_0(nsIFile* aFMDirectory,
mozIStorageConnection* aConnection)
@@ -3744,20 +3740,6 @@ UpgradeSchemaFrom19_0To20_0(nsIFile* aFMDirectory,
"UpgradeSchemaFrom19_0To20_0",
js::ProfileEntry::Category::STORAGE);
-#if defined(MOZ_B2G)
-
- // We don't have to do the upgrade of file ids on B2G. The old format was
- // only used by the previous single process implementation and B2G was
- // always multi process. This is a nice optimization since the upgrade needs
- // to deserialize all structured clones which reference a stored file or
- // a mutable file.
- nsresult rv = aConnection->SetSchemaVersion(MakeSchemaVersion(20, 0));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
-#else // MOZ_B2G
-
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT count(*) "
@@ -3856,8 +3838,6 @@ UpgradeSchemaFrom19_0To20_0(nsIFile* aFMDirectory,
return rv;
}
-#endif // MOZ_B2G
-
return NS_OK;
}
@@ -7767,12 +7747,10 @@ private:
virtual void
SendResults() override;
-#ifdef ENABLE_INTL_API
static nsresult
UpdateLocaleAwareIndex(mozIStorageConnection* aConnection,
const IndexMetadata& aIndexMetadata,
const nsCString& aLocale);
-#endif
};
class OpenDatabaseOp::VersionChangeOp final
@@ -8462,12 +8440,12 @@ class ObjectStoreAddOrPutRequestOp::SCInputStream final
: public nsIInputStream
{
const JSStructuredCloneData& mData;
- JSStructuredCloneData::IterImpl mIter;
+ JSStructuredCloneData::Iterator mIter;
public:
explicit SCInputStream(const JSStructuredCloneData& aData)
: mData(aData)
- , mIter(aData.Iter())
+ , mIter(aData.Start())
{ }
private:
@@ -13492,10 +13470,6 @@ nsresult
ConnectionPool::
ThreadRunnable::Run()
{
-#ifdef MOZ_ENABLE_PROFILER_SPS
- char stackTopGuess;
-#endif // MOZ_ENABLE_PROFILER_SPS
-
MOZ_ASSERT(!IsOnBackgroundThread());
MOZ_ASSERT(mContinueRunning);
@@ -13512,10 +13486,6 @@ ThreadRunnable::Run()
const nsPrintfCString threadName("IndexedDB #%lu", mSerialNumber);
PR_SetCurrentThreadName(threadName.get());
-
-#ifdef MOZ_ENABLE_PROFILER_SPS
- profiler_register_thread(threadName.get(), &stackTopGuess);
-#endif // MOZ_ENABLE_PROFILER_SPS
}
{
@@ -13559,10 +13529,6 @@ ThreadRunnable::Run()
}
}
-#ifdef MOZ_ENABLE_PROFILER_SPS
- profiler_unregister_thread();
-#endif // MOZ_ENABLE_PROFILER_SPS
-
return NS_OK;
}
@@ -19666,8 +19632,6 @@ AutoProgressHandler::OnProgress(mozIStorageConnection* aConnection,
NS_IMPL_ISUPPORTS(CompressDataBlobsFunction, mozIStorageFunction)
NS_IMPL_ISUPPORTS(EncodeKeysFunction, mozIStorageFunction)
-#if !defined(MOZ_B2G)
-
nsresult
UpgradeFileIdsFunction::Init(nsIFile* aFMDirectory,
mozIStorageConnection* aConnection)
@@ -19723,7 +19687,7 @@ UpgradeFileIdsFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
return NS_ERROR_UNEXPECTED;
}
- StructuredCloneReadInfo cloneInfo;
+ StructuredCloneReadInfo cloneInfo(JS::StructuredCloneScope::DifferentProcess);
DatabaseOperationBase::GetStructuredCloneReadInfoFromValueArray(aArguments,
1,
0,
@@ -19762,8 +19726,6 @@ UpgradeFileIdsFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
return NS_OK;
}
-#endif // MOZ_B2G
-
// static
void
DatabaseOperationBase::GetBindingClauseForKeyRange(
@@ -19930,7 +19892,7 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromBlob(
return NS_ERROR_FILE_CORRUPTED;
}
- if (!aInfo->mData.WriteBytes(uncompressedBuffer, uncompressed.Length())) {
+ if (!aInfo->mData.AppendBytes(uncompressedBuffer, uncompressed.Length())) {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -20016,7 +19978,7 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromExternalBlob(
break;
}
- if (NS_WARN_IF(!aInfo->mData.WriteBytes(buffer, numRead))) {
+ if (NS_WARN_IF(!aInfo->mData.AppendBytes(buffer, numRead))) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
@@ -20064,9 +20026,6 @@ DatabaseOperationBase::BindKeyRangeToStatement(
mozIStorageStatement* aStatement,
const nsCString& aLocale)
{
-#ifndef ENABLE_INTL_API
- return BindKeyRangeToStatement(aKeyRange, aStatement);
-#else
MOZ_ASSERT(!IsOnBackgroundThread());
MOZ_ASSERT(aStatement);
MOZ_ASSERT(!aLocale.IsEmpty());
@@ -20104,7 +20063,6 @@ DatabaseOperationBase::BindKeyRangeToStatement(
}
return NS_OK;
-#endif
}
// static
@@ -22197,7 +22155,6 @@ OpenDatabaseOp::LoadDatabaseInformation(mozIStorageConnection* aConnection)
indexMetadata->mCommonMetadata.multiEntry() = !!scratch;
-#ifdef ENABLE_INTL_API
const bool localeAware = !stmt->IsNull(6);
if (localeAware) {
rv = stmt->GetUTF8String(6, indexMetadata->mCommonMetadata.locale());
@@ -22227,7 +22184,6 @@ OpenDatabaseOp::LoadDatabaseInformation(mozIStorageConnection* aConnection)
}
}
}
-#endif
if (NS_WARN_IF(!objectStoreMetadata->mIndexes.Put(indexId, indexMetadata,
fallible))) {
@@ -22253,7 +22209,6 @@ OpenDatabaseOp::LoadDatabaseInformation(mozIStorageConnection* aConnection)
return NS_OK;
}
-#ifdef ENABLE_INTL_API
/* static */
nsresult
OpenDatabaseOp::UpdateLocaleAwareIndex(mozIStorageConnection* aConnection,
@@ -22371,7 +22326,6 @@ OpenDatabaseOp::UpdateLocaleAwareIndex(mozIStorageConnection* aConnection,
rv = metaStmt->Execute();
return rv;
}
-#endif
nsresult
OpenDatabaseOp::BeginVersionChange()
@@ -25383,7 +25337,7 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues,
}
#endif
- StructuredCloneReadInfo cloneInfo;
+ StructuredCloneReadInfo cloneInfo(JS::StructuredCloneScope::DifferentProcess);
nsresult rv =
GetStructuredCloneReadInfoFromValueArray(aValues,
/* aDataIndex */ 3,
@@ -26592,18 +26546,9 @@ ObjectStoreAddOrPutRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
char keyPropBuffer[keyPropSize];
LittleEndian::writeUint64(keyPropBuffer, keyPropValue);
- auto iter = cloneData.Iter();
- DebugOnly<bool> result =
- iter.AdvanceAcrossSegments(cloneData, cloneInfo.offsetToKeyProp());
- MOZ_ASSERT(result);
-
- for (uint32_t index = 0; index < keyPropSize; index++) {
- char* keyPropPointer = iter.Data();
- *keyPropPointer = keyPropBuffer[index];
-
- result = iter.AdvanceAcrossSegments(cloneData, 1);
- MOZ_ASSERT(result);
- }
+ auto iter = cloneData.Start();
+ MOZ_ALWAYS_TRUE(cloneData.Advance(iter, cloneInfo.offsetToKeyProp()));
+ MOZ_ALWAYS_TRUE(cloneData.UpdateBytes(iter, keyPropBuffer, keyPropSize));
}
}
@@ -26629,7 +26574,7 @@ ObjectStoreAddOrPutRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
} else {
nsCString flatCloneData;
flatCloneData.SetLength(cloneDataSize);
- auto iter = cloneData.Iter();
+ auto iter = cloneData.Start();
cloneData.ReadBytes(iter, flatCloneData.BeginWriting(), cloneDataSize);
// Compress the bytes before adding into the database.
@@ -26886,7 +26831,7 @@ SCInputStream::ReadSegments(nsWriteSegmentFun aWriter,
*_retval += count;
aCount -= count;
- mIter.Advance(mData, count);
+ mData.Advance(mIter, count);
}
return NS_OK;
@@ -28075,7 +28020,7 @@ CursorOpBase::PopulateResponseFromStatement(
switch (mCursor->mType) {
case OpenCursorParams::TObjectStoreOpenCursorParams: {
- StructuredCloneReadInfo cloneInfo;
+ StructuredCloneReadInfo cloneInfo(JS::StructuredCloneScope::DifferentProcess);
rv = GetStructuredCloneReadInfoFromStatement(aStmt,
2,
1,
@@ -28123,7 +28068,7 @@ CursorOpBase::PopulateResponseFromStatement(
return rv;
}
- StructuredCloneReadInfo cloneInfo;
+ StructuredCloneReadInfo cloneInfo(JS::StructuredCloneScope::DifferentProcess);
rv = GetStructuredCloneReadInfoFromStatement(aStmt,
4,
3,
@@ -28191,15 +28136,12 @@ OpenOp::GetRangeKeyInfo(bool aLowerBound, Key* aKey, bool* aOpen)
if (range.isOnly()) {
*aKey = range.lower();
*aOpen = false;
-#ifdef ENABLE_INTL_API
if (mCursor->IsLocaleAware()) {
range.lower().ToLocaleBasedKey(*aKey, mCursor->mLocale);
}
-#endif
} else {
*aKey = aLowerBound ? range.lower() : range.upper();
*aOpen = aLowerBound ? range.lowerOpen() : range.upperOpen();
-#ifdef ENABLE_INTL_API
if (mCursor->IsLocaleAware()) {
if (aLowerBound) {
range.lower().ToLocaleBasedKey(*aKey, mCursor->mLocale);
@@ -28207,7 +28149,6 @@ OpenOp::GetRangeKeyInfo(bool aLowerBound, Key* aKey, bool* aOpen)
range.upper().ToLocaleBasedKey(*aKey, mCursor->mLocale);
}
}
-#endif
}
} else {
*aOpen = false;
diff --git a/dom/indexedDB/IDBCursor.cpp b/dom/indexedDB/IDBCursor.cpp
index e5d8913f9..7ae35e981 100644
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -65,13 +65,11 @@ IDBCursor::IDBCursor(Type aType,
}
}
-#ifdef ENABLE_INTL_API
bool
IDBCursor::IsLocaleAware() const
{
return mSourceIndex && !mSourceIndex->Locale().IsEmpty();
}
-#endif
IDBCursor::~IDBCursor()
{
@@ -437,7 +435,6 @@ IDBCursor::Continue(JSContext* aCx,
return;
}
-#ifdef ENABLE_INTL_API
if (IsLocaleAware() && !key.IsUnset()) {
Key tmp;
aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale());
@@ -448,9 +445,6 @@ IDBCursor::Continue(JSContext* aCx,
}
const Key& sortKey = IsLocaleAware() ? mSortKey : mKey;
-#else
- const Key& sortKey = mKey;
-#endif
if (!key.IsUnset()) {
switch (mDirection) {
@@ -547,7 +541,6 @@ IDBCursor::ContinuePrimaryKey(JSContext* aCx,
return;
}
-#ifdef ENABLE_INTL_API
if (IsLocaleAware() && !key.IsUnset()) {
Key tmp;
aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale());
@@ -558,9 +551,6 @@ IDBCursor::ContinuePrimaryKey(JSContext* aCx,
}
const Key& sortKey = IsLocaleAware() ? mSortKey : mKey;
-#else
- const Key& sortKey = mKey;
-#endif
if (key.IsUnset()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
diff --git a/dom/indexedDB/IDBCursor.h b/dom/indexedDB/IDBCursor.h
index 25be16bee..3a4bedcda 100644
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -205,11 +205,9 @@ private:
~IDBCursor();
-#ifdef ENABLE_INTL_API
// Checks if this is a locale aware cursor (ie. the index's sortKey is unset)
bool
IsLocaleAware() const;
-#endif
void
DropJSObjects();
diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
index c9ab24970..8a0b292ad 100644
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -67,7 +67,7 @@ struct IDBObjectStore::StructuredCloneWriteInfo
uint64_t mOffsetToKeyProp;
explicit StructuredCloneWriteInfo(IDBDatabase* aDatabase)
- : mCloneBuffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr,
+ : mCloneBuffer(JS::StructuredCloneScope::DifferentProcessForIndexedDB, nullptr,
nullptr)
, mDatabase(aDatabase)
, mOffsetToKeyProp(0)
@@ -859,10 +859,6 @@ public:
}
};
-// We don't need to upgrade database on B2G. See the comment in ActorsParent.cpp,
-// UpgradeSchemaFrom18_0To19_0()
-#if !defined(MOZ_B2G)
-
class UpgradeDeserializationHelper
{
public:
@@ -929,8 +925,6 @@ public:
}
};
-#endif // MOZ_B2G
-
template <class Traits>
JSObject*
CommonStructuredCloneReadCallback(JSContext* aCx,
@@ -1086,9 +1080,7 @@ IDBObjectStore::AppendIndexUpdateInfo(
{
nsresult rv;
-#ifdef ENABLE_INTL_API
const bool localeAware = !aLocale.IsEmpty();
-#endif
if (!aMultiEntry) {
Key key;
@@ -1106,14 +1098,12 @@ IDBObjectStore::AppendIndexUpdateInfo(
IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement();
updateInfo->indexId() = aIndexID;
updateInfo->value() = key;
-#ifdef ENABLE_INTL_API
if (localeAware) {
rv = key.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
-#endif
return NS_OK;
}
@@ -1153,14 +1143,12 @@ IDBObjectStore::AppendIndexUpdateInfo(
IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement();
updateInfo->indexId() = aIndexID;
updateInfo->value() = value;
-#ifdef ENABLE_INTL_API
if (localeAware) {
rv = value.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
-#endif
}
}
else {
@@ -1174,14 +1162,12 @@ IDBObjectStore::AppendIndexUpdateInfo(
IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement();
updateInfo->indexId() = aIndexID;
updateInfo->value() = value;
-#ifdef ENABLE_INTL_API
if (localeAware) {
rv = value.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
-#endif
}
return NS_OK;
@@ -1230,7 +1216,7 @@ IDBObjectStore::DeserializeValue(JSContext* aCx,
// FIXME: Consider to use StructuredCloneHolder here and in other
// deserializing methods.
if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
- JS::StructuredCloneScope::SameProcessSameThread,
+ JS::StructuredCloneScope::DifferentProcessForIndexedDB,
aValue, &callbacks, &aCloneReadInfo)) {
return false;
}
@@ -1263,7 +1249,7 @@ IDBObjectStore::DeserializeIndexValue(JSContext* aCx,
};
if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
- JS::StructuredCloneScope::SameProcessSameThread,
+ JS::StructuredCloneScope::DifferentProcessForIndexedDB,
aValue, &callbacks, &aCloneReadInfo)) {
return false;
}
@@ -1271,8 +1257,6 @@ IDBObjectStore::DeserializeIndexValue(JSContext* aCx,
return true;
}
-#if !defined(MOZ_B2G)
-
// static
bool
IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
@@ -1301,7 +1285,7 @@ IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
};
if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
- JS::StructuredCloneScope::SameProcessSameThread,
+ JS::StructuredCloneScope::DifferentProcessForIndexedDB,
aValue, &callbacks, &aCloneReadInfo)) {
return false;
}
@@ -1309,8 +1293,6 @@ IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
return true;
}
-#endif // MOZ_B2G
-
#ifdef DEBUG
void
@@ -2052,11 +2034,9 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
// Valid locale names are always ASCII as per BCP-47.
nsCString locale = NS_LossyConvertUTF16toASCII(aOptionalParameters.mLocale);
bool autoLocale = locale.EqualsASCII("auto");
-#ifdef ENABLE_INTL_API
if (autoLocale) {
locale = IndexedDatabaseManager::GetLocale();
}
-#endif
IndexMetadata* metadata = indexes.AppendElement(
IndexMetadata(transaction->NextIndexId(), nsString(aName), keyPath,
diff --git a/dom/indexedDB/IDBObjectStore.h b/dom/indexedDB/IDBObjectStore.h
index 7a255a4af..994931afa 100644
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -101,12 +101,10 @@ public:
StructuredCloneReadInfo& aCloneReadInfo,
JS::MutableHandle<JS::Value> aValue);
-#if !defined(MOZ_B2G)
static bool
DeserializeUpgradeValue(JSContext* aCx,
StructuredCloneReadInfo& aCloneReadInfo,
JS::MutableHandle<JS::Value> aValue);
-#endif
static const JSClass*
DummyPropClass()
diff --git a/dom/indexedDB/IndexedDatabase.h b/dom/indexedDB/IndexedDatabase.h
index b0c4cb877..b3c6ab725 100644
--- a/dom/indexedDB/IndexedDatabase.h
+++ b/dom/indexedDB/IndexedDatabase.h
@@ -65,6 +65,10 @@ struct StructuredCloneReadInfo
bool mHasPreprocessInfo;
// In IndexedDatabaseInlines.h
+ inline explicit
+ StructuredCloneReadInfo(JS::StructuredCloneScope aScope);
+
+ // In IndexedDatabaseInlines.h
inline
StructuredCloneReadInfo();
diff --git a/dom/indexedDB/IndexedDatabaseInlines.h b/dom/indexedDB/IndexedDatabaseInlines.h
index 830c2f110..8c34a81dd 100644
--- a/dom/indexedDB/IndexedDatabaseInlines.h
+++ b/dom/indexedDB/IndexedDatabaseInlines.h
@@ -45,14 +45,21 @@ StructuredCloneFile::operator==(const StructuredCloneFile& aOther) const
}
inline
-StructuredCloneReadInfo::StructuredCloneReadInfo()
- : mDatabase(nullptr)
+StructuredCloneReadInfo::StructuredCloneReadInfo(JS::StructuredCloneScope aScope)
+ : mData(aScope)
+ , mDatabase(nullptr)
, mHasPreprocessInfo(false)
{
MOZ_COUNT_CTOR(StructuredCloneReadInfo);
}
inline
+StructuredCloneReadInfo::StructuredCloneReadInfo()
+ : StructuredCloneReadInfo(JS::StructuredCloneScope::DifferentProcessForIndexedDB)
+{
+}
+
+inline
StructuredCloneReadInfo::StructuredCloneReadInfo(
StructuredCloneReadInfo&& aCloneReadInfo)
: mData(Move(aCloneReadInfo.mData))
diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp
index 2590b0127..62ba51c08 100644
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -59,10 +59,8 @@
#include "mozilla/dom/IDBTransactionBinding.h"
#include "mozilla/dom/IDBVersionChangeEventBinding.h"
-#ifdef ENABLE_INTL_API
#include "nsCharSeparatedTokenizer.h"
#include "unicode/locid.h"
-#endif
#define IDB_STR "indexedDB"
@@ -155,7 +153,7 @@ const char kPrefMaxSerilizedMsgSize[] = IDB_PREF_BRANCH_ROOT "maxSerializedMsgSi
const char kPrefLoggingEnabled[] = IDB_PREF_LOGGING_BRANCH_ROOT "enabled";
const char kPrefLoggingDetails[] = IDB_PREF_LOGGING_BRANCH_ROOT "details";
-#if defined(DEBUG) || defined(MOZ_ENABLE_PROFILER_SPS)
+#if defined(DEBUG)
const char kPrefLoggingProfiler[] =
IDB_PREF_LOGGING_BRANCH_ROOT "profiler-marks";
#endif
@@ -417,10 +415,7 @@ IndexedDatabaseManager::Init()
Preferences::RegisterCallback(LoggingModePrefChangedCallback,
kPrefLoggingDetails);
-#ifdef MOZ_ENABLE_PROFILER_SPS
- Preferences::RegisterCallback(LoggingModePrefChangedCallback,
- kPrefLoggingProfiler);
-#endif
+
Preferences::RegisterCallbackAndCall(LoggingModePrefChangedCallback,
kPrefLoggingEnabled);
@@ -430,7 +425,6 @@ IndexedDatabaseManager::Init()
Preferences::RegisterCallbackAndCall(MaxSerializedMsgSizePrefChangeCallback,
kPrefMaxSerilizedMsgSize);
-#ifdef ENABLE_INTL_API
const nsAdoptingCString& acceptLang =
Preferences::GetLocalizedCString("intl.accept_languages");
@@ -449,7 +443,6 @@ IndexedDatabaseManager::Init()
if (mLocale.IsEmpty()) {
mLocale.AssignLiteral("en_US");
}
-#endif
return NS_OK;
}
@@ -483,10 +476,6 @@ IndexedDatabaseManager::Destroy()
Preferences::UnregisterCallback(LoggingModePrefChangedCallback,
kPrefLoggingDetails);
-#ifdef MOZ_ENABLE_PROFILER_SPS
- Preferences::UnregisterCallback(LoggingModePrefChangedCallback,
- kPrefLoggingProfiler);
-#endif
Preferences::UnregisterCallback(LoggingModePrefChangedCallback,
kPrefLoggingEnabled);
@@ -1064,15 +1053,13 @@ IndexedDatabaseManager::LoggingModePrefChangedCallback(
}
bool useProfiler =
-#if defined(DEBUG) || defined(MOZ_ENABLE_PROFILER_SPS)
+#if defined(DEBUG)
Preferences::GetBool(kPrefLoggingProfiler);
-#if !defined(MOZ_ENABLE_PROFILER_SPS)
if (useProfiler) {
NS_WARNING("IndexedDB cannot create profiler marks because this build does "
"not have profiler extensions enabled!");
useProfiler = false;
}
-#endif
#else
false;
#endif
@@ -1088,7 +1075,6 @@ IndexedDatabaseManager::LoggingModePrefChangedCallback(
}
}
-#ifdef ENABLE_INTL_API
// static
const nsCString&
IndexedDatabaseManager::GetLocale()
@@ -1098,7 +1084,6 @@ IndexedDatabaseManager::GetLocale()
return idbManager->mLocale;
}
-#endif
NS_IMPL_ADDREF(IndexedDatabaseManager)
NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy())
diff --git a/dom/indexedDB/IndexedDatabaseManager.h b/dom/indexedDB/IndexedDatabaseManager.h
index 8bb9d7003..d63c548ec 100644
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -186,10 +186,8 @@ public:
nsresult
FlushPendingFileDeletions();
-#ifdef ENABLE_INTL_API
static const nsCString&
GetLocale();
-#endif
static mozilla::Mutex&
FileMutex()
@@ -238,9 +236,7 @@ private:
// and FileInfo.mSliceRefCnt
mozilla::Mutex mFileMutex;
-#ifdef ENABLE_INTL_API
nsCString mLocale;
-#endif
indexedDB::BackgroundUtilsChild* mBackgroundActor;
diff --git a/dom/indexedDB/Key.cpp b/dom/indexedDB/Key.cpp
index 945320dd5..0f693b2c6 100644
--- a/dom/indexedDB/Key.cpp
+++ b/dom/indexedDB/Key.cpp
@@ -22,9 +22,7 @@
#include "ReportInternalError.h"
#include "xpcpublic.h"
-#ifdef ENABLE_INTL_API
#include "unicode/ucol.h"
-#endif
namespace mozilla {
namespace dom {
@@ -108,7 +106,6 @@ namespace indexedDB {
[1, 2] // 0x60 bf f0 0 0 0 0 0 0 0x10 c0
[[]] // 0x80
*/
-#ifdef ENABLE_INTL_API
nsresult
Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const
{
@@ -202,7 +199,6 @@ Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const
aTarget.TrimBuffer();
return NS_OK;
}
-#endif
nsresult
Key::EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
@@ -483,7 +479,6 @@ Key::EncodeAsString(const T* aStart, const T* aEnd, uint8_t aType)
NS_ASSERTION(buffer == mBuffer.EndReading(), "Wrote wrong number of bytes");
}
-#ifdef ENABLE_INTL_API
nsresult
Key::EncodeLocaleString(const nsDependentString& aString, uint8_t aTypeOffset,
const nsCString& aLocale)
@@ -522,7 +517,6 @@ Key::EncodeLocaleString(const nsDependentString& aString, uint8_t aTypeOffset,
aTypeOffset);
return NS_OK;
}
-#endif
// static
nsresult
diff --git a/dom/indexedDB/Key.h b/dom/indexedDB/Key.h
index 856089c97..9d70ce6ad 100644
--- a/dom/indexedDB/Key.h
+++ b/dom/indexedDB/Key.h
@@ -214,10 +214,8 @@ public:
nsresult
AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal);
-#ifdef ENABLE_INTL_API
nsresult
ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const;
-#endif
void
FinishArray()
@@ -298,11 +296,9 @@ private:
void
EncodeAsString(const T* aStart, const T* aEnd, uint8_t aType);
-#ifdef ENABLE_INTL_API
nsresult
EncodeLocaleString(const nsDependentString& aString, uint8_t aTypeOffset,
const nsCString& aLocale);
-#endif
void
EncodeNumber(double aFloat, uint8_t aType);
diff --git a/dom/indexedDB/moz.build b/dom/indexedDB/moz.build
index 1fb01135c..d8c217f38 100644
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -17,8 +17,7 @@ XPCSHELL_TESTS_MANIFESTS += [
'test/unit/xpcshell-parent-process.ini'
]
-if CONFIG['ENABLE_INTL_API']:
- MOCHITEST_MANIFESTS += ['test/mochitest-intl-api.ini']
+MOCHITEST_MANIFESTS += ['test/mochitest-intl-api.ini']
EXPORTS.mozilla.dom += [
'IDBCursor.h',
diff --git a/dom/indexedDB/test/browser_forgetThisSite.js b/dom/indexedDB/test/browser_forgetThisSite.js
index c1177908f..02674922f 100644
--- a/dom/indexedDB/test/browser_forgetThisSite.js
+++ b/dom/indexedDB/test/browser_forgetThisSite.js
@@ -67,9 +67,10 @@ function test2()
function test3()
{
// Remove database from domain 2
- ForgetAboutSite.removeDataFromDomain(domains[1]);
- setPermission(testPageURL4, "indexedDB");
- executeSoon(test4);
+ ForgetAboutSite.removeDataFromDomain(domains[1]).then(() => {
+ setPermission(testPageURL4, "indexedDB");
+ executeSoon(test4);
+ });
}
function test4()
diff --git a/dom/indexedDB/test/unit/xpcshell-child-process.ini b/dom/indexedDB/test/unit/xpcshell-child-process.ini
index 970fe8c3d..5918471ea 100644
--- a/dom/indexedDB/test/unit/xpcshell-child-process.ini
+++ b/dom/indexedDB/test/unit/xpcshell-child-process.ini
@@ -6,7 +6,7 @@
dupe-manifest =
head = xpcshell-head-child-process.js
tail =
-skip-if = toolkit == 'android' || toolkit == 'gonk'
+skip-if = toolkit == 'android'
support-files =
GlobalObjectsChild.js
GlobalObjectsComponent.js
diff --git a/dom/indexedDB/test/unit/xpcshell-parent-process.ini b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
index 22bc861cc..04df5f552 100644
--- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini
+++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
@@ -6,7 +6,6 @@
dupe-manifest =
head = xpcshell-head-parent-process.js
tail =
-skip-if = toolkit == 'gonk'
support-files =
bug1056939_profile.zip
defaultStorageUpgrade_profile.zip
diff --git a/dom/inputmethod/HardwareKeyHandler.cpp b/dom/inputmethod/HardwareKeyHandler.cpp
deleted file mode 100644
index 737c30e5b..000000000
--- a/dom/inputmethod/HardwareKeyHandler.cpp
+++ /dev/null
@@ -1,562 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "HardwareKeyHandler.h"
-#include "mozilla/BasicEvents.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/KeyboardEvent.h"
-#include "mozilla/dom/TabParent.h"
-#include "mozilla/EventDispatcher.h"
-#include "mozilla/EventStateManager.h"
-#include "mozilla/TextEvents.h"
-#include "nsDeque.h"
-#include "nsFocusManager.h"
-#include "nsFrameLoader.h"
-#include "nsIContent.h"
-#include "nsIDOMHTMLDocument.h"
-#include "nsIDOMHTMLElement.h"
-#include "nsPIDOMWindow.h"
-#include "nsPresContext.h"
-#include "nsPresShell.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-NS_IMPL_ISUPPORTS(HardwareKeyHandler, nsIHardwareKeyHandler)
-
-StaticRefPtr<HardwareKeyHandler> HardwareKeyHandler::sInstance;
-
-HardwareKeyHandler::HardwareKeyHandler()
- : mInputMethodAppConnected(false)
-{
-}
-
-HardwareKeyHandler::~HardwareKeyHandler()
-{
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::OnInputMethodAppConnected()
-{
- if (NS_WARN_IF(mInputMethodAppConnected)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- mInputMethodAppConnected = true;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::OnInputMethodAppDisconnected()
-{
- if (NS_WARN_IF(!mInputMethodAppConnected)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- mInputMethodAppConnected = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::RegisterListener(nsIHardwareKeyEventListener* aListener)
-{
- // Make sure the listener is not nullptr and there is no available
- // hardwareKeyEventListener now
- if (NS_WARN_IF(!aListener)) {
- return NS_ERROR_NULL_POINTER;
- }
-
- if (NS_WARN_IF(mHardwareKeyEventListener)) {
- return NS_ERROR_ALREADY_INITIALIZED;
- }
-
- mHardwareKeyEventListener = do_GetWeakReference(aListener);
-
- if (NS_WARN_IF(!mHardwareKeyEventListener)) {
- return NS_ERROR_NULL_POINTER;
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::UnregisterListener()
-{
- // Clear the HardwareKeyEventListener
- mHardwareKeyEventListener = nullptr;
- return NS_OK;
-}
-
-bool
-HardwareKeyHandler::ForwardKeyToInputMethodApp(nsINode* aTarget,
- WidgetKeyboardEvent* aEvent,
- nsEventStatus* aEventStatus)
-{
- MOZ_ASSERT(aTarget, "No target provided");
- MOZ_ASSERT(aEvent, "No event provided");
-
- // No need to forward hardware key event to IME
- // if key's defaultPrevented is true
- if (aEvent->mFlags.mDefaultPrevented) {
- return false;
- }
-
- // No need to forward hardware key event to IME if IME is disabled
- if (!mInputMethodAppConnected) {
- return false;
- }
-
- // No need to forward hardware key event to IME
- // if this key event is generated by IME itself(from nsITextInputProcessor)
- if (aEvent->mIsSynthesizedByTIP) {
- return false;
- }
-
- // No need to forward hardware key event to IME
- // if the key event is handling or already handled
- if (aEvent->mInputMethodAppState != WidgetKeyboardEvent::eNotHandled) {
- return false;
- }
-
- // No need to forward hardware key event to IME
- // if there is no nsIHardwareKeyEventListener in use
- nsCOMPtr<nsIHardwareKeyEventListener>
- keyHandler(do_QueryReferent(mHardwareKeyEventListener));
- if (!keyHandler) {
- return false;
- }
-
- // Set the flags to specify the keyboard event is in forwarding phase.
- aEvent->mInputMethodAppState = WidgetKeyboardEvent::eHandling;
-
- // For those keypress events coming after their heading keydown's reply
- // already arrives, they should be dispatched directly instead of
- // being stored into the event queue. Otherwise, without the heading keydown
- // in the event queue, the stored keypress will never be withdrawn to be fired.
- if (aEvent->mMessage == eKeyPress && mEventQueue.IsEmpty()) {
- DispatchKeyPress(aTarget, *aEvent, *aEventStatus);
- return true;
- }
-
- // Push the key event into queue for reuse when its reply arrives.
- KeyboardInfo* copiedInfo =
- new KeyboardInfo(aTarget,
- *aEvent,
- aEventStatus ? *aEventStatus : nsEventStatus_eIgnore);
-
- // No need to forward hardware key event to IME if the event queue is full
- if (!mEventQueue.Push(copiedInfo)) {
- delete copiedInfo;
- return false;
- }
-
- // We only forward keydown and keyup event to input-method-app
- // because input-method-app will generate keypress by itself.
- if (aEvent->mMessage == eKeyPress) {
- return true;
- }
-
- // Create a keyboard event to pass into
- // nsIHardwareKeyEventListener.onHardwareKey
- nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
- nsPresContext* presContext = GetPresContext(aTarget);
- RefPtr<KeyboardEvent> keyboardEvent =
- NS_NewDOMKeyboardEvent(eventTarget, presContext, aEvent->AsKeyboardEvent());
- // Duplicate the internal event data in the heap for the keyboardEvent,
- // or the internal data from |aEvent| in the stack may be destroyed by others.
- keyboardEvent->DuplicatePrivateData();
-
- // Forward the created keyboard event to input-method-app
- bool isSent = false;
- keyHandler->OnHardwareKey(keyboardEvent, &isSent);
-
- // Pop the pending key event if it can't be forwarded
- if (!isSent) {
- mEventQueue.RemoveFront();
- }
-
- return isSent;
-}
-
-NS_IMETHODIMP
-HardwareKeyHandler::OnHandledByInputMethodApp(const nsAString& aType,
- uint16_t aDefaultPrevented)
-{
- // We can not handle this reply because the pending events had been already
- // removed from the forwarding queue before this reply arrives.
- if (mEventQueue.IsEmpty()) {
- return NS_OK;
- }
-
- RefPtr<KeyboardInfo> keyInfo = mEventQueue.PopFront();
-
- // Only allow keydown and keyup to call this method
- if (NS_WARN_IF(aType.EqualsLiteral("keydown") &&
- keyInfo->mEvent.mMessage != eKeyDown) ||
- NS_WARN_IF(aType.EqualsLiteral("keyup") &&
- keyInfo->mEvent.mMessage != eKeyUp)) {
- return NS_ERROR_INVALID_ARG;
- }
-
- // The value of defaultPrevented depends on whether or not
- // the key is consumed by input-method-app
- SetDefaultPrevented(keyInfo->mEvent, aDefaultPrevented);
-
- // Set the flag to specify the reply phase
- keyInfo->mEvent.mInputMethodAppState = WidgetKeyboardEvent::eHandled;
-
- // Check whether the event is still valid to be fired
- if (CanDispatchEvent(keyInfo->mTarget, keyInfo->mEvent)) {
- // If the key's defaultPrevented is true, it means that the
- // input-method-app has already consumed this key,
- // so we can dispatch |mozbrowserafterkey*| directly if
- // preference "dom.beforeAfterKeyboardEvent.enabled" is enabled.
- if (keyInfo->mEvent.mFlags.mDefaultPrevented) {
- DispatchAfterKeyEvent(keyInfo->mTarget, keyInfo->mEvent);
- // Otherwise, it means that input-method-app doesn't handle this key,
- // so we need to dispatch it to its current event target.
- } else {
- DispatchToTargetApp(keyInfo->mTarget,
- keyInfo->mEvent,
- keyInfo->mStatus);
- }
- }
-
- // No need to do further processing if the event is not keydown
- if (keyInfo->mEvent.mMessage != eKeyDown) {
- return NS_OK;
- }
-
- // Update the latest keydown data:
- // Release the holding reference to the previous keydown's data and
- // add a reference count to the current keydown's data.
- mLatestKeyDownInfo = keyInfo;
-
- // Handle the pending keypress event once keydown's reply arrives:
- // It may have many keypress events per keydown on some platforms,
- // so we use loop to dispatch keypress events.
- // (But Gonk dispatch only one keypress per keydown)
- // However, if there is no keypress after this keydown,
- // then those following keypress will be handled in
- // ForwardKeyToInputMethodApp directly.
- for (KeyboardInfo* keypressInfo;
- !mEventQueue.IsEmpty() &&
- (keypressInfo = mEventQueue.PeekFront()) &&
- keypressInfo->mEvent.mMessage == eKeyPress;
- mEventQueue.RemoveFront()) {
- DispatchKeyPress(keypressInfo->mTarget,
- keypressInfo->mEvent,
- keypressInfo->mStatus);
- }
-
- return NS_OK;
-}
-
-bool
-HardwareKeyHandler::DispatchKeyPress(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus& aStatus)
-{
- MOZ_ASSERT(aTarget, "No target provided");
- MOZ_ASSERT(aEvent.mMessage == eKeyPress, "Event is not keypress");
-
- // No need to dispatch keypress to the event target
- // if the keydown event is consumed by the input-method-app.
- if (mLatestKeyDownInfo &&
- mLatestKeyDownInfo->mEvent.mFlags.mDefaultPrevented) {
- return false;
- }
-
- // No need to dispatch keypress to the event target
- // if the previous keydown event is modifier key's
- if (mLatestKeyDownInfo &&
- mLatestKeyDownInfo->mEvent.IsModifierKeyEvent()) {
- return false;
- }
-
- // No need to dispatch keypress to the event target
- // if it's invalid to be dispatched
- if (!CanDispatchEvent(aTarget, aEvent)) {
- return false;
- }
-
- // Set the flag to specify the reply phase.
- aEvent.mInputMethodAppState = WidgetKeyboardEvent::eHandled;
-
- // Dispatch the pending keypress event
- bool ret = DispatchToTargetApp(aTarget, aEvent, aStatus);
-
- // Re-trigger EventStateManager::PostHandleKeyboardEvent for keypress
- PostHandleKeyboardEvent(aTarget, aEvent, aStatus);
-
- return ret;
-}
-
-void
-HardwareKeyHandler::DispatchAfterKeyEvent(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent)
-{
- MOZ_ASSERT(aTarget, "No target provided");
-
- if (!PresShell::BeforeAfterKeyboardEventEnabled() ||
- aEvent.mMessage == eKeyPress) {
- return;
- }
-
- nsCOMPtr<nsIPresShell> presShell = GetPresShell(aTarget);
- if (NS_WARN_IF(presShell)) {
- presShell->DispatchAfterKeyboardEvent(aTarget,
- aEvent,
- aEvent.mFlags.mDefaultPrevented);
- }
-}
-
-bool
-HardwareKeyHandler::DispatchToTargetApp(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus& aStatus)
-{
- MOZ_ASSERT(aTarget, "No target provided");
-
- // Get current focused element as the event target
- nsCOMPtr<nsIContent> currentTarget = GetCurrentTarget();
- if (NS_WARN_IF(!currentTarget)) {
- return false;
- }
-
- // The event target should be set to the current focused element.
- // However, it might have security issue if the event is dispatched to
- // the unexpected application, and it might cause unexpected operation
- // in the new app.
- nsCOMPtr<nsPIDOMWindowOuter> originalRootWindow = GetRootWindow(aTarget);
- nsCOMPtr<nsPIDOMWindowOuter> currentRootWindow = GetRootWindow(currentTarget);
- if (currentRootWindow != originalRootWindow) {
- NS_WARNING("The root window is changed during the event is dispatching");
- return false;
- }
-
- // If the current focused element is still in the same app,
- // then we can use it as the current target to dispatch event.
- nsCOMPtr<nsIPresShell> presShell = GetPresShell(currentTarget);
- if (!presShell) {
- return false;
- }
-
- if (!presShell->CanDispatchEvent(&aEvent)) {
- return false;
- }
-
- // In-process case: the event target is in the current process
- if (!PresShell::IsTargetIframe(currentTarget)) {
- DispatchToCurrentProcess(presShell, currentTarget, aEvent, aStatus);
-
- if (presShell->CanDispatchEvent(&aEvent)) {
- DispatchAfterKeyEvent(aTarget, aEvent);
- }
-
- return true;
- }
-
- // OOP case: the event target is in the child process
- return DispatchToCrossProcess(aTarget, aEvent);
-
- // After the oop target receives the event from TabChild::RecvRealKeyEvent
- // and return the result through TabChild::SendDispatchAfterKeyboardEvent,
- // the |mozbrowserafterkey*| will be fired from
- // TabParent::RecvDispatchAfterKeyboardEvent, so we don't need to dispatch
- // |mozbrowserafterkey*| by ourselves in this module.
-}
-
-void
-HardwareKeyHandler::DispatchToCurrentProcess(nsIPresShell* presShell,
- nsIContent* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus& aStatus)
-{
- EventDispatcher::Dispatch(aTarget, presShell->GetPresContext(),
- &aEvent, nullptr, &aStatus, nullptr);
-}
-
-bool
-HardwareKeyHandler::DispatchToCrossProcess(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent)
-{
- nsCOMPtr<nsIFrameLoaderOwner> remoteLoaderOwner = do_QueryInterface(aTarget);
- if (NS_WARN_IF(!remoteLoaderOwner)) {
- return false;
- }
-
- RefPtr<nsFrameLoader> remoteFrameLoader =
- remoteLoaderOwner->GetFrameLoader();
- if (NS_WARN_IF(!remoteFrameLoader)) {
- return false;
- }
-
- uint32_t eventMode;
- remoteFrameLoader->GetEventMode(&eventMode);
- if (eventMode == nsIFrameLoader::EVENT_MODE_DONT_FORWARD_TO_CHILD) {
- return false;
- }
-
- PBrowserParent* remoteBrowser = remoteFrameLoader->GetRemoteBrowser();
- TabParent* remote = static_cast<TabParent*>(remoteBrowser);
- if (NS_WARN_IF(!remote)) {
- return false;
- }
-
- return remote->SendRealKeyEvent(aEvent);
-}
-
-void
-HardwareKeyHandler::PostHandleKeyboardEvent(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus& aStatus)
-{
- MOZ_ASSERT(aTarget, "No target provided");
-
- nsPresContext* presContext = GetPresContext(aTarget);
-
- RefPtr<mozilla::EventStateManager> esm = presContext->EventStateManager();
- bool dispatchedToChildProcess = PresShell::IsTargetIframe(aTarget);
- esm->PostHandleKeyboardEvent(&aEvent, aStatus, dispatchedToChildProcess);
-}
-
-void
-HardwareKeyHandler::SetDefaultPrevented(WidgetKeyboardEvent& aEvent,
- uint16_t aDefaultPrevented) {
- if (aDefaultPrevented & DEFAULT_PREVENTED) {
- aEvent.mFlags.mDefaultPrevented = true;
- }
-
- if (aDefaultPrevented & DEFAULT_PREVENTED_BY_CHROME) {
- aEvent.mFlags.mDefaultPreventedByChrome = true;
- }
-
- if (aDefaultPrevented & DEFAULT_PREVENTED_BY_CONTENT) {
- aEvent.mFlags.mDefaultPreventedByContent = true;
- }
-}
-
-bool
-HardwareKeyHandler::CanDispatchEvent(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent)
-{
- nsCOMPtr<nsIPresShell> presShell = GetPresShell(aTarget);
- if (NS_WARN_IF(!presShell)) {
- return false;
- }
- return presShell->CanDispatchEvent(&aEvent);
-}
-
-already_AddRefed<nsPIDOMWindowOuter>
-HardwareKeyHandler::GetRootWindow(nsINode* aNode)
-{
- // Get nsIPresShell's pointer first
- nsCOMPtr<nsIPresShell> presShell = GetPresShell(aNode);
- if (NS_WARN_IF(!presShell)) {
- return nullptr;
- }
- nsCOMPtr<nsPIDOMWindowOuter> rootWindow = presShell->GetRootWindow();
- return rootWindow.forget();
-}
-
-already_AddRefed<nsIContent>
-HardwareKeyHandler::GetCurrentTarget()
-{
- nsFocusManager* fm = nsFocusManager::GetFocusManager();
- if (NS_WARN_IF(!fm)) {
- return nullptr;
- }
-
- nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
- fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
- if (NS_WARN_IF(!focusedWindow)) {
- return nullptr;
- }
-
- auto* ourWindow = nsPIDOMWindowOuter::From(focusedWindow);
-
- nsCOMPtr<nsPIDOMWindowOuter> rootWindow = ourWindow->GetPrivateRoot();
- if (NS_WARN_IF(!rootWindow)) {
- return nullptr;
- }
-
- nsCOMPtr<nsPIDOMWindowOuter> focusedFrame;
- nsCOMPtr<nsIContent> focusedContent =
- fm->GetFocusedDescendant(rootWindow, true, getter_AddRefs(focusedFrame));
-
- // If there is no focus, then we use document body instead
- if (NS_WARN_IF(!focusedContent || !focusedContent->GetPrimaryFrame())) {
- nsIDocument* document = ourWindow->GetExtantDoc();
- if (NS_WARN_IF(!document)) {
- return nullptr;
- }
-
- focusedContent = document->GetRootElement();
-
- nsCOMPtr<nsIDOMHTMLDocument> htmlDocument = do_QueryInterface(document);
- if (htmlDocument) {
- nsCOMPtr<nsIDOMHTMLElement> body;
- htmlDocument->GetBody(getter_AddRefs(body));
- nsCOMPtr<nsIContent> bodyContent = do_QueryInterface(body);
- if (bodyContent) {
- focusedContent = bodyContent;
- }
- }
- }
-
- return focusedContent ? focusedContent.forget() : nullptr;
-}
-
-nsPresContext*
-HardwareKeyHandler::GetPresContext(nsINode* aNode)
-{
- // Get nsIPresShell's pointer first
- nsCOMPtr<nsIPresShell> presShell = GetPresShell(aNode);
- if (NS_WARN_IF(!presShell)) {
- return nullptr;
- }
-
- // then use nsIPresShell to get nsPresContext's pointer
- return presShell->GetPresContext();
-}
-
-already_AddRefed<nsIPresShell>
-HardwareKeyHandler::GetPresShell(nsINode* aNode)
-{
- nsIDocument* doc = aNode->OwnerDoc();
- if (NS_WARN_IF(!doc)) {
- return nullptr;
- }
-
- nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
- if (NS_WARN_IF(!presShell)) {
- return nullptr;
- }
-
- return presShell.forget();
-}
-
-/* static */
-already_AddRefed<HardwareKeyHandler>
-HardwareKeyHandler::GetInstance()
-{
- if (!XRE_IsParentProcess()) {
- return nullptr;
- }
-
- if (!sInstance) {
- sInstance = new HardwareKeyHandler();
- ClearOnShutdown(&sInstance);
- }
-
- RefPtr<HardwareKeyHandler> service = sInstance.get();
- return service.forget();
-}
-
-} // namespace mozilla
diff --git a/dom/inputmethod/HardwareKeyHandler.h b/dom/inputmethod/HardwareKeyHandler.h
deleted file mode 100644
index 7520c40cd..000000000
--- a/dom/inputmethod/HardwareKeyHandler.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_HardwareKeyHandler_h_
-#define mozilla_HardwareKeyHandler_h_
-
-#include "mozilla/EventForwards.h" // for nsEventStatus
-#include "mozilla/StaticPtr.h"
-#include "mozilla/TextEvents.h"
-#include "nsCOMPtr.h"
-#include "nsDeque.h"
-#include "nsIHardwareKeyHandler.h"
-#include "nsIWeakReferenceUtils.h" // for nsWeakPtr
-
-class nsIContent;
-class nsINode;
-class nsIPresShell;
-class nsPIDOMWindowOuter;
-class nsPresContext;
-
-namespace mozilla {
-
-// This module will copy the events' data into its event queue for reuse
-// after receiving input-method-app's reply, so we use the following struct
-// for storing these information.
-// RefCounted<T> is a helper class for adding reference counting mechanism.
-struct KeyboardInfo : public RefCounted<KeyboardInfo>
-{
- MOZ_DECLARE_REFCOUNTED_TYPENAME(KeyboardInfo)
-
- nsINode* mTarget;
- WidgetKeyboardEvent mEvent;
- nsEventStatus mStatus;
-
- KeyboardInfo(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus aStatus)
- : mTarget(aTarget)
- , mEvent(aEvent)
- , mStatus(aStatus)
- {
- }
-};
-
-// The following is the type-safe wrapper around nsDeque
-// for storing events' data.
-// The T must be one class that supports reference counting mechanism.
-// The EventQueueDeallocator will be called in nsDeque::~nsDeque() or
-// nsDeque::Erase() to deallocate the objects. nsDeque::Erase() will remove
-// and delete all items in the queue. See more from nsDeque.h.
-template <class T>
-class EventQueueDeallocator : public nsDequeFunctor
-{
- virtual void* operator() (void* aObject)
- {
- RefPtr<T> releaseMe = dont_AddRef(static_cast<T*>(aObject));
- return nullptr;
- }
-};
-
-// The type-safe queue to be used to store the KeyboardInfo data
-template <class T>
-class EventQueue : private nsDeque
-{
-public:
- EventQueue()
- : nsDeque(new EventQueueDeallocator<T>())
- {
- };
-
- ~EventQueue()
- {
- Clear();
- }
-
- inline size_t GetSize()
- {
- return nsDeque::GetSize();
- }
-
- bool IsEmpty()
- {
- return !nsDeque::GetSize();
- }
-
- inline bool Push(T* aItem)
- {
- MOZ_ASSERT(aItem);
- NS_ADDREF(aItem);
- size_t sizeBefore = GetSize();
- nsDeque::Push(aItem);
- if (GetSize() != sizeBefore + 1) {
- NS_RELEASE(aItem);
- return false;
- }
- return true;
- }
-
- inline already_AddRefed<T> PopFront()
- {
- RefPtr<T> rv = dont_AddRef(static_cast<T*>(nsDeque::PopFront()));
- return rv.forget();
- }
-
- inline void RemoveFront()
- {
- RefPtr<T> releaseMe = PopFront();
- }
-
- inline T* PeekFront()
- {
- return static_cast<T*>(nsDeque::PeekFront());
- }
-
- void Clear()
- {
- while (GetSize() > 0) {
- RemoveFront();
- }
- }
-};
-
-class HardwareKeyHandler : public nsIHardwareKeyHandler
-{
-public:
- HardwareKeyHandler();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIHARDWAREKEYHANDLER
-
- static already_AddRefed<HardwareKeyHandler> GetInstance();
-
- virtual bool ForwardKeyToInputMethodApp(nsINode* aTarget,
- WidgetKeyboardEvent* aEvent,
- nsEventStatus* aEventStatus) override;
-
-private:
- virtual ~HardwareKeyHandler();
-
- // Return true if the keypress is successfully dispatched.
- // Otherwise, return false.
- bool DispatchKeyPress(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus& aStatus);
-
- void DispatchAfterKeyEvent(nsINode* aTarget, WidgetKeyboardEvent& aEvent);
-
- void DispatchToCurrentProcess(nsIPresShell* aPresShell,
- nsIContent* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus& aStatus);
-
- bool DispatchToCrossProcess(nsINode* aTarget, WidgetKeyboardEvent& aEvent);
-
- // This method will dispatch not only key* event to its event target,
- // no mather it's in the current process or in its child process,
- // but also mozbrowserafterkey* to the corresponding target if it needs.
- // Return true if the key is successfully dispatched.
- // Otherwise, return false.
- bool DispatchToTargetApp(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus& aStatus);
-
- // This method will be called after dispatching keypress to its target,
- // if the input-method-app doesn't handle the key.
- // In normal dispatching path, EventStateManager::PostHandleKeyboardEvent
- // will be called when event is keypress.
- // However, the ::PostHandleKeyboardEvent mentioned above will be aborted
- // when we try to forward key event to the input-method-app.
- // If the input-method-app consumes the key, then we don't need to do anything
- // because the input-method-app will generate a new key event by itself.
- // On the other hand, if the input-method-app doesn't consume the key,
- // then we need to dispatch the key event by ourselves
- // and call ::PostHandleKeyboardEvent again after the event is forwarded.
- // Note that the EventStateManager::PreHandleEvent is already called before
- // forwarding, so we don't need to call it in this module.
- void PostHandleKeyboardEvent(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent,
- nsEventStatus& aStatus);
-
- void SetDefaultPrevented(WidgetKeyboardEvent& aEvent,
- uint16_t aDefaultPrevented);
-
- // Check whether the event is valid to be fired.
- // This method should be called every time before dispatching next event.
- bool CanDispatchEvent(nsINode* aTarget,
- WidgetKeyboardEvent& aEvent);
-
- already_AddRefed<nsPIDOMWindowOuter> GetRootWindow(nsINode* aNode);
-
- already_AddRefed<nsIContent> GetCurrentTarget();
-
- nsPresContext* GetPresContext(nsINode* aNode);
-
- already_AddRefed<nsIPresShell> GetPresShell(nsINode* aNode);
-
- static StaticRefPtr<HardwareKeyHandler> sInstance;
-
- // The event queue is used to store the forwarded keyboard events.
- // Those stored events will be dispatched if input-method-app doesn't
- // consume them.
- EventQueue<KeyboardInfo> mEventQueue;
-
- // Hold the pointer to the latest keydown's data
- RefPtr<KeyboardInfo> mLatestKeyDownInfo;
-
- // input-method-app needs to register a listener by
- // |nsIHardwareKeyHandler.registerListener| to receive
- // the hardware keyboard event, and |nsIHardwareKeyHandler.registerListener|
- // will set an nsIHardwareKeyEventListener to mHardwareKeyEventListener.
- // Then, mHardwareKeyEventListener is used to forward the event
- // to the input-method-app.
- nsWeakPtr mHardwareKeyEventListener;
-
- // To keep tracking the input-method-app is active or disabled.
- bool mInputMethodAppConnected;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_HardwareKeyHandler_h_
diff --git a/dom/inputmethod/Keyboard.jsm b/dom/inputmethod/Keyboard.jsm
index 22f87ffbc..51506c41f 100644
--- a/dom/inputmethod/Keyboard.jsm
+++ b/dom/inputmethod/Keyboard.jsm
@@ -24,12 +24,7 @@ XPCOMUtils.defineLazyGetter(this, "appsService", function() {
});
XPCOMUtils.defineLazyGetter(this, "hardwareKeyHandler", function() {
-#ifdef MOZ_B2G
- return Cc["@mozilla.org/HardwareKeyHandler;1"]
- .getService(Ci.nsIHardwareKeyHandler);
-#else
return null;
-#endif
});
var Utils = {
@@ -50,17 +45,6 @@ var Utils = {
};
this.Keyboard = {
-#ifdef MOZ_B2G
- // For receving keyboard event fired from hardware before it's dispatched,
- // |this| object is used to be the listener to get the forwarded event.
- // As the listener, |this| object must implement nsIHardwareKeyEventListener
- // and nsSupportsWeakReference.
- // Please see nsIHardwareKeyHandler.idl to get more information.
- QueryInterface: XPCOMUtils.generateQI([
- Ci.nsIHardwareKeyEventListener,
- Ci.nsISupportsWeakReference
- ]),
-#endif
_isConnectedToHardwareKeyHandler: false,
_formMM: null, // The current web page message manager.
_keyboardMM: null, // The keyboard app message manager.
diff --git a/dom/inputmethod/moz.build b/dom/inputmethod/moz.build
index 504e2ebfc..84b3cb8ab 100644
--- a/dom/inputmethod/moz.build
+++ b/dom/inputmethod/moz.build
@@ -4,29 +4,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-if CONFIG['MOZ_B2G']:
- XPIDL_SOURCES += [
- 'nsIHardwareKeyHandler.idl',
- ]
-
- XPIDL_MODULE = 'inputmethod'
-
- EXPORTS.mozilla += [
- 'HardwareKeyHandler.h',
- ]
-
- SOURCES += [
- 'HardwareKeyHandler.cpp'
- ]
-
- include('/ipc/chromium/chromium-config.mozbuild')
-
- FINAL_LIBRARY = 'xul'
- LOCAL_INCLUDES += [
- '/dom/base',
- '/layout/base',
- ]
-
EXTRA_COMPONENTS += [
'InputMethod.manifest',
'MozKeyboard.js',
diff --git a/dom/inputmethod/nsIHardwareKeyHandler.idl b/dom/inputmethod/nsIHardwareKeyHandler.idl
deleted file mode 100644
index 5bce4d980..000000000
--- a/dom/inputmethod/nsIHardwareKeyHandler.idl
+++ /dev/null
@@ -1,142 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMKeyEvent;
-
-%{C++
-#define NS_HARDWARE_KEY_HANDLER_CID \
- { 0xfb45921b, 0xe0a5, 0x45c6, \
- { 0x90, 0xd0, 0xa6, 0x97, 0xa7, 0x72, 0xc4, 0x2a } }
-#define NS_HARDWARE_KEY_HANDLER_CONTRACTID \
- "@mozilla.org/HardwareKeyHandler;1"
-
-#include "mozilla/EventForwards.h" /* For nsEventStatus */
-
-namespace mozilla {
-class WidgetKeyboardEvent;
-}
-
-using mozilla::WidgetKeyboardEvent;
-
-class nsINode;
-%}
-
-/**
- * This interface is used to be registered to the nsIHardwareKeyHandler through
- * |nsIHardwareKeyHandler.registerListener|.
- */
-[scriptable, function, uuid(cd5aeee3-b4b9-459d-85e7-c0671c7a8a2e)]
-interface nsIHardwareKeyEventListener : nsISupports
-{
- /**
- * This method will be invoked by nsIHardwareKeyHandler to forward the native
- * keyboard event to the active input method
- */
- bool onHardwareKey(in nsIDOMKeyEvent aEvent);
-};
-
-/**
- * This interface has two main roles. One is to send a hardware keyboard event
- * to the active input method app and the other is to receive its reply result.
- * If a keyboard event is triggered from a hardware keyboard when an editor has
- * focus, the event target should be the editor. However, the text input
- * processor algorithm is implemented in an input method app and it should
- * handle the event earlier than the real event target to do the mapping such
- * as character conversion according to the language setting or the type of a
- * hardware keyboard.
- */
-[scriptable, builtinclass, uuid(25b34270-caad-4d18-a910-860351690639)]
-interface nsIHardwareKeyHandler : nsISupports
-{
- /**
- * Flags used to set the defaultPrevented's result. The default result
- * from input-method-app should be set to NO_DEFAULT_PREVENTED.
- * (It means the forwarded event isn't consumed by input-method-app.)
- * If the input-method-app consumes the forwarded event,
- * then the result should be set by DEFAULT_PREVENTED* before reply.
- */
- const unsigned short NO_DEFAULT_PREVENTED = 0x0000;
- const unsigned short DEFAULT_PREVENTED = 0x0001;
- const unsigned short DEFAULT_PREVENTED_BY_CHROME = 0x0002;
- const unsigned short DEFAULT_PREVENTED_BY_CONTENT = 0x0004;
-
- /**
- * Registers a listener in input-method-app to receive
- * the forwarded hardware keyboard events
- *
- * @param aListener Listener object to be notified for receiving
- * the keyboard event fired from hardware
- * @note A listener object must implement
- * nsIHardwareKeyEventListener and
- * nsSupportsWeakReference
- * @see nsIHardwareKeyEventListener
- * @see nsSupportsWeakReference
- */
- void registerListener(in nsIHardwareKeyEventListener aListener);
-
- /**
- * Unregisters the current listener from input-method-app
- */
- void unregisterListener();
-
- /**
- * Notifies nsIHardwareKeyHandler that input-method-app is active.
- */
- void onInputMethodAppConnected();
-
- /**
- * Notifies nsIHardwareKeyHandler that input-method-app is disabled.
- */
- void onInputMethodAppDisconnected();
-
- /**
- * Input-method-app will pass the processing result that the forwarded
- * event is handled or not through this method, and the nsIHardwareKeyHandler
- * can use this to receive the reply of |forwardKeyToInputMethodApp|
- * from the active input method.
- *
- * The result should contain the original event type and the info whether
- * the default is prevented, also, it is prevented by chrome or content.
- *
- * @param aEventType The type of an original event.
- * @param aDefaultPrevented State that |evt.preventDefault|
- * is called by content, chrome or not.
- */
- void onHandledByInputMethodApp(in DOMString aType,
- in unsigned short aDefaultPrevented);
-
- /**
- * Sends the native keyboard events triggered from hardware to the
- * active input method before dispatching to its event target.
- * This method only forwards keydown and keyup events.
- * If the event isn't allowed to be forwarded, we should continue the
- * normal event processing. For those forwarded keydown and keyup events
- * We will pause the further event processing to wait for the completion
- * of the event handling in the active input method app.
- * Once |onHandledByInputMethodApp| is called by the input method app,
- * the pending event processing can be resumed according to its reply.
- * On the other hand, the keypress will never be sent to the input-method-app.
- * Depending on whether the keydown's reply arrives before the keypress event
- * comes, the keypress event will be handled directly or pushed into
- * the event queue to wait for its heading keydown's reply.
- *
- * This implementation will call |nsIHardwareKeyEventListener.onHardwareKey|,
- * which is registered through |nsIHardwareKeyEventListener.registerListener|,
- * to forward the events.
- *
- * Returns true, if the event is handled in this module.
- * Returns false, otherwise.
- *
- * If it returns false, we should continue the normal event processing.
- */
- %{C++
- virtual bool ForwardKeyToInputMethodApp(nsINode* aTarget,
- WidgetKeyboardEvent* aEvent,
- nsEventStatus* aEventStatus) = 0;
- %}
-};
diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp
index 75678ca96..fc288e2c5 100644
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -11,7 +11,6 @@
#include "ContentChild.h"
#include "BlobChild.h"
-#include "CrashReporterChild.h"
#include "GeckoProfiler.h"
#include "TabChild.h"
#include "HandlerServiceChild.h"
@@ -32,7 +31,6 @@
#include "mozilla/dom/ExternalHelperAppChild.h"
#include "mozilla/dom/FlyWebPublishedServerIPC.h"
#include "mozilla/dom/GetFilesHelper.h"
-#include "mozilla/dom/PCrashReporterChild.h"
#include "mozilla/dom/ProcessGlobal.h"
#include "mozilla/dom/PushNotifier.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
@@ -65,21 +63,6 @@
#include "imgLoader.h"
#include "GMPServiceChild.h"
-#if defined(MOZ_CONTENT_SANDBOX)
-#if defined(XP_WIN)
-#define TARGET_SANDBOX_EXPORTS
-#include "mozilla/sandboxTarget.h"
-#elif defined(XP_LINUX)
-#include "mozilla/Sandbox.h"
-#include "mozilla/SandboxInfo.h"
-
-// Remove this include with Bug 1104619
-#include "CubebUtils.h"
-#elif defined(XP_MACOSX)
-#include "mozilla/Sandbox.h"
-#endif
-#endif
-
#include "mozilla/Unused.h"
#include "mozInlineSpellChecker.h"
@@ -152,12 +135,6 @@
#include "APKOpen.h"
#endif
-#if defined(MOZ_WIDGET_GONK)
-#include "nsVolume.h"
-#include "nsVolumeService.h"
-#include "SpeakerManagerService.h"
-#endif
-
#ifdef XP_WIN
#include <process.h>
#define getpid _getpid
@@ -211,9 +188,6 @@ using namespace mozilla::net;
using namespace mozilla::jsipc;
using namespace mozilla::psm;
using namespace mozilla::widget;
-#if defined(MOZ_WIDGET_GONK)
-using namespace mozilla::system;
-#endif
using namespace mozilla::widget;
namespace mozilla {
@@ -559,8 +533,7 @@ ContentChild::Init(MessageLoop* aIOLoop,
NS_ASSERTION(!sSingleton, "only one ContentChild per child");
// Once we start sending IPC messages, we need the thread manager to be
- // initialized so we can deal with the responses. Do that here before we
- // try to construct the crash reporter.
+ // initialized so we can deal with the responses. Do that here.
nsresult rv = nsThreadManager::get().Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
@@ -600,15 +573,7 @@ ContentChild::Init(MessageLoop* aIOLoop,
void
ContentChild::InitProcessAttributes()
{
-#ifdef MOZ_WIDGET_GONK
- if (mIsForApp && !mIsForBrowser) {
- SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
- } else {
- SetProcessName(NS_LITERAL_STRING("Browser"), false);
- }
-#else
SetProcessName(NS_LITERAL_STRING("Web Content"), true);
-#endif
}
void
@@ -1250,192 +1215,11 @@ ContentChild::AllocPProcessHangMonitorChild(Transport* aTransport,
return CreateHangMonitorChild(aTransport, aOtherProcess);
}
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-
-#include <stdlib.h>
-
-static bool
-GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath, nsCString &aAppDir)
-{
- nsAutoCString appPath;
- nsAutoCString appBinaryPath(
- (CommandLine::ForCurrentProcess()->argv()[0]).c_str());
-
- nsAutoCString::const_iterator start, end;
- appBinaryPath.BeginReading(start);
- appBinaryPath.EndReading(end);
- if (RFindInReadable(NS_LITERAL_CSTRING(".app/Contents/MacOS/"), start, end)) {
- end = start;
- ++end; ++end; ++end; ++end;
- appBinaryPath.BeginReading(start);
- appPath.Assign(Substring(start, end));
- } else {
- return false;
- }
-
- nsCOMPtr<nsIFile> app, appBinary;
- nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appPath),
- true, getter_AddRefs(app));
- if (NS_FAILED(rv)) {
- return false;
- }
- rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appBinaryPath),
- true, getter_AddRefs(appBinary));
- if (NS_FAILED(rv)) {
- return false;
- }
-
- nsCOMPtr<nsIFile> appDir;
- nsCOMPtr<nsIProperties> dirSvc =
- do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
- if (!dirSvc) {
- return false;
- }
- rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
- NS_GET_IID(nsIFile), getter_AddRefs(appDir));
- if (NS_FAILED(rv)) {
- return false;
- }
- bool exists;
- rv = appDir->Exists(&exists);
- if (NS_FAILED(rv) || !exists) {
- return false;
- }
-
- bool isLink;
- app->IsSymlink(&isLink);
- if (isLink) {
- app->GetNativeTarget(aAppPath);
- } else {
- app->GetNativePath(aAppPath);
- }
- appBinary->IsSymlink(&isLink);
- if (isLink) {
- appBinary->GetNativeTarget(aAppBinaryPath);
- } else {
- appBinary->GetNativePath(aAppBinaryPath);
- }
- appDir->IsSymlink(&isLink);
- if (isLink) {
- appDir->GetNativeTarget(aAppDir);
- } else {
- appDir->GetNativePath(aAppDir);
- }
-
- return true;
-}
-
-static bool
-StartMacOSContentSandbox()
-{
- int sandboxLevel = Preferences::GetInt("security.sandbox.content.level");
- if (sandboxLevel < 1) {
- return false;
- }
-
- nsAutoCString appPath, appBinaryPath, appDir;
- if (!GetAppPaths(appPath, appBinaryPath, appDir)) {
- MOZ_CRASH("Error resolving child process path");
- }
-
- // During sandboxed content process startup, before reaching
- // this point, NS_OS_TEMP_DIR is modified to refer to a sandbox-
- // writable temporary directory
- nsCOMPtr<nsIFile> tempDir;
- nsresult rv = nsDirectoryService::gService->Get(NS_OS_TEMP_DIR,
- NS_GET_IID(nsIFile), getter_AddRefs(tempDir));
- if (NS_FAILED(rv)) {
- MOZ_CRASH("Failed to get NS_OS_TEMP_DIR");
- }
-
- nsAutoCString tempDirPath;
- tempDir->Normalize();
- rv = tempDir->GetNativePath(tempDirPath);
- if (NS_FAILED(rv)) {
- MOZ_CRASH("Failed to get NS_OS_TEMP_DIR path");
- }
-
- nsCOMPtr<nsIFile> profileDir;
- ContentChild::GetSingleton()->GetProfileDir(getter_AddRefs(profileDir));
- nsCString profileDirPath;
- if (profileDir) {
- rv = profileDir->GetNativePath(profileDirPath);
- if (NS_FAILED(rv) || profileDirPath.IsEmpty()) {
- MOZ_CRASH("Failed to get profile path");
- }
- }
-
- MacSandboxInfo info;
- info.type = MacSandboxType_Content;
- info.level = info.level = sandboxLevel;
- info.appPath.assign(appPath.get());
- info.appBinaryPath.assign(appBinaryPath.get());
- info.appDir.assign(appDir.get());
- info.appTempDir.assign(tempDirPath.get());
-
- if (profileDir) {
- info.hasSandboxedProfile = true;
- info.profileDir.assign(profileDirPath.get());
- } else {
- info.hasSandboxedProfile = false;
- }
-
- std::string err;
- if (!mozilla::StartMacSandbox(info, err)) {
- NS_WARNING(err.c_str());
- MOZ_CRASH("sandbox_init() failed");
- }
-
- return true;
-}
-#endif
-
bool
ContentChild::RecvSetProcessSandbox(const MaybeFileDesc& aBroker)
{
// We may want to move the sandbox initialization somewhere else
// at some point; see bug 880808.
-#if defined(MOZ_CONTENT_SANDBOX)
- bool sandboxEnabled = true;
-#if defined(XP_LINUX)
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
- // For B2G >= KitKat, sandboxing is mandatory; this has already
- // been enforced by ContentParent::StartUp().
- MOZ_ASSERT(SandboxInfo::Get().CanSandboxContent());
-#else
- // Otherwise, sandboxing is best-effort.
- if (!SandboxInfo::Get().CanSandboxContent()) {
- sandboxEnabled = false;
- } else {
- // This triggers the initialization of cubeb, which needs to happen
- // before seccomp is enabled (Bug 1259508). It also increases the startup
- // time of the content process, because cubeb is usually initialized
- // when it is actually needed. This call here is no longer required
- // once Bug 1104619 (remoting audio) is resolved.
- Unused << CubebUtils::GetCubebContext();
- }
-
-#endif /* MOZ_WIDGET_GONK && ANDROID_VERSION >= 19 */
- if (sandboxEnabled) {
- int brokerFd = -1;
- if (aBroker.type() == MaybeFileDesc::TFileDescriptor) {
- auto fd = aBroker.get_FileDescriptor().ClonePlatformHandle();
- brokerFd = fd.release();
- // brokerFd < 0 means to allow direct filesystem access, so
- // make absolutely sure that doesn't happen if the parent
- // didn't intend it.
- MOZ_RELEASE_ASSERT(brokerFd >= 0);
- }
- sandboxEnabled = SetContentProcessSandbox(brokerFd);
- }
-#elif defined(XP_WIN)
- mozilla::SandboxTarget::Instance()->StartSandbox();
-#elif defined(XP_MACOSX)
- sandboxEnabled = StartMacOSContentSandbox();
-#endif
-
-#endif /* MOZ_CONTENT_SANDBOX */
-
return true;
}
@@ -1453,15 +1237,6 @@ ContentChild::RecvNotifyLayerAllocated(const dom::TabId& aTabId, const uint64_t&
bool
ContentChild::RecvSpeakerManagerNotify()
{
-#ifdef MOZ_WIDGET_GONK
- // Only notify the process which has the SpeakerManager instance.
- RefPtr<SpeakerManagerService> service =
- SpeakerManagerService::GetSpeakerManagerService();
- if (service) {
- service->Notify();
- }
- return true;
-#endif
return false;
}
@@ -1719,19 +1494,6 @@ ContentChild::RecvNotifyEmptyHTTPCache()
return true;
}
-PCrashReporterChild*
-ContentChild::AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
- const uint32_t& processType)
-{
- return nullptr;
-}
-
-bool
-ContentChild::DeallocPCrashReporterChild(PCrashReporterChild* crashreporter)
-{
- delete crashreporter;
- return true;
-}
PHalChild*
ContentChild::AllocPHalChild()
@@ -2480,12 +2242,6 @@ ContentChild::RecvLastPrivateDocShellDestroyed()
bool
ContentChild::RecvVolumes(nsTArray<VolumeInfo>&& aVolumes)
{
-#ifdef MOZ_WIDGET_GONK
- RefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
- if (vs) {
- vs->RecvVolumesFromParent(aVolumes);
- }
-#endif
return true;
}
@@ -2502,17 +2258,6 @@ ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
const bool& aIsRemovable,
const bool& aIsHotSwappable)
{
-#ifdef MOZ_WIDGET_GONK
- RefPtr<nsVolume> volume = new nsVolume(aFsName, aVolumeName, aState,
- aMountGeneration, aIsMediaPresent,
- aIsSharing, aIsFormatting, aIsFake,
- aIsUnmounting, aIsRemovable, aIsHotSwappable);
-
- RefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
- if (vs) {
- vs->UpdateVolume(volume);
- }
-#else
// Remove warnings about unused arguments
Unused << aFsName;
Unused << aVolumeName;
@@ -2525,22 +2270,15 @@ ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
Unused << aIsUnmounting;
Unused << aIsRemovable;
Unused << aIsHotSwappable;
-#endif
+
return true;
}
bool
ContentChild::RecvVolumeRemoved(const nsString& aFsName)
{
-#ifdef MOZ_WIDGET_GONK
- RefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
- if (vs) {
- vs->RemoveVolumeByName(aFsName);
- }
-#else
// Remove warnings about unused arguments
Unused << aFsName;
-#endif
return true;
}
@@ -2666,61 +2404,6 @@ ContentChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor)
}
bool
-ContentChild::RecvStartProfiler(const ProfilerInitParams& params)
-{
- nsTArray<const char*> featureArray;
- for (size_t i = 0; i < params.features().Length(); ++i) {
- featureArray.AppendElement(params.features()[i].get());
- }
-
- nsTArray<const char*> threadNameFilterArray;
- for (size_t i = 0; i < params.threadFilters().Length(); ++i) {
- threadNameFilterArray.AppendElement(params.threadFilters()[i].get());
- }
-
- profiler_start(params.entries(), params.interval(),
- featureArray.Elements(), featureArray.Length(),
- threadNameFilterArray.Elements(),
- threadNameFilterArray.Length());
-
- return true;
-}
-
-bool
-ContentChild::RecvStopProfiler()
-{
- profiler_stop();
- return true;
-}
-
-bool
-ContentChild::RecvPauseProfiler(const bool& aPause)
-{
- if (aPause) {
- profiler_pause();
- } else {
- profiler_resume();
- }
-
- return true;
-}
-
-bool
-ContentChild::RecvGatherProfile()
-{
- nsCString profileCString;
- UniquePtr<char[]> profile = profiler_get_profile();
- if (profile) {
- profileCString = nsCString(profile.get(), strlen(profile.get()));
- } else {
- profileCString = EmptyCString();
- }
-
- Unused << SendProfile(profileCString);
- return true;
-}
-
-bool
ContentChild::RecvLoadPluginResult(const uint32_t& aPluginId,
const bool& aResult)
{
@@ -2874,15 +2557,6 @@ ContentChild::RecvShutdown()
GetIPCChannel()->SetAbortOnError(false);
-#ifdef MOZ_ENABLE_PROFILER_SPS
- if (profiler_is_active()) {
- // We're shutting down while we were profiling. Send the
- // profile up to the parent so that we don't lose this
- // information.
- Unused << RecvGatherProfile();
- }
-#endif
-
// Start a timer that will insure we quickly exit after a reasonable
// period of time. Prevents shutdown hangs after our connection to the
// parent closes.
diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h
index cb718aff9..ba590b58e 100644
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -21,10 +21,6 @@
#include "nsWeakPtr.h"
#include "nsIWindowProvider.h"
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-#include "nsIFile.h"
-#endif
-
struct ChromePackage;
class nsIObserver;
struct SubstitutionMapping;
@@ -118,19 +114,6 @@ public:
void GetProcessName(nsACString& aName) const;
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
- void GetProfileDir(nsIFile** aProfileDir) const
- {
- *aProfileDir = mProfileDir;
- NS_IF_ADDREF(*aProfileDir);
- }
-
- void SetProfileDir(nsIFile* aProfileDir)
- {
- mProfileDir = aProfileDir;
- }
-#endif
-
bool IsAlive() const;
bool IsShuttingDown() const;
@@ -203,13 +186,6 @@ public:
virtual bool DeallocPBlobChild(PBlobChild* aActor) override;
- virtual PCrashReporterChild*
- AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
- const uint32_t& processType) override;
-
- virtual bool
- DeallocPCrashReporterChild(PCrashReporterChild*) override;
-
virtual PHalChild* AllocPHalChild() override;
virtual bool DeallocPHalChild(PHalChild*) override;
@@ -478,14 +454,6 @@ public:
virtual bool RecvUpdateWindow(const uintptr_t& aChildId) override;
- virtual bool RecvStartProfiler(const ProfilerInitParams& params) override;
-
- virtual bool RecvPauseProfiler(const bool& aPause) override;
-
- virtual bool RecvStopProfiler() override;
-
- virtual bool RecvGatherProfile() override;
-
virtual bool RecvDomainSetChanged(const uint32_t& aSetType,
const uint32_t& aChangeType,
const OptionalURIParams& aDomain) override;
@@ -679,10 +647,6 @@ private:
nsCOMPtr<nsIDomainPolicy> mPolicy;
nsCOMPtr<nsITimer> mForceKillTimer;
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
- nsCOMPtr<nsIFile> mProfileDir;
-#endif
-
// Hashtable to keep track of the pending GetFilesHelper objects.
// This GetFilesHelperChild objects are removed when RecvGetFilesResponse is
// received.
diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
index 73621df22..0a07147bf 100644
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -16,18 +16,12 @@
# include <sys/resource.h>
#endif
-#ifdef MOZ_WIDGET_GONK
-#include <sys/types.h>
-#include <sys/wait.h>
-#endif
-
#include "chrome/common/process_watcher.h"
#include "mozilla/a11y/PDocAccessible.h"
#include "AppProcessChecker.h"
#include "AudioChannelService.h"
#include "BlobParent.h"
-#include "CrashReporterParent.h"
#include "GMPServiceParent.h"
#include "HandlerServiceParent.h"
#include "IHistory.h"
@@ -87,9 +81,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/ProcessHangMonitor.h"
#include "mozilla/ProcessHangMonitorIPC.h"
-#ifdef MOZ_ENABLE_PROFILER_SPS
-#include "mozilla/ProfileGatherer.h"
-#endif
#include "mozilla/ScopeExit.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
@@ -210,14 +201,6 @@
# include "AndroidBridge.h"
#endif
-#ifdef MOZ_WIDGET_GONK
-#include "nsIVolume.h"
-#include "nsVolumeService.h"
-#include "nsIVolumeService.h"
-#include "SpeakerManagerService.h"
-using namespace mozilla::system;
-#endif
-
#ifdef MOZ_WIDGET_GTK
#include <gdk/gdk.h>
#endif
@@ -230,21 +213,10 @@ using namespace mozilla::system;
#include "mozilla/dom/SpeechSynthesisParent.h"
#endif
-#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX)
-#include "mozilla/SandboxInfo.h"
-#include "mozilla/SandboxBroker.h"
-#include "mozilla/SandboxBrokerPolicyFactory.h"
-#endif
-
#ifdef MOZ_TOOLKIT_SEARCH
#include "nsIBrowserSearchService.h"
#endif
-#ifdef MOZ_ENABLE_PROFILER_SPS
-#include "nsIProfiler.h"
-#include "nsIProfileSaveEvent.h"
-#endif
-
#ifdef XP_WIN
#include "mozilla/widget/AudioSession.h"
#endif
@@ -265,9 +237,6 @@ extern const char* kForceEnableE10sPref;
using base::ChildPrivileges;
using base::KillProcess;
-#ifdef MOZ_ENABLE_PROFILER_SPS
-using mozilla::ProfileGatherer;
-#endif
using namespace mozilla::dom::power;
using namespace mozilla::media;
@@ -503,9 +472,6 @@ nsTArray<ContentParent*>* ContentParent::sNonAppContentParents;
nsTArray<ContentParent*>* ContentParent::sLargeAllocationContentParents;
nsTArray<ContentParent*>* ContentParent::sPrivateContent;
StaticAutoPtr<LinkedList<ContentParent> > ContentParent::sContentParents;
-#if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
-UniquePtr<SandboxBrokerPolicyFactory> ContentParent::sSandboxBrokerPolicyFactory;
-#endif
// This is true when subprocess launching is enabled. This is the
// case between StartUp() and ShutDown() or JoinAllSubprocesses().
@@ -535,22 +501,9 @@ static const char* sObserverTopics[] = {
"child-mmu-request",
"last-pb-context-exited",
"file-watcher-update",
-#ifdef MOZ_WIDGET_GONK
- NS_VOLUME_STATE_CHANGED,
- NS_VOLUME_REMOVED,
- "phone-state-changed",
-#endif
#ifdef ACCESSIBILITY
"a11y-init-or-shutdown",
#endif
-#ifdef MOZ_ENABLE_PROFILER_SPS
- "profiler-started",
- "profiler-stopped",
- "profiler-paused",
- "profiler-resumed",
- "profiler-subprocess-gather",
- "profiler-subprocess",
-#endif
"cacheservice:empty-cache",
};
@@ -637,18 +590,6 @@ ContentParent::StartUp()
return;
}
-#if defined(MOZ_CONTENT_SANDBOX) && defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
- // Require sandboxing on B2G >= KitKat. This condition must stay
- // in sync with ContentChild::RecvSetProcessSandbox.
- if (!SandboxInfo::Get().CanSandboxContent()) {
- // MOZ_CRASH strings are only for debug builds; make sure the
- // message is clear on non-debug builds as well:
- printf_stderr("Sandboxing support is required on this platform. "
- "Recompile kernel with CONFIG_SECCOMP_FILTER=y\n");
- MOZ_CRASH("Sandboxing support is required on this platform.");
- }
-#endif
-
// Note: This reporter measures all ContentParents.
RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
@@ -662,10 +603,6 @@ ContentParent::StartUp()
PreallocatedProcessManager::AllocateAfterDelay();
sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
-
-#if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
- sSandboxBrokerPolicyFactory = MakeUnique<SandboxBrokerPolicyFactory>();
-#endif
}
/*static*/ void
@@ -674,10 +611,6 @@ ContentParent::ShutDown()
// No-op for now. We rely on normal process shutdown and
// ClearOnShutdown() to clean up our state.
sCanLaunchSubprocesses = false;
-
-#if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
- sSandboxBrokerPolicyFactory = nullptr;
-#endif
}
/*static*/ void
@@ -1353,26 +1286,6 @@ ContentParent::Init()
}
#endif
-#ifdef MOZ_ENABLE_PROFILER_SPS
- nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
- bool profilerActive = false;
- DebugOnly<nsresult> rv = profiler->IsActive(&profilerActive);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-
- if (profilerActive) {
- nsCOMPtr<nsIProfilerStartParams> currentProfilerParams;
- rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-
- nsCOMPtr<nsISupports> gatherer;
- rv = profiler->GetProfileGatherer(getter_AddRefs(gatherer));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
-
- StartProfiler(currentProfilerParams);
- }
-#endif
-
RefPtr<GeckoMediaPluginServiceParent> gmps(GeckoMediaPluginServiceParent::GetSingleton());
gmps->UpdateContentProcessGMPCapabilities();
}
@@ -1384,14 +1297,6 @@ ContentParent::ForwardKnownInfo()
if (!mMetamorphosed) {
return;
}
-#ifdef MOZ_WIDGET_GONK
- InfallibleTArray<VolumeInfo> volumeInfo;
- RefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
- if (vs) {
- vs->GetVolumesForIPC(&volumeInfo);
- Unused << SendVolumes(volumeInfo);
- }
-#endif /* MOZ_WIDGET_GONK */
}
namespace {
@@ -1439,23 +1344,6 @@ bool
ContentParent::SetPriorityAndCheckIsAlive(ProcessPriority aPriority)
{
ProcessPriorityManager::SetProcessPriority(this, aPriority);
-
- // Now that we've set this process's priority, check whether the process is
- // still alive. Hopefully we've set the priority to FOREGROUND*, so the
- // process won't unexpectedly crash after this point!
- //
- // Bug 943174: use waitid() with WNOWAIT so that, if the process
- // did exit, we won't consume its zombie and confuse the
- // GeckoChildProcessHost dtor.
-#ifdef MOZ_WIDGET_GONK
- siginfo_t info;
- info.si_pid = 0;
- if (waitid(P_PID, Pid(), &info, WNOWAIT | WNOHANG | WEXITED) == 0
- && info.si_pid != 0) {
- return false;
- }
-#endif
-
return true;
}
@@ -1824,12 +1712,6 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
mConsoleService = nullptr;
-#ifdef MOZ_ENABLE_PROFILER_SPS
- if (mGatherer && !mProfile.IsEmpty()) {
- mGatherer->OOPExitProfile(mProfile);
- }
-#endif
-
if (obs) {
RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
@@ -2106,7 +1988,7 @@ ContentParent::ContentParent(mozIApplication* aApp,
// PID along with the warning.
nsDebugImpl::SetMultiprocessMode("Parent");
-#if defined(XP_WIN) && !defined(MOZ_B2G)
+#if defined(XP_WIN)
// Request Windows message deferral behavior on our side of the PContent
// channel. Generally only applies to the situation where we get caught in
// a deadlock with the plugin process when sending CPOWs.
@@ -2244,37 +2126,6 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
}
}
-#ifdef MOZ_CONTENT_SANDBOX
- bool shouldSandbox = true;
- MaybeFileDesc brokerFd = void_t();
-#ifdef XP_LINUX
- // XXX: Checking the pref here makes it possible to enable/disable sandboxing
- // during an active session. Currently the pref is only used for testing
- // purpose. If the decision is made to permanently rely on the pref, this
- // should be changed so that it is required to restart firefox for the change
- // of value to take effect.
- shouldSandbox = (Preferences::GetInt("security.sandbox.content.level") > 0) &&
- !PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX");
-
- if (shouldSandbox) {
- MOZ_ASSERT(!mSandboxBroker);
- UniquePtr<SandboxBroker::Policy> policy =
- sSandboxBrokerPolicyFactory->GetContentPolicy(Pid());
- if (policy) {
- brokerFd = FileDescriptor();
- mSandboxBroker = SandboxBroker::Create(Move(policy), Pid(), brokerFd);
- if (!mSandboxBroker) {
- KillHard("SandboxBroker::Create failed");
- return;
- }
- MOZ_ASSERT(static_cast<const FileDescriptor&>(brokerFd).IsValid());
- }
- }
-#endif
- if (shouldSandbox && !SendSetProcessSandbox(brokerFd)) {
- KillHard("SandboxInitFailed");
- }
-#endif
#if defined(XP_WIN)
// Send the info needed to join the browser process's audio session.
nsID id;
@@ -2660,27 +2511,6 @@ ContentParent::Observe(nsISupports* aSubject,
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
}
-#ifdef MOZ_ENABLE_PROFILER_SPS
- // Need to do this before the mIsAlive check to avoid missing profiles.
- if (!strcmp(aTopic, "profiler-subprocess-gather")) {
- if (mGatherer) {
- mGatherer->WillGatherOOPProfile();
- if (mIsAlive && mSubprocess) {
- Unused << SendGatherProfile();
- }
- }
- }
- else if (!strcmp(aTopic, "profiler-subprocess")) {
- nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
- if (pse) {
- if (!mProfile.IsEmpty()) {
- pse->AddSubProfile(mProfile.get());
- mProfile.Truncate();
- }
- }
- }
-#endif
-
if (!mIsAlive || !mSubprocess)
return NS_OK;
@@ -2746,50 +2576,6 @@ ContentParent::Observe(nsISupports* aSubject,
else if (!strcmp(aTopic, "last-pb-context-exited")) {
Unused << SendLastPrivateDocShellDestroyed();
}
-#ifdef MOZ_WIDGET_GONK
- else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
- nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
- if (!vol) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- nsString volName;
- nsString mountPoint;
- int32_t state;
- int32_t mountGeneration;
- bool isMediaPresent;
- bool isSharing;
- bool isFormatting;
- bool isFake;
- bool isUnmounting;
- bool isRemovable;
- bool isHotSwappable;
-
- vol->GetName(volName);
- vol->GetMountPoint(mountPoint);
- vol->GetState(&state);
- vol->GetMountGeneration(&mountGeneration);
- vol->GetIsMediaPresent(&isMediaPresent);
- vol->GetIsSharing(&isSharing);
- vol->GetIsFormatting(&isFormatting);
- vol->GetIsFake(&isFake);
- vol->GetIsUnmounting(&isUnmounting);
- vol->GetIsRemovable(&isRemovable);
- vol->GetIsHotSwappable(&isHotSwappable);
-
- Unused << SendFileSystemUpdate(volName, mountPoint, state,
- mountGeneration, isMediaPresent,
- isSharing, isFormatting, isFake,
- isUnmounting, isRemovable, isHotSwappable);
- } else if (!strcmp(aTopic, "phone-state-changed")) {
- nsString state(aData);
- Unused << SendNotifyPhoneStateChange(state);
- }
- else if(!strcmp(aTopic, NS_VOLUME_REMOVED)) {
- nsString volName(aData);
- Unused << SendVolumeRemoved(volName);
- }
-#endif
#ifdef ACCESSIBILITY
else if (aData && !strcmp(aTopic, "a11y-init-or-shutdown")) {
if (*aData == '1') {
@@ -2811,22 +2597,6 @@ ContentParent::Observe(nsISupports* aSubject,
}
}
#endif
-#ifdef MOZ_ENABLE_PROFILER_SPS
- else if (!strcmp(aTopic, "profiler-started")) {
- nsCOMPtr<nsIProfilerStartParams> params(do_QueryInterface(aSubject));
- StartProfiler(params);
- }
- else if (!strcmp(aTopic, "profiler-stopped")) {
- mGatherer = nullptr;
- Unused << SendStopProfiler();
- }
- else if (!strcmp(aTopic, "profiler-paused")) {
- Unused << SendPauseProfiler(true);
- }
- else if (!strcmp(aTopic, "profiler-resumed")) {
- Unused << SendPauseProfiler(false);
- }
-#endif
else if (!strcmp(aTopic, "cacheservice:empty-cache")) {
Unused << SendNotifyEmptyHTTPCache();
}
@@ -3100,29 +2870,6 @@ ContentParent::FriendlyName(nsAString& aName, bool aAnonymize)
}
}
-PCrashReporterParent*
-ContentParent::AllocPCrashReporterParent(const NativeThreadId& tid,
- const uint32_t& processType)
-{
- return nullptr;
-}
-
-bool
-ContentParent::RecvPCrashReporterConstructor(PCrashReporterParent* actor,
- const NativeThreadId& tid,
- const uint32_t& processType)
-{
- static_cast<CrashReporterParent*>(actor)->SetChildData(tid, processType);
- return true;
-}
-
-bool
-ContentParent::DeallocPCrashReporterParent(PCrashReporterParent* crashreporter)
-{
- delete crashreporter;
- return true;
-}
-
hal_sandbox::PHalParent*
ContentParent::AllocPHalParent()
{
@@ -3224,11 +2971,15 @@ PPrintingParent*
ContentParent::AllocPPrintingParent()
{
#ifdef NS_PRINTING
- MOZ_ASSERT(!mPrintingParent,
- "Only one PrintingParent should be created per process.");
+ MOZ_RELEASE_ASSERT(!mPrintingParent,
+ "Only one PrintingParent should be created per process.");
// Create the printing singleton for this process.
mPrintingParent = new PrintingParent();
+
+ // Take another reference for IPDL code.
+ mPrintingParent.get()->AddRef();
+
return mPrintingParent.get();
#else
MOZ_ASSERT_UNREACHABLE("Should never be created if no printing.");
@@ -3240,8 +2991,11 @@ bool
ContentParent::DeallocPPrintingParent(PPrintingParent* printing)
{
#ifdef NS_PRINTING
- MOZ_ASSERT(mPrintingParent == printing,
- "Only one PrintingParent should have been created per process.");
+ MOZ_RELEASE_ASSERT(mPrintingParent == printing,
+ "Only one PrintingParent should have been created per process.");
+
+ // Release reference taken for IPDL code.
+ static_cast<PrintingParent*>(printing)->Release();
mPrintingParent = nullptr;
#else
@@ -3451,29 +3205,12 @@ ContentParent::RecvPSpeechSynthesisConstructor(PSpeechSynthesisParent* aActor)
bool
ContentParent::RecvSpeakerManagerGetSpeakerStatus(bool* aValue)
{
-#ifdef MOZ_WIDGET_GONK
- *aValue = false;
- RefPtr<SpeakerManagerService> service =
- SpeakerManagerService::GetOrCreateSpeakerManagerService();
- MOZ_ASSERT(service);
-
- *aValue = service->GetSpeakerStatus();
- return true;
-#endif
return false;
}
bool
ContentParent::RecvSpeakerManagerForceSpeaker(const bool& aEnable)
{
-#ifdef MOZ_WIDGET_GONK
- RefPtr<SpeakerManagerService> service =
- SpeakerManagerService::GetOrCreateSpeakerManagerService();
- MOZ_ASSERT(service);
- service->ForceSpeaker(aEnable, mChildID);
-
- return true;
-#endif
return false;
}
@@ -3636,13 +3373,13 @@ ContentParent::RecvIsSecureURI(const uint32_t& type,
}
bool
-ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive, const bool& aHSTSPriming)
+ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive)
{
nsCOMPtr<nsIURI> ourURI = DeserializeURI(aURI);
if (!ourURI) {
return false;
}
- nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive, aHSTSPriming);
+ nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive);
return true;
}
@@ -4029,49 +3766,22 @@ bool
ContentParent::RecvCreateFakeVolume(const nsString& fsName,
const nsString& mountPoint)
{
-#ifdef MOZ_WIDGET_GONK
- nsresult rv;
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
- if (vs) {
- vs->CreateFakeVolume(fsName, mountPoint);
- }
- return true;
-#else
- NS_WARNING("ContentParent::RecvCreateFakeVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
+ NS_WARNING("ContentParent::RecvCreateFakeVolume shouldn't be called");
return false;
-#endif
}
bool
ContentParent::RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState)
{
-#ifdef MOZ_WIDGET_GONK
- nsresult rv;
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
- if (vs) {
- vs->SetFakeVolumeState(fsName, fsState);
- }
- return true;
-#else
- NS_WARNING("ContentParent::RecvSetFakeVolumeState shouldn't be called when MOZ_WIDGET_GONK is not defined");
+ NS_WARNING("ContentParent::RecvSetFakeVolumeState shouldn't be called");
return false;
-#endif
}
bool
ContentParent::RecvRemoveFakeVolume(const nsString& fsName)
{
-#ifdef MOZ_WIDGET_GONK
- nsresult rv;
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
- if (vs) {
- vs->RemoveFakeVolume(fsName);
- }
- return true;
-#else
- NS_WARNING("ContentParent::RecvRemoveFakeVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
+ NS_WARNING("ContentParent::RecvRemoveFakeVolume shouldn't be called");
return false;
-#endif
}
bool
@@ -4765,19 +4475,6 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
}
bool
-ContentParent::RecvProfile(const nsCString& aProfile)
-{
-#ifdef MOZ_ENABLE_PROFILER_SPS
- if (NS_WARN_IF(!mGatherer)) {
- return true;
- }
- mProfile = aProfile;
- mGatherer->GatheredOOPProfile();
-#endif
- return true;
-}
-
-bool
ContentParent::RecvGetGraphicsDeviceInitData(ContentDeviceData* aOut)
{
gfxPlatform::GetPlatform()->BuildContentDeviceData(aOut);
@@ -4863,34 +4560,6 @@ ContentParent::RecvNotifyBenchmarkResult(const nsString& aCodecName,
return true;
}
-void
-ContentParent::StartProfiler(nsIProfilerStartParams* aParams)
-{
-#ifdef MOZ_ENABLE_PROFILER_SPS
- if (NS_WARN_IF(!aParams)) {
- return;
- }
-
- ProfilerInitParams ipcParams;
-
- ipcParams.enabled() = true;
- aParams->GetEntries(&ipcParams.entries());
- aParams->GetInterval(&ipcParams.interval());
- ipcParams.features() = aParams->GetFeatures();
- ipcParams.threadFilters() = aParams->GetThreadFilterNames();
-
- Unused << SendStartProfiler(ipcParams);
-
- nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
- if (NS_WARN_IF(!profiler)) {
- return;
- }
- nsCOMPtr<nsISupports> gatherer;
- profiler->GetProfileGatherer(getter_AddRefs(gatherer));
- mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
-#endif
-}
-
bool
ContentParent::RecvNotifyPushObservers(const nsCString& aScope,
const IPC::Principal& aPrincipal,
@@ -5052,6 +4721,14 @@ ContentParent::RecvGetFilesRequest(const nsID& aUUID,
{
MOZ_ASSERT(!mGetFilesPendingRequests.GetWeak(aUUID));
+ if (!mozilla::Preferences::GetBool("dom.filesystem.pathcheck.disabled", false)) {
+ RefPtr<FileSystemSecurity> fss = FileSystemSecurity::Get();
+ if (NS_WARN_IF(!fss ||
+ !fss->ContentProcessHasAccessTo(ChildID(), aDirectoryPath))) {
+ return false;
+ }
+ }
+
ErrorResult rv;
RefPtr<GetFilesHelper> helper =
GetFilesHelperParent::Create(aUUID, aDirectoryPath, aRecursiveFlag, this,
diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h
index a3750de1a..abcea0b65 100644
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -42,14 +42,6 @@ class nsIWidget;
namespace mozilla {
class PRemoteSpellcheckEngineParent;
-#ifdef MOZ_ENABLE_PROFILER_SPS
-class ProfileGatherer;
-#endif
-
-#if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
-class SandboxBroker;
-class SandboxBrokerPolicyFactory;
-#endif
namespace embedding {
class PrintingParent;
@@ -377,15 +369,6 @@ public:
virtual void OnChannelError() override;
- virtual PCrashReporterParent*
- AllocPCrashReporterParent(const NativeThreadId& tid,
- const uint32_t& processType) override;
-
- virtual bool
- RecvPCrashReporterConstructor(PCrashReporterParent* actor,
- const NativeThreadId& tid,
- const uint32_t& processType) override;
-
virtual PNeckoParent* AllocPNeckoParent() override;
virtual bool RecvPNeckoConstructor(PNeckoParent* aActor) override
@@ -740,9 +723,6 @@ private:
RecvPBlobConstructor(PBlobParent* aActor,
const BlobConstructorParams& params) override;
- virtual bool
- DeallocPCrashReporterParent(PCrashReporterParent* crashreporter) override;
-
virtual bool RecvNSSU2FTokenIsCompatibleVersion(const nsString& aVersion,
bool* aIsCompatible) override;
@@ -762,8 +742,7 @@ private:
const uint32_t& aFlags, bool* aIsSecureURI) override;
virtual bool RecvAccumulateMixedContentHSTS(const URIParams& aURI,
- const bool& aActive,
- const bool& aHSTSPriming) override;
+ const bool& aActive) override;
virtual bool DeallocPHalParent(PHalParent*) override;
@@ -1035,12 +1014,8 @@ private:
virtual bool RecvUpdateDropEffect(const uint32_t& aDragAction,
const uint32_t& aDropEffect) override;
- virtual bool RecvProfile(const nsCString& aProfile) override;
-
virtual bool RecvGetGraphicsDeviceInitData(ContentDeviceData* aOut) override;
- void StartProfiler(nsIProfilerStartParams* aParams);
-
virtual bool RecvGetAndroidSystemInfo(AndroidSystemInfo* aInfo) override;
virtual bool RecvNotifyBenchmarkResult(const nsString& aCodecName,
@@ -1145,19 +1120,10 @@ private:
PProcessHangMonitorParent* mHangMonitorActor;
-#ifdef MOZ_ENABLE_PROFILER_SPS
- RefPtr<mozilla::ProfileGatherer> mGatherer;
-#endif
nsCString mProfile;
UniquePtr<gfx::DriverCrashGuard> mDriverCrashGuard;
-#if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
- mozilla::UniquePtr<SandboxBroker> mSandboxBroker;
- static mozilla::UniquePtr<SandboxBrokerPolicyFactory>
- sSandboxBrokerPolicyFactory;
-#endif
-
#ifdef NS_PRINTING
RefPtr<embedding::PrintingParent> mPrintingParent;
#endif
diff --git a/dom/ipc/ContentProcess.cpp b/dom/ipc/ContentProcess.cpp
index 2413d8808..986617f55 100644
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -8,122 +8,17 @@
#include "ContentProcess.h"
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-#include <stdlib.h>
-#endif
-
-#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
-#include "mozilla/Preferences.h"
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsDirectoryService.h"
-#include "nsDirectoryServiceDefs.h"
-#endif
-
using mozilla::ipc::IOThreadChild;
namespace mozilla {
namespace dom {
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
-static bool
-IsSandboxTempDirRequired()
-{
- // On Windows, a sandbox-writable temp directory is only used
- // when sandbox pref level >= 1.
- return Preferences::GetInt("security.sandbox.content.level") >= 1;
-}
-
-static void
-SetTmpEnvironmentVariable(nsIFile* aValue)
-{
- // Save the TMP environment variable so that is is picked up by GetTempPath().
- // Note that we specifically write to the TMP variable, as that is the first
- // variable that is checked by GetTempPath() to determine its output.
- nsAutoString fullTmpPath;
- nsresult rv = aValue->GetPath(fullTmpPath);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
- Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", fullTmpPath.get()));
- // We also set TEMP in case there is naughty third-party code that is
- // referencing the environment variable directly.
- Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", fullTmpPath.get()));
-}
-#endif
-
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-static bool
-IsSandboxTempDirRequired()
-{
- // On OSX, use the sandbox-writable temp when the pref level >= 1.
- return (Preferences::GetInt("security.sandbox.content.level") >= 1);
-}
-
-static void
-SetTmpEnvironmentVariable(nsIFile* aValue)
-{
- nsAutoCString fullTmpPath;
- nsresult rv = aValue->GetNativePath(fullTmpPath);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
- Unused << NS_WARN_IF(setenv("TMPDIR", fullTmpPath.get(), 1) != 0);
-}
-#endif
-
-#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
-static void
-SetUpSandboxEnvironment()
-{
- MOZ_ASSERT(nsDirectoryService::gService,
- "SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
-
- if (!IsSandboxTempDirRequired()) {
- return;
- }
-
- nsCOMPtr<nsIFile> sandboxedContentTemp;
- nsresult rv =
- nsDirectoryService::gService->Get(NS_APP_CONTENT_PROCESS_TEMP_DIR,
- NS_GET_IID(nsIFile),
- getter_AddRefs(sandboxedContentTemp));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- // Change the gecko defined temp directory to our sandbox-writable one.
- // Undefine returns a failure if the property is not already set.
- Unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
- rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, sandboxedContentTemp);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- SetTmpEnvironmentVariable(sandboxedContentTemp);
-}
-#endif
-
void
ContentProcess::SetAppDir(const nsACString& aPath)
{
mXREEmbed.SetAppDir(aPath);
}
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-void
-ContentProcess::SetProfile(const nsACString& aProfile)
-{
- bool flag;
- nsresult rv =
- XRE_GetFileFromPath(aProfile.BeginReading(), getter_AddRefs(mProfileDir));
- if (NS_FAILED(rv) ||
- NS_FAILED(mProfileDir->Exists(&flag)) || !flag) {
- NS_WARNING("Invalid profile directory passed to content process.");
- mProfileDir = nullptr;
- }
-}
-#endif
-
bool
ContentProcess::Init()
{
@@ -134,14 +29,6 @@ ContentProcess::Init()
mContent.InitXPCOM();
mContent.InitGraphicsDeviceData();
-#if (defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
- mContent.SetProfileDir(mProfileDir);
-#endif
-
-#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
- SetUpSandboxEnvironment();
-#endif
-
return true;
}
diff --git a/dom/ipc/ContentProcess.h b/dom/ipc/ContentProcess.h
index bf9968f8c..3950368bd 100644
--- a/dom/ipc/ContentProcess.h
+++ b/dom/ipc/ContentProcess.h
@@ -39,18 +39,10 @@ public:
void SetAppDir(const nsACString& aPath);
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
- void SetProfile(const nsACString& aProfile);
-#endif
-
private:
ContentChild mContent;
mozilla::ipc::ScopedXREEmbed mXREEmbed;
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
- nsCOMPtr<nsIFile> mProfileDir;
-#endif
-
#if defined(XP_WIN)
// This object initializes and configures COM.
mozilla::mscom::MainThreadRuntime mCOMRuntime;
diff --git a/dom/ipc/CrashReporterChild.cpp b/dom/ipc/CrashReporterChild.cpp
deleted file mode 100644
index 8174452e7..000000000
--- a/dom/ipc/CrashReporterChild.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "mozilla/plugins/PluginModuleChild.h"
-#include "ContentChild.h"
-#include "CrashReporterChild.h"
-#include "nsXULAppAPI.h"
-
-using mozilla::plugins::PluginModuleChild;
-
-namespace mozilla {
-namespace dom {
-
-/*static*/
-PCrashReporterChild*
-CrashReporterChild::GetCrashReporter()
-{
- const ManagedContainer<PCrashReporterChild>* reporters = nullptr;
- switch (XRE_GetProcessType()) {
- case GeckoProcessType_Content: {
- ContentChild* child = ContentChild::GetSingleton();
- reporters = &child->ManagedPCrashReporterChild();
- break;
- }
- case GeckoProcessType_Plugin: {
- PluginModuleChild* child = PluginModuleChild::GetChrome();
- reporters = &child->ManagedPCrashReporterChild();
- break;
- }
- default:
- break;
- }
- if (!reporters) {
- return nullptr;
- }
- return LoneManagedOrNullAsserts(*reporters);
-}
-
-} // namespace dom
-} // namespace mozilla
diff --git a/dom/ipc/CrashReporterChild.h b/dom/ipc/CrashReporterChild.h
deleted file mode 100644
index 96355ca11..000000000
--- a/dom/ipc/CrashReporterChild.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_CrashReporterChild_h
-#define mozilla_dom_CrashReporterChild_h
-
-#include "mozilla/dom/PCrashReporterChild.h"
-
-namespace mozilla {
-namespace dom {
-
-class CrashReporterChild :
- public PCrashReporterChild
-{
-public:
- CrashReporterChild() {
- MOZ_COUNT_CTOR(CrashReporterChild);
- }
- ~CrashReporterChild() {
- MOZ_COUNT_DTOR(CrashReporterChild);
- }
-
- static PCrashReporterChild* GetCrashReporter();
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_CrashReporterChild_h
diff --git a/dom/ipc/CrashReporterParent.cpp b/dom/ipc/CrashReporterParent.cpp
deleted file mode 100644
index 677b29670..000000000
--- a/dom/ipc/CrashReporterParent.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "CrashReporterParent.h"
-#include "mozilla/Sprintf.h"
-#include "mozilla/dom/ContentParent.h"
-#include "mozilla/ipc/CrashReporterHost.h"
-#include "nsAutoPtr.h"
-#include "nsXULAppAPI.h"
-#include <time.h>
-
-#include "mozilla/Telemetry.h"
-
-namespace mozilla {
-namespace dom {
-
-using namespace mozilla::ipc;
-
-void
-CrashReporterParent::AnnotateCrashReport(const nsCString& key,
- const nsCString& data)
-{
-}
-
-void
-CrashReporterParent::ActorDestroy(ActorDestroyReason aWhy)
-{
- // Implement me! Bug 1005155
-}
-
-bool
-CrashReporterParent::RecvAppendAppNotes(const nsCString& data)
-{
- mAppNotes.Append(data);
- return true;
-}
-
-CrashReporterParent::CrashReporterParent()
- :
- mStartTime(::time(nullptr))
- , mInitialized(false)
-{
- MOZ_COUNT_CTOR(CrashReporterParent);
-}
-
-CrashReporterParent::~CrashReporterParent()
-{
- MOZ_COUNT_DTOR(CrashReporterParent);
-}
-
-void
-CrashReporterParent::SetChildData(const NativeThreadId& tid,
- const uint32_t& processType)
-{
- mInitialized = true;
- mMainThread = tid;
- mProcessType = GeckoProcessType(processType);
-}
-
-} // namespace dom
-} // namespace mozilla
diff --git a/dom/ipc/CrashReporterParent.h b/dom/ipc/CrashReporterParent.h
deleted file mode 100644
index 71896c5c1..000000000
--- a/dom/ipc/CrashReporterParent.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_CrashReporterParent_h
-#define mozilla_dom_CrashReporterParent_h
-
-#include "mozilla/dom/PCrashReporterParent.h"
-#include "mozilla/dom/TabMessageUtils.h"
-#include "nsIFile.h"
-
-namespace mozilla {
-namespace dom {
-
-class CrashReporterParent : public PCrashReporterParent
-{
-public:
- CrashReporterParent();
- virtual ~CrashReporterParent();
-
- /*
- * Initialize this reporter with data from the child process.
- */
- void
- SetChildData(const NativeThreadId& id, const uint32_t& processType);
-
- /*
- * Returns the ID of the child minidump.
- * GeneratePairedMinidump or GenerateCrashReport must be called first.
- */
- const nsString& ChildDumpID() const {
- return mChildDumpID;
- }
-
- /*
- * Add an annotation to our internally tracked list of annotations.
- * Callers must apply these notes using GenerateChildData otherwise
- * the notes will get dropped.
- */
- void
- AnnotateCrashReport(const nsCString& aKey, const nsCString& aData);
-
- protected:
- virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-
- virtual bool RecvAnnotateCrashReport(const nsCString& aKey,
- const nsCString& aData) override
- {
- AnnotateCrashReport(aKey, aData);
- return true;
- }
-
- virtual bool RecvAppendAppNotes(const nsCString& aData) override;
-
- nsCString mAppNotes;
- nsString mChildDumpID;
- // stores the child main thread id
- NativeThreadId mMainThread;
- time_t mStartTime;
- // stores the child process type
- GeckoProcessType mProcessType;
- bool mInitialized;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_CrashReporterParent_h
diff --git a/dom/ipc/DatePickerParent.cpp b/dom/ipc/DatePickerParent.cpp
deleted file mode 100644
index 509944ddd..000000000
--- a/dom/ipc/DatePickerParent.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "DatePickerParent.h"
-#include "nsComponentManagerUtils.h"
-#include "nsIDocument.h"
-#include "nsIDOMWindow.h"
-#include "mozilla/Unused.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/TabParent.h"
-
-using mozilla::Unused;
-using namespace mozilla::dom;
-
-NS_IMPL_ISUPPORTS(DatePickerParent::DatePickerShownCallback,
- nsIDatePickerShownCallback);
-
-NS_IMETHODIMP
-DatePickerParent::DatePickerShownCallback::Cancel()
-{
- if (mDatePickerParent) {
- Unused << mDatePickerParent->SendCancel();
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DatePickerParent::DatePickerShownCallback::Done(const nsAString& aDate)
-{
- if (mDatePickerParent) {
- Unused << mDatePickerParent->Send__delete__(mDatePickerParent,
- nsString(aDate));
- }
- return NS_OK;
-}
-
-void
-DatePickerParent::DatePickerShownCallback::Destroy()
-{
- mDatePickerParent = nullptr;
-}
-
-bool
-DatePickerParent::CreateDatePicker()
-{
- mPicker = do_CreateInstance("@mozilla.org/datepicker;1");
- if (!mPicker) {
- return false;
- }
-
- Element* ownerElement = TabParent::GetFrom(Manager())->GetOwnerElement();
- if (!ownerElement) {
- return false;
- }
-
- nsCOMPtr<mozIDOMWindowProxy> window = do_QueryInterface(ownerElement->OwnerDoc()->GetWindow());
- if (!window) {
- return false;
- }
-
- return NS_SUCCEEDED(mPicker->Init(window, mTitle, mInitialDate));
-}
-
-bool
-DatePickerParent::RecvOpen()
-{
- if (!CreateDatePicker()) {
- Unused << Send__delete__(this, mInitialDate);
- return true;
- }
-
- mCallback = new DatePickerShownCallback(this);
-
- mPicker->Open(mCallback);
- return true;
-};
-
-void
-DatePickerParent::ActorDestroy(ActorDestroyReason aWhy)
-{
- if (mCallback) {
- mCallback->Destroy();
- }
-}
diff --git a/dom/ipc/DatePickerParent.h b/dom/ipc/DatePickerParent.h
deleted file mode 100644
index 73b66f96c..000000000
--- a/dom/ipc/DatePickerParent.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_DatePickerParent_h
-#define mozilla_dom_DatePickerParent_h
-
-#include "mozilla/dom/PDatePickerParent.h"
-#include "nsIDatePicker.h"
-
-namespace mozilla {
-namespace dom {
-
-class DatePickerParent : public PDatePickerParent
-{
- public:
- DatePickerParent(const nsString& aTitle,
- const nsString& aInitialDate)
- : mTitle(aTitle)
- , mInitialDate(aInitialDate)
- {}
-
- virtual bool RecvOpen() override;
- virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-
- class DatePickerShownCallback final
- : public nsIDatePickerShownCallback
- {
- public:
- explicit DatePickerShownCallback(DatePickerParent* aDatePickerParnet)
- : mDatePickerParent(aDatePickerParnet)
- {}
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDATEPICKERSHOWNCALLBACK
-
- void Destroy();
-
- private:
- ~DatePickerShownCallback() {}
- DatePickerParent* mDatePickerParent;
- };
-
- private:
- virtual ~DatePickerParent() {}
-
- bool CreateDatePicker();
-
- RefPtr<DatePickerShownCallback> mCallback;
- nsCOMPtr<nsIDatePicker> mPicker;
-
- nsString mTitle;
- nsString mInitialDate;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_DatePickerParent_h
diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl
index 9dfccbc5c..f09e484ee 100644
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -9,7 +9,6 @@ include protocol PBlob;
include protocol PColorPicker;
include protocol PContent;
include protocol PContentBridge;
-include protocol PDatePicker;
include protocol PDocAccessible;
include protocol PFilePicker;
include protocol PIndexedDBPermissionRequest;
@@ -116,7 +115,6 @@ nested(upto inside_cpow) sync protocol PBrowser
manager PContent or PContentBridge;
manages PColorPicker;
- manages PDatePicker;
manages PDocAccessible;
manages PFilePicker;
manages PIndexedDBPermissionRequest;
@@ -441,12 +439,6 @@ parent:
*/
async PColorPicker(nsString title, nsString initialColor);
- /**
- * Create an asynchronous date picker on the parent side,
- * but don't open it yet.
- */
- async PDatePicker(nsString title, nsString initialDate);
-
async PFilePicker(nsString aTitle, int16_t aMode);
/**
diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl
index d436c19fe..c01ad59c1 100644
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -11,7 +11,6 @@ include protocol PCompositorBridge;
include protocol PContentBridge;
include protocol PContentPermissionRequest;
include protocol PCycleCollectWithLogs;
-include protocol PCrashReporter;
include protocol PPSMContentDownloader;
include protocol PExternalHelperApp;
include protocol PHandlerService;
@@ -243,7 +242,6 @@ nested(upto inside_cpow) sync protocol PContent
manages PBlob;
manages PBrowser;
manages PContentPermissionRequest;
- manages PCrashReporter;
manages PCycleCollectWithLogs;
manages PPSMContentDownloader;
manages PExternalHelperApp;
@@ -466,15 +464,6 @@ child:
*/
async LoadPluginResult(uint32_t aPluginId, bool aResult);
- /**
- * Control the Gecko Profiler in the child process.
- */
- async StartProfiler(ProfilerInitParams params);
- async StopProfiler();
- async PauseProfiler(bool aPause);
-
- async GatherProfile();
-
async InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action);
async EndDragSession(bool aDoneDrag, bool aUserCancelled,
@@ -625,8 +614,6 @@ parent:
async PRemoteSpellcheckEngine();
- sync PCrashReporter(NativeThreadId tid, uint32_t processType);
-
/**
* Is this token compatible with the provided version?
*
@@ -674,7 +661,7 @@ parent:
sync IsSecureURI(uint32_t type, URIParams uri, uint32_t flags)
returns (bool isSecureURI);
- async AccumulateMixedContentHSTS(URIParams uri, bool active, bool hasHSTSPriming);
+ async AccumulateMixedContentHSTS(URIParams uri, bool active);
sync GetLookAndFeelCache()
returns (LookAndFeelInt[] lookAndFeelIntCache);
@@ -962,8 +949,6 @@ parent:
async PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal,
TabId tabId);
- async Profile(nsCString aProfile);
-
/**
* Request graphics initialization information from the parent.
*/
diff --git a/dom/ipc/PCrashReporter.ipdl b/dom/ipc/PCrashReporter.ipdl
deleted file mode 100644
index 8f965f2ee..000000000
--- a/dom/ipc/PCrashReporter.ipdl
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set sw=4 ts=8 et tw=80 :
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-include protocol PContent;
-include protocol PPluginModule;
-include protocol PGMP;
-
-namespace mozilla {
-namespace dom {
-
-struct Mapping {
- nsCString library_name;
- nsCString file_id;
- uintptr_t start_address;
- size_t mapping_length;
- size_t file_offset;
-};
-
-async protocol PCrashReporter {
- manager PContent or PPluginModule or PGMP;
-parent:
- async AnnotateCrashReport(nsCString key, nsCString data);
- async AppendAppNotes(nsCString data);
- async __delete__();
-};
-
-}
-}
diff --git a/dom/ipc/PDatePicker.ipdl b/dom/ipc/PDatePicker.ipdl
deleted file mode 100644
index 90a2654bb..000000000
--- a/dom/ipc/PDatePicker.ipdl
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
-/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-include protocol PBrowser;
-
-namespace mozilla {
-namespace dom {
-
-protocol PDatePicker
-{
- manager PBrowser;
-
-parent:
- async Open();
-
-child:
- async Cancel();
-
- async __delete__(nsString color);
-};
-
-} // namespace dom
-} // namespace mozilla
diff --git a/dom/ipc/StructuredCloneData.cpp b/dom/ipc/StructuredCloneData.cpp
index 98f56904f..2c1fff2ac 100644
--- a/dom/ipc/StructuredCloneData.cpp
+++ b/dom/ipc/StructuredCloneData.cpp
@@ -88,7 +88,7 @@ StructuredCloneData::Write(JSContext* aCx,
return;
}
- JSStructuredCloneData data;
+ JSStructuredCloneData data(mBuffer->scope());
mBuffer->abandon();
mBuffer->steal(&data);
mBuffer = nullptr;
@@ -107,7 +107,7 @@ StructuredCloneData::ReadIPCParams(const IPC::Message* aMsg,
PickleIterator* aIter)
{
MOZ_ASSERT(!mInitialized);
- JSStructuredCloneData data;
+ JSStructuredCloneData data(JS::StructuredCloneScope::DifferentProcess);
if (!ReadParam(aMsg, aIter, &data)) {
return false;
}
diff --git a/dom/ipc/StructuredCloneData.h b/dom/ipc/StructuredCloneData.h
index 9e427e938..64cfd1935 100644
--- a/dom/ipc/StructuredCloneData.h
+++ b/dom/ipc/StructuredCloneData.h
@@ -31,8 +31,8 @@ public:
static already_AddRefed<SharedJSAllocatedData>
CreateFromExternalData(const char* aData, size_t aDataLength)
{
- JSStructuredCloneData buf;
- buf.WriteBytes(aData, aDataLength);
+ JSStructuredCloneData buf(JS::StructuredCloneScope::DifferentProcess);
+ buf.AppendBytes(aData, aDataLength);
RefPtr<SharedJSAllocatedData> sharedData =
new SharedJSAllocatedData(Move(buf));
return sharedData.forget();
@@ -41,12 +41,8 @@ public:
static already_AddRefed<SharedJSAllocatedData>
CreateFromExternalData(const JSStructuredCloneData& aData)
{
- JSStructuredCloneData buf;
- auto iter = aData.Iter();
- while (!iter.Done()) {
- buf.WriteBytes(iter.Data(), iter.RemainingInSegment());
- iter.Advance(aData, iter.RemainingInSegment());
- }
+ JSStructuredCloneData buf(aData.scope());
+ buf.Append(aData);
RefPtr<SharedJSAllocatedData> sharedData =
new SharedJSAllocatedData(Move(buf));
return sharedData.forget();
@@ -70,6 +66,7 @@ public:
: StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
StructuredCloneHolder::TransferringSupported,
StructuredCloneHolder::StructuredCloneScope::DifferentProcess)
+ , mExternalData(StructuredCloneHolder::StructuredCloneScope::DifferentProcess)
, mInitialized(false)
{}
@@ -113,10 +110,9 @@ public:
bool UseExternalData(const JSStructuredCloneData& aData)
{
- auto iter = aData.Iter();
+ auto iter = aData.Start();
bool success = false;
- mExternalData =
- aData.Borrow<js::SystemAllocPolicy>(iter, aData.Size(), &success);
+ mExternalData = aData.Borrow(iter, aData.Size(), &success);
mInitialized = true;
return success;
}
@@ -133,6 +129,11 @@ public:
return mSharedData ? mSharedData->Data() : mExternalData;
}
+ void InitScope(JS::StructuredCloneScope aScope)
+ {
+ Data().initScope(aScope);
+ }
+
size_t DataLength() const
{
return mSharedData ? mSharedData->DataLength() : mExternalData.Size();
diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp
index c8a0c6e3f..705799c54 100644
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -96,7 +96,6 @@
#include "LayersLogging.h"
#include "nsDOMClassInfoID.h"
#include "nsColorPickerProxy.h"
-#include "nsDatePickerProxy.h"
#include "nsContentPermissionHelper.h"
#include "nsPresShell.h"
#include "nsIAppsService.h"
@@ -2013,21 +2012,6 @@ TabChild::DeallocPColorPickerChild(PColorPickerChild* aColorPicker)
return true;
}
-PDatePickerChild*
-TabChild::AllocPDatePickerChild(const nsString&, const nsString&)
-{
- NS_RUNTIMEABORT("unused");
- return nullptr;
-}
-
-bool
-TabChild::DeallocPDatePickerChild(PDatePickerChild* aDatePicker)
-{
- nsDatePickerProxy* picker = static_cast<nsDatePickerProxy*>(aDatePicker);
- NS_RELEASE(picker);
- return true;
-}
-
PFilePickerChild*
TabChild::AllocPFilePickerChild(const nsString&, const int16_t&)
{
diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h
index 2232ffeaf..d9988a596 100644
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -451,10 +451,6 @@ public:
virtual bool DeallocPColorPickerChild(PColorPickerChild* aActor) override;
- virtual PDatePickerChild*
- AllocPDatePickerChild(const nsString& title, const nsString& initialDate) override;
- virtual bool DeallocPDatePickerChild(PDatePickerChild* actor) override;
-
virtual PFilePickerChild*
AllocPFilePickerChild(const nsString& aTitle, const int16_t& aMode) override;
diff --git a/dom/ipc/TabContext.cpp b/dom/ipc/TabContext.cpp
index b36dbc5eb..362bce3a4 100644
--- a/dom/ipc/TabContext.cpp
+++ b/dom/ipc/TabContext.cpp
@@ -358,12 +358,7 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
case IPCTabContext::TUnsafeIPCTabContext: {
// XXXcatalinb: This used *only* by ServiceWorkerClients::OpenWindow.
// It is meant as a temporary solution until service workers can
- // provide a TabChild equivalent. Don't allow this on b2g since
- // it might be used to escalate privileges.
-#ifdef MOZ_B2G
- mInvalidReason = "ServiceWorkerClients::OpenWindow is not supported.";
- return;
-#endif
+ // provide a TabChild equivalent.
if (!Preferences::GetBool("dom.serviceWorkers.enabled", false)) {
mInvalidReason = "ServiceWorkers should be enabled.";
return;
diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp
index 8e98de3ce..0f190708f 100644
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -80,7 +80,6 @@
#include "PermissionMessageUtils.h"
#include "StructuredCloneData.h"
#include "ColorPickerParent.h"
-#include "DatePickerParent.h"
#include "FilePickerParent.h"
#include "TabChild.h"
#include "LoadContext.h"
@@ -2424,20 +2423,6 @@ TabParent::DeallocPColorPickerParent(PColorPickerParent* actor)
return true;
}
-PDatePickerParent*
-TabParent::AllocPDatePickerParent(const nsString& aTitle,
- const nsString& aInitialDate)
-{
- return new DatePickerParent(aTitle, aInitialDate);
-}
-
-bool
-TabParent::DeallocPDatePickerParent(PDatePickerParent* actor)
-{
- delete actor;
- return true;
-}
-
PRenderFrameParent*
TabParent::AllocPRenderFrameParent()
{
diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h
index 09bb999f3..3624ce320 100644
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -347,10 +347,6 @@ public:
virtual bool
DeallocPColorPickerParent(PColorPickerParent* aColorPicker) override;
- virtual PDatePickerParent*
- AllocPDatePickerParent(const nsString& aTitle, const nsString& aInitialDate) override;
- virtual bool DeallocPDatePickerParent(PDatePickerParent* aDatePicker) override;
-
virtual PDocAccessibleParent*
AllocPDocAccessibleParent(PDocAccessibleParent*, const uint64_t&,
const uint32_t&, const IAccessibleHolder&) override;
diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build
index ff3880bc2..5629ab2c6 100644
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -26,8 +26,6 @@ EXPORTS.mozilla.dom += [
'ContentProcess.h',
'ContentProcessManager.h',
'CPOWManagerGetter.h',
- 'CrashReporterChild.h',
- 'CrashReporterParent.h',
'FilePickerParent.h',
'nsIContentChild.h',
'nsIContentParent.h',
@@ -54,8 +52,6 @@ UNIFIED_SOURCES += [
'ContentParent.cpp',
'ContentProcess.cpp',
'ContentProcessManager.cpp',
- 'CrashReporterParent.cpp',
- 'DatePickerParent.cpp',
'FilePickerParent.cpp',
'nsIContentChild.cpp',
'nsIContentParent.cpp',
@@ -71,13 +67,10 @@ UNIFIED_SOURCES += [
]
# Blob.cpp cannot be compiled in unified mode because it triggers a fatal gcc warning.
-# CrashReporterChild.cpp cannot be compiled in unified mode because of name clashes
-# in OS X headers.
# ContentChild.cpp cannot be compiled in unified mode on linux due to Time conflict
SOURCES += [
'Blob.cpp',
'ContentChild.cpp',
- 'CrashReporterChild.cpp',
'ProcessHangMonitor.cpp',
]
@@ -93,9 +86,7 @@ IPDL_SOURCES += [
'PContentBridge.ipdl',
'PContentPermission.ipdlh',
'PContentPermissionRequest.ipdl',
- 'PCrashReporter.ipdl',
'PCycleCollectWithLogs.ipdl',
- 'PDatePicker.ipdl',
'PFilePicker.ipdl',
'PMemoryReportRequest.ipdl',
'PPluginWidget.ipdl',
@@ -114,11 +105,6 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin':
'mozsandbox',
]
-if CONFIG['MOZ_CONTENT_SANDBOX'] and CONFIG['OS_ARCH'] == 'Linux':
- USE_LIBS += [
- 'mozsandbox',
- ]
-
LOCAL_INCLUDES += [
'/caps',
'/chrome',
@@ -139,7 +125,6 @@ LOCAL_INCLUDES += [
'/layout/base',
'/media/webrtc',
'/netwerk/base',
- '/toolkit/crashreporter',
'/toolkit/xre',
'/uriloader/exthandler',
'/widget',
@@ -147,12 +132,6 @@ LOCAL_INCLUDES += [
'/xpcom/threads',
]
-if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
- LOCAL_INCLUDES += [
- '/security/sandbox/chromium',
- '/security/sandbox/chromium-shim',
- ]
-
if CONFIG['OS_ARCH'] != 'WINNT':
LOCAL_INCLUDES += [
'/modules/libjar',
@@ -160,7 +139,7 @@ if CONFIG['OS_ARCH'] != 'WINNT':
DEFINES['BIN_SUFFIX'] = '"%s"' % CONFIG['BIN_SUFFIX']
-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gonk'):
+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2'):
DEFINES['MOZ_ENABLE_FREETYPE'] = True
if CONFIG['MOZ_TOOLKIT_SEARCH']:
diff --git a/dom/ipc/tests/test_cpow_cookies.html b/dom/ipc/tests/test_cpow_cookies.html
index 1e55d3878..d8f87cced 100644
--- a/dom/ipc/tests/test_cpow_cookies.html
+++ b/dom/ipc/tests/test_cpow_cookies.html
@@ -81,7 +81,8 @@
["dom.ipc.browser_frames.oop_by_default", true],
["dom.mozBrowserFramesEnabled", true],
["network.disable.ipc.security", true],
- ["browser.pagethumbnails.capturing_disabled", true]
+ ["browser.pagethumbnails.capturing_disabled", true],
+ ["security.data_uri.block_toplevel_data_uri_navigations", false],
]
}, runTests);
});
diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp
index cdb63f890..90171db10 100644
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -36,7 +36,6 @@
#include "nsIContentViewer.h"
#include "nsIXPConnect.h"
#include "nsContentUtils.h"
-#include "nsNullPrincipal.h"
#include "nsJSUtils.h"
#include "nsThreadUtils.h"
#include "nsIScriptChannel.h"
@@ -336,7 +335,7 @@ public:
NS_FORWARD_SAFE_NSIPROPERTYBAG(mPropertyBag)
NS_FORWARD_SAFE_NSIPROPERTYBAG2(mPropertyBag)
- nsresult Init(nsIURI *aURI);
+ nsresult Init(nsIURI *aURI, nsILoadInfo* aLoadInfo);
// Actually evaluate the script.
void EvaluateScript();
@@ -354,17 +353,16 @@ protected:
nsCOMPtr<nsIChannel> mStreamChannel;
nsCOMPtr<nsIPropertyBag2> mPropertyBag;
nsCOMPtr<nsIStreamListener> mListener; // Our final listener
- nsCOMPtr<nsISupports> mContext; // The context passed to AsyncOpen
nsCOMPtr<nsPIDOMWindowInner> mOriginalInnerWindow; // The inner window our load
// started against.
- // If we blocked onload on a document in AsyncOpen, this is the document we
+ // If we blocked onload on a document in AsyncOpen2, this is the document we
// did it on.
nsCOMPtr<nsIDocument> mDocumentOnloadBlockedOn;
nsresult mStatus; // Our status
nsLoadFlags mLoadFlags;
- nsLoadFlags mActualLoadFlags; // See AsyncOpen
+ nsLoadFlags mActualLoadFlags; // See AsyncOpen2
RefPtr<nsJSThunk> mIOThunk;
PopupControlState mPopupState;
@@ -404,7 +402,7 @@ nsresult nsJSChannel::StopAll()
return rv;
}
-nsresult nsJSChannel::Init(nsIURI *aURI)
+nsresult nsJSChannel::Init(nsIURI* aURI, nsILoadInfo* aLoadInfo)
{
RefPtr<nsJSURI> jsURI;
nsresult rv = aURI->QueryInterface(kJSURICID,
@@ -418,21 +416,13 @@ nsresult nsJSChannel::Init(nsIURI *aURI)
// Remember, until AsyncOpen is called, the script will not be evaluated
// and the underlying Input Stream will not be created...
nsCOMPtr<nsIChannel> channel;
-
- nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();
-
- // If the resultant script evaluation actually does return a value, we
- // treat it as html.
- // The following channel is never openend, so it does not matter what
- // securityFlags we pass; let's follow the principle of least privilege.
- rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
- aURI,
- mIOThunk,
- nullPrincipal,
- nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
- nsIContentPolicy::TYPE_OTHER,
- NS_LITERAL_CSTRING("text/html"));
- if (NS_FAILED(rv)) return rv;
+ rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
+ aURI,
+ mIOThunk,
+ NS_LITERAL_CSTRING("text/html"),
+ EmptyCString(),
+ aLoadInfo);
+ NS_ENSURE_SUCCESS(rv, rv);
rv = mIOThunk->Init(aURI);
if (NS_SUCCEEDED(rv)) {
@@ -563,6 +553,7 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
"security flags in loadInfo but asyncOpen2() not called");
}
#endif
+ MOZ_RELEASE_ASSERT(!aContext, "please call AsyncOpen2()");
NS_ENSURE_ARG(aListener);
@@ -584,7 +575,6 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
}
mListener = aListener;
- mContext = aContext;
mIsActive = true;
@@ -655,7 +645,7 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
return mStatus;
}
- // We're returning success from asyncOpen(), but we didn't open a
+ // We're returning success from asyncOpen2(), but we didn't open a
// stream channel. We'll have to notify ourselves, but make sure to do
// it asynchronously.
method = &nsJSChannel::NotifyListener;
@@ -772,7 +762,7 @@ nsJSChannel::EvaluateScript()
return;
}
- mStatus = mStreamChannel->AsyncOpen(this, mContext);
+ mStatus = mStreamChannel->AsyncOpen2(this);
if (NS_SUCCEEDED(mStatus)) {
// mStreamChannel will call OnStartRequest and OnStopRequest on
// us, so we'll be sure to call them on our listener.
@@ -800,8 +790,8 @@ nsJSChannel::EvaluateScript()
void
nsJSChannel::NotifyListener()
{
- mListener->OnStartRequest(this, mContext);
- mListener->OnStopRequest(this, mContext, mStatus);
+ mListener->OnStartRequest(this, nullptr);
+ mListener->OnStopRequest(this, nullptr, mStatus);
CleanupStrongRefs();
}
@@ -810,7 +800,6 @@ void
nsJSChannel::CleanupStrongRefs()
{
mListener = nullptr;
- mContext = nullptr;
mOriginalInnerWindow = nullptr;
if (mDocumentOnloadBlockedOn) {
mDocumentOnloadBlockedOn->UnblockOnload(false);
@@ -1240,11 +1229,7 @@ nsJSProtocolHandler::NewChannel2(nsIURI* uri,
return NS_ERROR_OUT_OF_MEMORY;
}
- rv = channel->Init(uri);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // set the loadInfo on the new channel
- rv = channel->SetLoadInfo(aLoadInfo);
+ rv = channel->Init(uri, aLoadInfo);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_SUCCEEDED(rv)) {
diff --git a/dom/locales/en-US/chrome/layout/HtmlForm.properties b/dom/locales/en-US/chrome/layout/HtmlForm.properties
index 621a0b2b3..82274b2bc 100644
--- a/dom/locales/en-US/chrome/layout/HtmlForm.properties
+++ b/dom/locales/en-US/chrome/layout/HtmlForm.properties
@@ -34,7 +34,6 @@ NoDirSelected=No directory selected.
# %S will be a number greater or equal to 2.
XFilesSelected=%S files selected.
ColorPicker=Choose a color
-DatePicker=Choose a date
# LOCALIZATION NOTE (AndNMoreFiles): Semi-colon list of plural forms.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
# This string is shown at the end of the tooltip text for <input type='file'
diff --git a/dom/locales/en-US/chrome/plugins.properties b/dom/locales/en-US/chrome/plugins.properties
index ee8d25c88..fe03be59e 100644
--- a/dom/locales/en-US/chrome/plugins.properties
+++ b/dom/locales/en-US/chrome/plugins.properties
@@ -21,9 +21,6 @@ description_label=Description
suffixes_label=Suffixes
learn_more_label=Learn More
-deprecation_description=Missing something? Some plugins are no longer supported.
-deprecation_learn_more=Learn More.
-
# GMP Plugins
gmp_license_info=License information
gmp_privacy_info=Privacy Information
diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties
index 8b66cc265..c0b80996c 100644
--- a/dom/locales/en-US/chrome/security/security.properties
+++ b/dom/locales/en-US/chrome/security/security.properties
@@ -81,3 +81,6 @@ MimeTypeMismatch=The resource from “%1$S” was blocked due to MIME type misma
XCTOHeaderValueMissing=X-Content-Type-Options header warning: value was “%1$S”; did you mean to send “nosniff”?
BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a disallowed MIME type.
+
+# LOCALIZATION NOTE: Do not translate "data: URI".
+BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
diff --git a/dom/media/AudioConverter.cpp b/dom/media/AudioConverter.cpp
index 77ad46ec6..25b981f43 100644
--- a/dom/media/AudioConverter.cpp
+++ b/dom/media/AudioConverter.cpp
@@ -362,15 +362,13 @@ size_t
AudioConverter::ResampleRecipientFrames(size_t aFrames) const
{
if (!aFrames && mIn.Rate() != mOut.Rate()) {
- // The resampler will be drained, account for frames currently buffered
- // in the resampler.
if (!mResampler) {
return 0;
}
- return speex_resampler_get_output_latency(mResampler);
- } else {
- return (uint64_t)aFrames * mOut.Rate() / mIn.Rate() + 1;
+ // We drain by pushing in get_input_latency() samples of 0
+ aFrames = speex_resampler_get_input_latency(mResampler);
}
+ return (uint64_t)aFrames * mOut.Rate() / mIn.Rate() + 1;
}
size_t
diff --git a/dom/media/AudioStream.cpp b/dom/media/AudioStream.cpp
index 82ae3ee86..54cf7b965 100644
--- a/dom/media/AudioStream.cpp
+++ b/dom/media/AudioStream.cpp
@@ -333,11 +333,7 @@ AudioStream::Init(uint32_t aNumChannels, uint32_t aRate,
params.rate = aRate;
params.channels = mOutChannels;
#if defined(__ANDROID__)
-#if defined(MOZ_B2G)
- params.stream_type = CubebUtils::ConvertChannelToCubebType(aAudioChannel);
-#else
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
-#endif
if (params.stream_type == CUBEB_STREAM_TYPE_MAX) {
return NS_ERROR_INVALID_ARG;
diff --git a/dom/media/Benchmark.cpp b/dom/media/Benchmark.cpp
index 1ba6e561c..fdbedeca5 100644
--- a/dom/media/Benchmark.cpp
+++ b/dom/media/Benchmark.cpp
@@ -22,7 +22,7 @@ namespace mozilla {
// Update this version number to force re-running the benchmark. Such as when
// an improvement to FFVP9 or LIBVPX is deemed worthwhile.
-const uint32_t VP9Benchmark::sBenchmarkVersionID = 2;
+const uint32_t VP9Benchmark::sBenchmarkVersionID = 3;
const char* VP9Benchmark::sBenchmarkFpsPref = "media.benchmark.vp9.fps";
const char* VP9Benchmark::sBenchmarkFpsVersionCheck = "media.benchmark.vp9.versioncheck";
diff --git a/dom/media/CubebUtils.cpp b/dom/media/CubebUtils.cpp
index d1b4bae99..fe94264ee 100644
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -342,33 +342,6 @@ uint32_t MaxNumberOfChannels()
return 0;
}
-#if defined(__ANDROID__) && defined(MOZ_B2G)
-cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel)
-{
- switch(aChannel) {
- case dom::AudioChannel::Normal:
- /* FALLTHROUGH */
- case dom::AudioChannel::Content:
- return CUBEB_STREAM_TYPE_MUSIC;
- case dom::AudioChannel::Notification:
- return CUBEB_STREAM_TYPE_NOTIFICATION;
- case dom::AudioChannel::Alarm:
- return CUBEB_STREAM_TYPE_ALARM;
- case dom::AudioChannel::Telephony:
- return CUBEB_STREAM_TYPE_VOICE_CALL;
- case dom::AudioChannel::Ringer:
- return CUBEB_STREAM_TYPE_RING;
- case dom::AudioChannel::System:
- return CUBEB_STREAM_TYPE_SYSTEM;
- case dom::AudioChannel::Publicnotification:
- return CUBEB_STREAM_TYPE_SYSTEM_ENFORCED;
- default:
- NS_ERROR("The value of AudioChannel is invalid");
- return CUBEB_STREAM_TYPE_MAX;
- }
-}
-#endif
-
void GetCurrentBackend(nsAString& aBackend)
{
cubeb* cubebContext = GetCubebContext();
diff --git a/dom/media/CubebUtils.h b/dom/media/CubebUtils.h
index 171c244b7..fa5fc2294 100644
--- a/dom/media/CubebUtils.h
+++ b/dom/media/CubebUtils.h
@@ -40,9 +40,6 @@ void ReportCubebBackendUsed();
uint32_t GetCubebPlaybackLatencyInMilliseconds();
Maybe<uint32_t> GetCubebMSGLatencyInFrames();
bool CubebLatencyPrefSet();
-#if defined(__ANDROID__) && defined(MOZ_B2G)
-cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel);
-#endif
void GetCurrentBackend(nsAString& aBackend);
} // namespace CubebUtils
diff --git a/dom/media/DOMMediaStream.cpp b/dom/media/DOMMediaStream.cpp
index c1d451035..118d845a3 100755
--- a/dom/media/DOMMediaStream.cpp
+++ b/dom/media/DOMMediaStream.cpp
@@ -1505,20 +1505,6 @@ DOMAudioNodeMediaStream::CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWind
DOMHwMediaStream::DOMHwMediaStream(nsPIDOMWindowInner* aWindow)
: DOMLocalMediaStream(aWindow, nullptr)
{
-#ifdef MOZ_WIDGET_GONK
- if (!mWindow) {
- NS_ERROR("Expected window here.");
- mPrincipalHandle = PRINCIPAL_HANDLE_NONE;
- return;
- }
- nsIDocument* doc = mWindow->GetExtantDoc();
- if (!doc) {
- NS_ERROR("Expected document here.");
- mPrincipalHandle = PRINCIPAL_HANDLE_NONE;
- return;
- }
- mPrincipalHandle = MakePrincipalHandle(doc->NodePrincipal());
-#endif
}
DOMHwMediaStream::~DOMHwMediaStream()
@@ -1545,31 +1531,8 @@ DOMHwMediaStream::Init(MediaStream* stream, OverlayImage* aImage)
{
SourceMediaStream* srcStream = stream->AsSourceStream();
-#ifdef MOZ_WIDGET_GONK
- if (aImage) {
- mOverlayImage = aImage;
- } else {
- Data imageData;
- imageData.mOverlayId = DEFAULT_IMAGE_ID;
- imageData.mSize.width = DEFAULT_IMAGE_WIDTH;
- imageData.mSize.height = DEFAULT_IMAGE_HEIGHT;
-
- mOverlayImage = new OverlayImage();
- mOverlayImage->SetData(imageData);
- }
-#endif
-
if (srcStream) {
VideoSegment segment;
-#ifdef MOZ_WIDGET_GONK
- const StreamTime delta = STREAM_TIME_MAX; // Because MediaStreamGraph will run out frames in non-autoplay mode,
- // we must give it bigger frame length to cover this situation.
-
- RefPtr<Image> image = static_cast<Image*>(mOverlayImage.get());
- mozilla::gfx::IntSize size = image->GetSize();
-
- segment.AppendFrame(image.forget(), delta, size, mPrincipalHandle);
-#endif
srcStream->AddTrack(TRACK_VIDEO_PRIMARY, 0, new VideoSegment());
srcStream->AppendToTrack(TRACK_VIDEO_PRIMARY, &segment);
srcStream->AdvanceKnownTracksTime(STREAM_TIME_MAX);
@@ -1579,30 +1542,13 @@ DOMHwMediaStream::Init(MediaStream* stream, OverlayImage* aImage)
int32_t
DOMHwMediaStream::RequestOverlayId()
{
-#ifdef MOZ_WIDGET_GONK
- return mOverlayImage->GetOverlayId();
-#else
+ /*** STUB ***/
return -1;
-#endif
}
void
DOMHwMediaStream::SetImageSize(uint32_t width, uint32_t height)
{
-#ifdef MOZ_WIDGET_GONK
- if (mOverlayImage->GetSidebandStream().IsValid()) {
- OverlayImage::SidebandStreamData imgData;
- imgData.mStream = mOverlayImage->GetSidebandStream();
- imgData.mSize = IntSize(width, height);
- mOverlayImage->SetData(imgData);
- } else {
- OverlayImage::Data imgData;
- imgData.mOverlayId = mOverlayImage->GetOverlayId();
- imgData.mSize = IntSize(width, height);
- mOverlayImage->SetData(imgData);
- }
-#endif
-
SourceMediaStream* srcStream = GetInputStream()->AsSourceStream();
StreamTracks::Track* track = srcStream->FindTrack(TRACK_VIDEO_PRIMARY);
@@ -1610,23 +1556,6 @@ DOMHwMediaStream::SetImageSize(uint32_t width, uint32_t height)
return;
}
-#ifdef MOZ_WIDGET_GONK
- // Clear the old segment.
- // Changing the existing content of segment is a Very BAD thing, and this way will
- // confuse consumers of MediaStreams.
- // It is only acceptable for DOMHwMediaStream
- // because DOMHwMediaStream doesn't have consumers of TV streams currently.
- track->GetSegment()->Clear();
-
- // Change the image size.
- const StreamTime delta = STREAM_TIME_MAX;
- RefPtr<Image> image = static_cast<Image*>(mOverlayImage.get());
- mozilla::gfx::IntSize size = image->GetSize();
- VideoSegment segment;
-
- segment.AppendFrame(image.forget(), delta, size, mPrincipalHandle);
- srcStream->AppendToTrack(TRACK_VIDEO_PRIMARY, &segment);
-#endif
}
void
@@ -1635,9 +1564,6 @@ DOMHwMediaStream::SetOverlayImage(OverlayImage* aImage)
if (!aImage) {
return;
}
-#ifdef MOZ_WIDGET_GONK
- mOverlayImage = aImage;
-#endif
SourceMediaStream* srcStream = GetInputStream()->AsSourceStream();
StreamTracks::Track* track = srcStream->FindTrack(TRACK_VIDEO_PRIMARY);
@@ -1646,34 +1572,10 @@ DOMHwMediaStream::SetOverlayImage(OverlayImage* aImage)
return;
}
-#ifdef MOZ_WIDGET_GONK
- // Clear the old segment.
- // Changing the existing content of segment is a Very BAD thing, and this way will
- // confuse consumers of MediaStreams.
- // It is only acceptable for DOMHwMediaStream
- // because DOMHwMediaStream doesn't have consumers of TV streams currently.
- track->GetSegment()->Clear();
-
- // Change the image size.
- const StreamTime delta = STREAM_TIME_MAX;
- RefPtr<Image> image = static_cast<Image*>(mOverlayImage.get());
- mozilla::gfx::IntSize size = image->GetSize();
- VideoSegment segment;
-
- segment.AppendFrame(image.forget(), delta, size, mPrincipalHandle);
- srcStream->AppendToTrack(TRACK_VIDEO_PRIMARY, &segment);
-#endif
}
void
DOMHwMediaStream::SetOverlayId(int32_t aOverlayId)
{
-#ifdef MOZ_WIDGET_GONK
- OverlayImage::Data imgData;
-
- imgData.mOverlayId = aOverlayId;
- imgData.mSize = mOverlayImage->GetSize();
-
- mOverlayImage->SetData(imgData);
-#endif
+ /*** STUB ***/
}
diff --git a/dom/media/DOMMediaStream.h b/dom/media/DOMMediaStream.h
index 12f3529a8..5618f8b00 100644
--- a/dom/media/DOMMediaStream.h
+++ b/dom/media/DOMMediaStream.h
@@ -833,9 +833,6 @@ class DOMHwMediaStream : public DOMLocalMediaStream
{
typedef mozilla::gfx::IntSize IntSize;
typedef layers::OverlayImage OverlayImage;
-#ifdef MOZ_WIDGET_GONK
- typedef layers::OverlayImage::Data Data;
-#endif
public:
explicit DOMHwMediaStream(nsPIDOMWindowInner* aWindow);
@@ -853,14 +850,6 @@ protected:
private:
void Init(MediaStream* aStream, OverlayImage* aImage);
-
-#ifdef MOZ_WIDGET_GONK
- const int DEFAULT_IMAGE_ID = 0x01;
- const int DEFAULT_IMAGE_WIDTH = 400;
- const int DEFAULT_IMAGE_HEIGHT = 300;
- RefPtr<OverlayImage> mOverlayImage;
- PrincipalHandle mPrincipalHandle;
-#endif
};
} // namespace mozilla
diff --git a/dom/media/GraphDriver.cpp b/dom/media/GraphDriver.cpp
index 40e3b72cf..cae15eb8c 100644
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -640,11 +640,7 @@ AudioCallbackDriver::Init()
mSampleRate = output.rate = CubebUtils::PreferredSampleRate();
#if defined(__ANDROID__)
-#if defined(MOZ_B2G)
- output.stream_type = CubebUtils::ConvertChannelToCubebType(mAudioChannel);
-#else
output.stream_type = CUBEB_STREAM_TYPE_MUSIC;
-#endif
if (output.stream_type == CUBEB_STREAM_TYPE_MAX) {
NS_WARNING("Bad stream type");
return;
diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp
index 4a52c22ae..94f5f32a0 100644
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -9,9 +9,6 @@
#include "VideoUtils.h"
#include "ImageContainer.h"
-#ifdef MOZ_WIDGET_GONK
-#include <cutils/properties.h>
-#endif
#include <stdint.h>
namespace mozilla {
@@ -93,31 +90,6 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride;
}
-#ifdef MOZ_WIDGET_GONK
-static bool
-IsYV12Format(const VideoData::YCbCrBuffer::Plane& aYPlane,
- const VideoData::YCbCrBuffer::Plane& aCbPlane,
- const VideoData::YCbCrBuffer::Plane& aCrPlane)
-{
- return
- aYPlane.mWidth % 2 == 0 &&
- aYPlane.mHeight % 2 == 0 &&
- aYPlane.mWidth / 2 == aCbPlane.mWidth &&
- aYPlane.mHeight / 2 == aCbPlane.mHeight &&
- aCbPlane.mWidth == aCrPlane.mWidth &&
- aCbPlane.mHeight == aCrPlane.mHeight;
-}
-
-static bool
-IsInEmulator()
-{
- char propQemu[PROPERTY_VALUE_MAX];
- property_get("ro.kernel.qemu", propQemu, "");
- return !strncmp(propQemu, "1", 1);
-}
-
-#endif
-
VideoData::VideoData(int64_t aOffset,
int64_t aTime,
int64_t aDuration,
@@ -310,19 +282,8 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
aTimecode,
aInfo.mDisplay,
0));
-#ifdef MOZ_WIDGET_GONK
- const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
- const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
- const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
-#endif
-
// Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR
// format.
-#ifdef MOZ_WIDGET_GONK
- if (IsYV12Format(Y, Cb, Cr) && !IsInEmulator()) {
- v->mImage = new layers::GrallocImage();
- }
-#endif
if (!v->mImage) {
v->mImage = aContainer->CreatePlanarYCbCrImage();
}
@@ -341,20 +302,6 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
return nullptr;
}
-#ifdef MOZ_WIDGET_GONK
- if (!videoImage->IsValid() && IsYV12Format(Y, Cb, Cr)) {
- // Failed to allocate gralloc. Try fallback.
- v->mImage = aContainer->CreatePlanarYCbCrImage();
- if (!v->mImage) {
- return nullptr;
- }
- videoImage = v->mImage->AsPlanarYCbCrImage();
- if (!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
- true /* aCopyData */)) {
- return nullptr;
- }
- }
-#endif
return v.forget();
}
diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp
index ab39886ba..9334d1bcb 100644
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -327,11 +327,13 @@ MediaDecoder::SetVolume(double aVolume)
void
MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream,
+ TrackID aNextAvailableTrackID,
bool aFinishWhenEnded)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
- mDecoderStateMachine->AddOutputStream(aStream, aFinishWhenEnded);
+ mDecoderStateMachine->AddOutputStream(
+ aStream, aNextAvailableTrackID, aFinishWhenEnded);
}
void
@@ -342,6 +344,14 @@ MediaDecoder::RemoveOutputStream(MediaStream* aStream)
mDecoderStateMachine->RemoveOutputStream(aStream);
}
+TrackID
+MediaDecoder::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
+ return mDecoderStateMachine->NextAvailableTrackIDFor(aOutputStream);
+}
+
double
MediaDecoder::GetDuration()
{
@@ -1736,6 +1746,8 @@ MediaDecoder::RemoveMediaTracks()
videoList->RemoveTracks();
}
+ element->EndPreCreatedCapturedDecoderTracks();
+
mMediaTracksConstructed = false;
}
diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h
index 825bbbd2c..a4edcbe72 100644
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -210,9 +210,13 @@ public:
// Add an output stream. All decoder output will be sent to the stream.
// The stream is initially blocked. The decoder is responsible for unblocking
// it while it is playing back.
- virtual void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
+ virtual void AddOutputStream(ProcessedMediaStream* aStream,
+ TrackID aNextAvailableTrackID,
+ bool aFinishWhenEnded);
// Remove an output stream added with AddOutputStream.
virtual void RemoveOutputStream(MediaStream* aStream);
+ // The next TrackID that can be used without risk of a collision.
+ virtual TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const;
// Return the duration of the video in seconds.
virtual double GetDuration();
diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp
index f13e59b6c..c586139ad 100644
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2835,6 +2835,10 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
RefPtr<ShutdownPromise>
MediaDecoderStateMachine::BeginShutdown()
{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (mOutputStreamManager) {
+ mOutputStreamManager->Clear();
+ }
return InvokeAsync(OwnerThread(), this, __func__,
&MediaDecoderStateMachine::Shutdown);
}
@@ -3250,11 +3254,12 @@ MediaDecoderStateMachine::DumpDebugInfo()
}
void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
+ TrackID aNextAvailableTrackID,
bool aFinishWhenEnded)
{
MOZ_ASSERT(NS_IsMainThread());
DECODER_LOG("AddOutputStream aStream=%p!", aStream);
- mOutputStreamManager->Add(aStream, aFinishWhenEnded);
+ mOutputStreamManager->Add(aStream, aNextAvailableTrackID, aFinishWhenEnded);
nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>(
this, &MediaDecoderStateMachine::SetAudioCaptured, true);
OwnerThread()->Dispatch(r.forget());
@@ -3269,9 +3274,17 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>(
this, &MediaDecoderStateMachine::SetAudioCaptured, false);
OwnerThread()->Dispatch(r.forget());
+
}
}
+TrackID
+MediaDecoderStateMachine::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ return mOutputStreamManager->NextAvailableTrackIDFor(aOutputStream);
+}
+
size_t
MediaDecoderStateMachine::SizeOfVideoQueue() const
{
diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h
index a61fe13d2..ff3258ff1 100644
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -168,9 +168,12 @@ public:
void DumpDebugInfo();
- void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
+ void AddOutputStream(ProcessedMediaStream* aStream,
+ TrackID aNextAvailableTrackID,
+ bool aFinishWhenEnded);
// Remove an output stream added with AddOutputStream.
void RemoveOutputStream(MediaStream* aStream);
+ TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const;
// Seeks to the decoder to aTarget asynchronously.
RefPtr<MediaDecoder::SeekPromise> InvokeSeek(SeekTarget aTarget);
diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp
index 97a6855d9..ba6b4cd47 100644
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -13,9 +13,6 @@
#include "nsArray.h"
#include "nsContentUtils.h"
#include "nsHashPropertyBag.h"
-#ifdef MOZ_WIDGET_GONK
-#include "nsIAudioManager.h"
-#endif
#include "nsIEventTarget.h"
#include "nsIUUIDGenerator.h"
#include "nsIScriptGlobalObject.h"
@@ -73,10 +70,6 @@
#include "browser_logging/WebRtcLog.h"
#endif
-#ifdef MOZ_B2G
-#include "MediaPermissionGonk.h"
-#endif
-
#if defined (XP_WIN)
#include "mozilla/WindowsVersion.h"
#include <winsock2.h>
@@ -1573,7 +1566,7 @@ private:
RefPtr<MediaManager> mManager; // get ref to this when creating the runnable
};
-#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
+#if defined(ANDROID)
class GetUserMediaRunnableWrapper : public Runnable
{
public:
@@ -1819,10 +1812,6 @@ MediaManager::Get() {
__LINE__,
NS_LITERAL_STRING("Media shutdown"));
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
-#ifdef MOZ_B2G
- // Init MediaPermissionManager before sending out any permission requests.
- (void) MediaPermissionManager::GetInstance();
-#endif //MOZ_B2G
}
return sSingleton;
}
@@ -3050,18 +3039,6 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
}
return NS_OK;
}
-#ifdef MOZ_WIDGET_GONK
- else if (!strcmp(aTopic, "phone-state-changed")) {
- nsString state(aData);
- nsresult rv;
- uint32_t phoneState = state.ToInteger(&rv);
-
- if (NS_SUCCEEDED(rv) && phoneState == nsIAudioManager::PHONE_STATE_IN_CALL) {
- StopMediaStreams();
- }
- return NS_OK;
- }
-#endif
return NS_OK;
}
diff --git a/dom/media/MediaPermissionGonk.cpp b/dom/media/MediaPermissionGonk.cpp
deleted file mode 100644
index 2a9cbf331..000000000
--- a/dom/media/MediaPermissionGonk.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MediaManager.h"
-#include "MediaPermissionGonk.h"
-
-#include "nsArray.h"
-#include "nsCOMPtr.h"
-#include "nsIContentPermissionPrompt.h"
-#include "nsIDocument.h"
-#include "nsIDOMNavigatorUserMedia.h"
-#include "nsIStringEnumerator.h"
-#include "nsJSUtils.h"
-#include "nsQueryObject.h"
-#include "nsPIDOMWindow.h"
-#include "nsTArray.h"
-#include "GetUserMediaRequest.h"
-#include "mozilla/dom/PBrowserChild.h"
-#include "mozilla/dom/MediaStreamTrackBinding.h"
-#include "mozilla/dom/MediaStreamError.h"
-#include "nsISupportsPrimitives.h"
-#include "nsServiceManagerUtils.h"
-#include "nsArrayUtils.h"
-#include "nsContentPermissionHelper.h"
-#include "mozilla/dom/PermissionMessageUtils.h"
-
-#define AUDIO_PERMISSION_NAME "audio-capture"
-#define VIDEO_PERMISSION_NAME "video-capture"
-
-using namespace mozilla::dom;
-
-namespace mozilla {
-
-static MediaPermissionManager *gMediaPermMgr = nullptr;
-
-static void
-CreateDeviceNameList(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
- nsTArray<nsString> &aDeviceNameList)
-{
- for (uint32_t i = 0; i < aDevices.Length(); ++i) {
- nsString name;
- nsresult rv = aDevices[i]->GetName(name);
- NS_ENSURE_SUCCESS_VOID(rv);
- aDeviceNameList.AppendElement(name);
- }
-}
-
-static already_AddRefed<nsIMediaDevice>
-FindDeviceByName(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
- const nsAString &aDeviceName)
-{
- for (uint32_t i = 0; i < aDevices.Length(); ++i) {
- nsCOMPtr<nsIMediaDevice> device = aDevices[i];
- nsString deviceName;
- device->GetName(deviceName);
- if (deviceName.Equals(aDeviceName)) {
- return device.forget();
- }
- }
-
- return nullptr;
-}
-
-// Helper function for notifying permission granted
-static nsresult
-NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
-{
- nsresult rv;
- nsCOMPtr<nsIMutableArray> array = nsArray::Create();
-
- for (uint32_t i = 0; i < aDevices.Length(); ++i) {
- rv = array->AppendElement(aDevices.ElementAt(i), /*weak =*/ false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
-
- return obs->NotifyObservers(array, "getUserMedia:response:allow",
- aCallID.BeginReading());
-}
-
-// Helper function for notifying permision denial or error
-static nsresult
-NotifyPermissionDeny(const nsAString &aCallID, const nsAString &aErrorMsg)
-{
- nsresult rv;
- nsCOMPtr<nsISupportsString> supportsString =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = supportsString->SetData(aErrorMsg);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
-
- return obs->NotifyObservers(supportsString, "getUserMedia:response:deny",
- aCallID.BeginReading());
-}
-
-namespace {
-
-/**
- * MediaPermissionRequest will send a prompt ipdl request to b2g process according
- * to its owned type.
- */
-class MediaPermissionRequest : public nsIContentPermissionRequest
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSICONTENTPERMISSIONREQUEST
-
- MediaPermissionRequest(RefPtr<dom::GetUserMediaRequest> &aRequest,
- nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices);
-
- already_AddRefed<nsPIDOMWindowInner> GetOwner();
-
-protected:
- virtual ~MediaPermissionRequest() {}
-
-private:
- nsresult DoAllow(const nsString &audioDevice, const nsString &videoDevice);
-
- bool mAudio; // Request for audio permission
- bool mVideo; // Request for video permission
- RefPtr<dom::GetUserMediaRequest> mRequest;
- nsTArray<nsCOMPtr<nsIMediaDevice> > mAudioDevices; // candidate audio devices
- nsTArray<nsCOMPtr<nsIMediaDevice> > mVideoDevices; // candidate video devices
- nsCOMPtr<nsIContentPermissionRequester> mRequester;
-};
-
-// MediaPermissionRequest
-NS_IMPL_ISUPPORTS(MediaPermissionRequest, nsIContentPermissionRequest)
-
-MediaPermissionRequest::MediaPermissionRequest(RefPtr<dom::GetUserMediaRequest> &aRequest,
- nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
- : mRequest(aRequest)
-{
- dom::MediaStreamConstraints constraints;
- mRequest->GetConstraints(constraints);
-
- mAudio = !constraints.mAudio.IsBoolean() || constraints.mAudio.GetAsBoolean();
- mVideo = !constraints.mVideo.IsBoolean() || constraints.mVideo.GetAsBoolean();
-
- for (uint32_t i = 0; i < aDevices.Length(); ++i) {
- nsCOMPtr<nsIMediaDevice> device(aDevices[i]);
- nsAutoString deviceType;
- device->GetType(deviceType);
- if (mAudio && deviceType.EqualsLiteral("audio")) {
- mAudioDevices.AppendElement(device);
- }
- if (mVideo && deviceType.EqualsLiteral("video")) {
- mVideoDevices.AppendElement(device);
- }
- }
-
- nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
- mRequester = new nsContentPermissionRequester(window);
-}
-
-// nsIContentPermissionRequest methods
-NS_IMETHODIMP
-MediaPermissionRequest::GetTypes(nsIArray** aTypes)
-{
- nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
- //XXX append device list
- if (mAudio) {
- nsTArray<nsString> audioDeviceNames;
- CreateDeviceNameList(mAudioDevices, audioDeviceNames);
- nsCOMPtr<nsISupports> AudioType =
- new ContentPermissionType(NS_LITERAL_CSTRING(AUDIO_PERMISSION_NAME),
- NS_LITERAL_CSTRING("unused"),
- audioDeviceNames);
- types->AppendElement(AudioType, false);
- }
- if (mVideo) {
- nsTArray<nsString> videoDeviceNames;
- CreateDeviceNameList(mVideoDevices, videoDeviceNames);
- nsCOMPtr<nsISupports> VideoType =
- new ContentPermissionType(NS_LITERAL_CSTRING(VIDEO_PERMISSION_NAME),
- NS_LITERAL_CSTRING("unused"),
- videoDeviceNames);
- types->AppendElement(VideoType, false);
- }
- NS_IF_ADDREF(*aTypes = types);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
-{
- NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
-
- nsCOMPtr<nsPIDOMWindowInner> window =
- nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner();
- NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- NS_ADDREF(*aRequestingPrincipal = doc->NodePrincipal());
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetWindow(mozIDOMWindow** aRequestingWindow)
-{
- NS_ENSURE_ARG_POINTER(aRequestingWindow);
- nsCOMPtr<nsPIDOMWindowInner> window =
- nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner();
- window.forget(aRequestingWindow);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetElement(nsIDOMElement** aRequestingElement)
-{
- NS_ENSURE_ARG_POINTER(aRequestingElement);
- *aRequestingElement = nullptr;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::Cancel()
-{
- nsString callID;
- mRequest->GetCallID(callID);
- NotifyPermissionDeny(callID, NS_LITERAL_STRING("SecurityError"));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::Allow(JS::HandleValue aChoices)
-{
- // check if JS object
- if (!aChoices.isObject()) {
- MOZ_ASSERT(false, "Not a correct format of PermissionChoice");
- return NS_ERROR_INVALID_ARG;
- }
- // iterate through audio-capture and video-capture
- AutoJSAPI jsapi;
- if (!jsapi.Init(&aChoices.toObject())) {
- return NS_ERROR_UNEXPECTED;
- }
- JSContext* cx = jsapi.cx();
- JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
- JS::Rooted<JS::Value> v(cx);
-
- // get selected audio device name
- nsString audioDevice;
- if (mAudio) {
- if (!JS_GetProperty(cx, obj, AUDIO_PERMISSION_NAME, &v) || !v.isString()) {
- return NS_ERROR_FAILURE;
- }
- nsAutoJSString deviceName;
- if (!deviceName.init(cx, v)) {
- MOZ_ASSERT(false, "Couldn't initialize string from aChoices");
- return NS_ERROR_FAILURE;
- }
- audioDevice = deviceName;
- }
-
- // get selected video device name
- nsString videoDevice;
- if (mVideo) {
- if (!JS_GetProperty(cx, obj, VIDEO_PERMISSION_NAME, &v) || !v.isString()) {
- return NS_ERROR_FAILURE;
- }
- nsAutoJSString deviceName;
- if (!deviceName.init(cx, v)) {
- MOZ_ASSERT(false, "Couldn't initialize string from aChoices");
- return NS_ERROR_FAILURE;
- }
- videoDevice = deviceName;
- }
-
- return DoAllow(audioDevice, videoDevice);
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
-{
- NS_ENSURE_ARG_POINTER(aRequester);
-
- nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
- requester.forget(aRequester);
- return NS_OK;
-}
-
-nsresult
-MediaPermissionRequest::DoAllow(const nsString &audioDevice,
- const nsString &videoDevice)
-{
- nsTArray<nsCOMPtr<nsIMediaDevice> > selectedDevices;
- if (mAudio) {
- nsCOMPtr<nsIMediaDevice> device =
- FindDeviceByName(mAudioDevices, audioDevice);
- if (device) {
- selectedDevices.AppendElement(device);
- }
- }
-
- if (mVideo) {
- nsCOMPtr<nsIMediaDevice> device =
- FindDeviceByName(mVideoDevices, videoDevice);
- if (device) {
- selectedDevices.AppendElement(device);
- }
- }
-
- nsString callID;
- mRequest->GetCallID(callID);
- return NotifyPermissionAllow(callID, selectedDevices);
-}
-
-already_AddRefed<nsPIDOMWindowInner>
-MediaPermissionRequest::GetOwner()
-{
- nsCOMPtr<nsPIDOMWindowInner> window =
- nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner();
- return window.forget();
-}
-
-// Success callback for MediaManager::GetUserMediaDevices().
-class MediaDeviceSuccessCallback: public nsIGetUserMediaDevicesSuccessCallback
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIGETUSERMEDIADEVICESSUCCESSCALLBACK
-
- explicit MediaDeviceSuccessCallback(RefPtr<dom::GetUserMediaRequest> &aRequest)
- : mRequest(aRequest) {}
-
-protected:
- virtual ~MediaDeviceSuccessCallback() {}
-
-private:
- nsresult DoPrompt(RefPtr<MediaPermissionRequest> &req);
- RefPtr<dom::GetUserMediaRequest> mRequest;
-};
-
-NS_IMPL_ISUPPORTS(MediaDeviceSuccessCallback, nsIGetUserMediaDevicesSuccessCallback)
-
-// nsIGetUserMediaDevicesSuccessCallback method
-NS_IMETHODIMP
-MediaDeviceSuccessCallback::OnSuccess(nsIVariant* aDevices)
-{
- nsIID elementIID;
- uint16_t elementType;
- void* rawArray;
- uint32_t arrayLen;
-
- nsresult rv;
- rv = aDevices->GetAsArray(&elementType, &elementIID, &arrayLen, &rawArray);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (elementType != nsIDataType::VTYPE_INTERFACE) {
- free(rawArray);
- return NS_ERROR_FAILURE;
- }
-
- // Create array for nsIMediaDevice
- nsTArray<nsCOMPtr<nsIMediaDevice> > devices;
-
- nsISupports **supportsArray = reinterpret_cast<nsISupports **>(rawArray);
- for (uint32_t i = 0; i < arrayLen; ++i) {
- nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supportsArray[i]));
- devices.AppendElement(device);
- NS_IF_RELEASE(supportsArray[i]); // explicitly decrease reference count for raw pointer
- }
- free(rawArray); // explicitly free for the memory from nsIVariant::GetAsArray
-
- // Send MediaPermissionRequest
- RefPtr<MediaPermissionRequest> req = new MediaPermissionRequest(mRequest, devices);
- rv = DoPrompt(req);
-
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-// Trigger permission prompt UI
-nsresult
-MediaDeviceSuccessCallback::DoPrompt(RefPtr<MediaPermissionRequest> &req)
-{
- nsCOMPtr<nsPIDOMWindowInner> window(req->GetOwner());
- return dom::nsContentPermissionUtils::AskPermission(req, window);
-}
-
-// Error callback for MediaManager::GetUserMediaDevices()
-class MediaDeviceErrorCallback: public nsIDOMGetUserMediaErrorCallback
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDOMGETUSERMEDIAERRORCALLBACK
-
- explicit MediaDeviceErrorCallback(const nsAString &aCallID)
- : mCallID(aCallID) {}
-
-protected:
- virtual ~MediaDeviceErrorCallback() {}
-
-private:
- const nsString mCallID;
-};
-
-NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback)
-
-// nsIDOMGetUserMediaErrorCallback method
-NS_IMETHODIMP
-MediaDeviceErrorCallback::OnError(nsISupports* aError)
-{
- RefPtr<MediaStreamError> error = do_QueryObject(aError);
- if (!error) {
- return NS_ERROR_NO_INTERFACE;
- }
-
- nsString name;
- error->GetName(name);
- return NotifyPermissionDeny(mCallID, name);
-}
-
-} // namespace anonymous
-
-// MediaPermissionManager
-NS_IMPL_ISUPPORTS(MediaPermissionManager, nsIObserver)
-
-MediaPermissionManager*
-MediaPermissionManager::GetInstance()
-{
- if (!gMediaPermMgr) {
- gMediaPermMgr = new MediaPermissionManager();
- }
-
- return gMediaPermMgr;
-}
-
-MediaPermissionManager::MediaPermissionManager()
-{
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (obs) {
- obs->AddObserver(this, "getUserMedia:request", false);
- obs->AddObserver(this, "xpcom-shutdown", false);
- }
-}
-
-MediaPermissionManager::~MediaPermissionManager()
-{
- this->Deinit();
-}
-
-nsresult
-MediaPermissionManager::Deinit()
-{
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (obs) {
- obs->RemoveObserver(this, "getUserMedia:request");
- obs->RemoveObserver(this, "xpcom-shutdown");
- }
- return NS_OK;
-}
-
-// nsIObserver method
-NS_IMETHODIMP
-MediaPermissionManager::Observe(nsISupports* aSubject, const char* aTopic,
- const char16_t* aData)
-{
- nsresult rv;
- if (!strcmp(aTopic, "getUserMedia:request")) {
- RefPtr<dom::GetUserMediaRequest> req =
- static_cast<dom::GetUserMediaRequest*>(aSubject);
- rv = HandleRequest(req);
-
- if (NS_FAILED(rv)) {
- nsString callID;
- req->GetCallID(callID);
- NotifyPermissionDeny(callID, NS_LITERAL_STRING("unable to enumerate media device"));
- }
- } else if (!strcmp(aTopic, "xpcom-shutdown")) {
- rv = this->Deinit();
- } else {
- // not reachable
- rv = NS_ERROR_FAILURE;
- }
- return rv;
-}
-
-// Handle GetUserMediaRequest, query available media device first.
-nsresult
-MediaPermissionManager::HandleRequest(RefPtr<dom::GetUserMediaRequest> &req)
-{
- nsString callID;
- req->GetCallID(callID);
- uint64_t innerWindowID = req->InnerWindowID();
-
- nsCOMPtr<nsPIDOMWindowInner> innerWindow =
- nsGlobalWindow::GetInnerWindowWithId(innerWindowID)->AsInner();
- if (!innerWindow) {
- MOZ_ASSERT(false, "No inner window");
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess =
- new MediaDeviceSuccessCallback(req);
- nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError =
- new MediaDeviceErrorCallback(callID);
-
- dom::MediaStreamConstraints constraints;
- req->GetConstraints(constraints);
-
- RefPtr<MediaManager> MediaMgr = MediaManager::GetInstance();
- nsresult rv = MediaMgr->GetUserMediaDevices(innerWindow, constraints,
- onSuccess, onError,
- innerWindowID, callID);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/dom/media/MediaPermissionGonk.h b/dom/media/MediaPermissionGonk.h
deleted file mode 100644
index 0a2fac056..000000000
--- a/dom/media/MediaPermissionGonk.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DOM_MEDIA_MEDIAPERMISSIONGONK_H
-#define DOM_MEDIA_MEDIAPERMISSIONGONK_H
-
-#include "nsError.h"
-#include "nsIObserver.h"
-#include "nsISupportsImpl.h"
-#include "GetUserMediaRequest.h"
-
-namespace mozilla {
-
-/**
- * The observer to create the MediaPermissionMgr. This is the entry point of
- * permission request on b2g.
- */
-class MediaPermissionManager : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- static MediaPermissionManager* GetInstance();
-
-protected:
- virtual ~MediaPermissionManager();
-
-private:
- MediaPermissionManager();
- nsresult Deinit();
- nsresult HandleRequest(RefPtr<dom::GetUserMediaRequest> &req);
-};
-
-} // namespace mozilla
-
-#endif // DOM_MEDIA_MEDIAPERMISSIONGONK_H
-
diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp
index 94cafa029..e2934cbb2 100644
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1715,6 +1715,10 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
RefPtr<GraphDriver> driver = CurrentDriver();
MonitorAutoUnlock unlock(mMonitor);
driver->Start();
+ // It's not safe to Shutdown() a thread from StableState, and
+ // releasing this may shutdown a SystemClockDriver thread.
+ // Proxy the release to outside of StableState.
+ NS_ReleaseOnMainThread(driver.forget(), true); // always proxy
}
}
diff --git a/dom/media/MediaStreamTrack.cpp b/dom/media/MediaStreamTrack.cpp
index 8ccdeb90c..75cdeb1d1 100644
--- a/dom/media/MediaStreamTrack.cpp
+++ b/dom/media/MediaStreamTrack.cpp
@@ -165,11 +165,15 @@ MediaStreamTrack::Destroy()
mPrincipalHandleListener->Forget();
mPrincipalHandleListener = nullptr;
}
- for (auto l : mTrackListeners) {
- RemoveListener(l);
+ // Remove all listeners -- avoid iterating over the list we're removing from
+ const nsTArray<RefPtr<MediaStreamTrackListener>> trackListeners(mTrackListeners);
+ for (auto listener : trackListeners) {
+ RemoveListener(listener);
}
- for (auto l : mDirectTrackListeners) {
- RemoveDirectListener(l);
+ // Do the same as above for direct listeners
+ const nsTArray<RefPtr<DirectMediaStreamTrackListener>> directTrackListeners(mDirectTrackListeners);
+ for (auto listener : directTrackListeners) {
+ RemoveDirectListener(listener);
}
}
diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js
index 98b8debbe..0569b15ae 100644
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -516,6 +516,18 @@ RTCPeerConnection.prototype = {
};
},
+ // This implements the fairly common "Queue a task" logic
+ async _queueTaskWithClosedCheck(func) {
+ return new Promise(resolve => {
+ Services.tm.mainThread.dispatch({ run() {
+ if (!this._closed) {
+ func();
+ resolve();
+ }
+ }}, Ci.nsIThread.DISPATCH_NORMAL);
+ });
+ },
+
/**
* An RTCConfiguration may look like this:
*
@@ -791,7 +803,6 @@ RTCPeerConnection.prototype = {
return this._havePermission;
}
if (this._isChrome ||
- AppConstants.MOZ_B2G ||
Services.prefs.getBoolPref("media.navigator.permission.disabled")) {
return this._havePermission = Promise.resolve();
}
@@ -1446,7 +1457,10 @@ PeerConnectionObserver.prototype = {
break;
case "IceConnectionState":
- this.handleIceConnectionStateChange(this._dompc._pc.iceConnectionState);
+ let connState = this._dompc._pc.iceConnectionState;
+ this._dompc._queueTaskWithClosedCheck(() => {
+ this.handleIceConnectionStateChange(connState);
+ });
break;
case "IceGatheringState":
diff --git a/dom/media/android/AndroidMediaPluginHost.cpp b/dom/media/android/AndroidMediaPluginHost.cpp
index d3dce2b93..d4c4fc59e 100644
--- a/dom/media/android/AndroidMediaPluginHost.cpp
+++ b/dom/media/android/AndroidMediaPluginHost.cpp
@@ -12,7 +12,6 @@
#include "nsXPCOMStrings.h"
#include "nsISeekableStream.h"
#include "nsIGfxInfo.h"
-#include "gfxCrashReporterUtils.h"
#include "prmem.h"
#include "prlink.h"
#include "AndroidMediaResourceServer.h"
@@ -22,7 +21,7 @@
#include "nsIPropertyBag2.h"
-#if defined(ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(ANDROID)
#include "android/log.h"
#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "AndroidMediaPluginHost" , ## args)
#else
@@ -109,8 +108,6 @@ static bool IsOmxSupported()
return false;
}
- ScopedGfxFeatureReporter reporter("Stagefright", forceEnabled);
-
if (!forceEnabled) {
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
if (gfxInfo) {
@@ -125,7 +122,6 @@ static bool IsOmxSupported()
}
}
- reporter.SetSuccessful();
return true;
}
@@ -134,7 +130,7 @@ static bool IsOmxSupported()
// nullptr is returned if Omx decoding is not supported on the device,
static const char* GetOmxLibraryName()
{
-#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
+#if defined(ANDROID)
nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
NS_ASSERTION(infoService, "Could not find a system info service");
@@ -172,7 +168,7 @@ static const char* GetOmxLibraryName()
if (!IsOmxSupported())
return nullptr;
-#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
+#if defined(ANDROID)
if (version >= 17) {
return "libomxpluginkk.so";
}
@@ -180,8 +176,6 @@ static const char* GetOmxLibraryName()
// Ice Cream Sandwich and Jellybean
return "libomxplugin.so";
-#elif defined(ANDROID) && defined(MOZ_WIDGET_GONK)
- return "libomxplugin.so";
#else
return nullptr;
#endif
diff --git a/dom/media/encoder/OpusTrackEncoder.cpp b/dom/media/encoder/OpusTrackEncoder.cpp
index c65d57788..4b55b3954 100644
--- a/dom/media/encoder/OpusTrackEncoder.cpp
+++ b/dom/media/encoder/OpusTrackEncoder.cpp
@@ -9,12 +9,7 @@
#include <opus/opus.h>
#undef LOG
-#ifdef MOZ_WIDGET_GONK
-#include <android/log.h>
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args);
-#else
#define LOG(args, ...)
-#endif
namespace mozilla {
diff --git a/dom/media/encoder/TrackEncoder.cpp b/dom/media/encoder/TrackEncoder.cpp
index ea39bb5a6..df6b24409 100644
--- a/dom/media/encoder/TrackEncoder.cpp
+++ b/dom/media/encoder/TrackEncoder.cpp
@@ -10,12 +10,7 @@
#include "VideoUtils.h"
#undef LOG
-#ifdef MOZ_WIDGET_GONK
-#include <android/log.h>
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args);
-#else
#define LOG(args, ...)
-#endif
namespace mozilla {
diff --git a/dom/media/encoder/fmp4_muxer/AMRBox.cpp b/dom/media/encoder/fmp4_muxer/AMRBox.cpp
deleted file mode 100644
index cd1a34fae..000000000
--- a/dom/media/encoder/fmp4_muxer/AMRBox.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ISOControl.h"
-#include "ISOMediaBoxes.h"
-#include "AMRBox.h"
-#include "ISOTrackMetadata.h"
-
-namespace mozilla {
-
-nsresult
-AMRSampleEntry::Generate(uint32_t* aBoxSize)
-{
- uint32_t box_size;
- nsresult rv = amr_special_box->Generate(&box_size);
- NS_ENSURE_SUCCESS(rv, rv);
- size += box_size;
-
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-AMRSampleEntry::Write()
-{
- BoxSizeChecker checker(mControl, size);
- nsresult rv;
- rv = AudioSampleEntry::Write();
- NS_ENSURE_SUCCESS(rv, rv);
- rv = amr_special_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-AMRSampleEntry::AMRSampleEntry(ISOControl* aControl)
- : AudioSampleEntry(NS_LITERAL_CSTRING("samr"), aControl)
-{
- amr_special_box = new AMRSpecificBox(aControl);
- MOZ_COUNT_CTOR(AMRSampleEntry);
-}
-
-AMRSampleEntry::~AMRSampleEntry()
-{
- MOZ_COUNT_DTOR(AMRSampleEntry);
-}
-
-nsresult
-AMRSpecificBox::Generate(uint32_t* aBoxSize)
-{
- nsresult rv;
- FragmentBuffer* frag = mControl->GetFragment(Audio_Track);
- rv = frag->GetCSD(amrDecSpecInfo);
- NS_ENSURE_SUCCESS(rv, rv);
-
- size += amrDecSpecInfo.Length();
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-AMRSpecificBox::Write()
-{
- BoxSizeChecker checker(mControl, size);
- Box::Write();
- mControl->Write(amrDecSpecInfo.Elements(), amrDecSpecInfo.Length());
- return NS_OK;
-}
-
-AMRSpecificBox::AMRSpecificBox(ISOControl* aControl)
- : Box(NS_LITERAL_CSTRING("damr"), aControl)
-{
- MOZ_COUNT_CTOR(AMRSpecificBox);
-}
-
-AMRSpecificBox::~AMRSpecificBox()
-{
- MOZ_COUNT_DTOR(AMRSpecificBox);
-}
-
-}
diff --git a/dom/media/encoder/fmp4_muxer/AMRBox.h b/dom/media/encoder/fmp4_muxer/AMRBox.h
deleted file mode 100644
index 645d7f89c..000000000
--- a/dom/media/encoder/fmp4_muxer/AMRBox.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef AMRBOX_h_
-#define AMRBOX_h_
-
-#include "nsTArray.h"
-#include "MuxerOperation.h"
-
-namespace mozilla {
-
-class ISOControl;
-
-// 3GPP TS 26.244 6.7 'AMRSpecificBox field for AMRSampleEntry box'
-// Box type: 'damr'
-class AMRSpecificBox : public Box {
-public:
- // 3GPP members
- nsTArray<uint8_t> amrDecSpecInfo;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // AMRSpecificBox methods
- AMRSpecificBox(ISOControl* aControl);
- ~AMRSpecificBox();
-};
-
-// 3GPP TS 26.244 6.5 'AMRSampleEntry box'
-// Box type: 'sawb'
-class AMRSampleEntry : public AudioSampleEntry {
-public:
- // 3GPP members
- RefPtr<AMRSpecificBox> amr_special_box;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // AMRSampleEntry methods
- AMRSampleEntry(ISOControl* aControl);
- ~AMRSampleEntry();
-};
-
-}
-
-#endif // AMRBOX_h_
diff --git a/dom/media/encoder/fmp4_muxer/AVCBox.cpp b/dom/media/encoder/fmp4_muxer/AVCBox.cpp
deleted file mode 100644
index a45cda8b7..000000000
--- a/dom/media/encoder/fmp4_muxer/AVCBox.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <climits>
-#include "ISOControl.h"
-#include "ISOMediaBoxes.h"
-#include "AVCBox.h"
-
-namespace mozilla {
-
-nsresult
-AVCSampleEntry::Generate(uint32_t* aBoxSize)
-{
- uint32_t avc_box_size = 0;
- nsresult rv;
- rv = avcConfigBox->Generate(&avc_box_size);
- NS_ENSURE_SUCCESS(rv, rv);
-
- size += avc_box_size;
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-AVCSampleEntry::Write()
-{
- BoxSizeChecker checker(mControl, size);
- nsresult rv;
- rv = VisualSampleEntry::Write();
- NS_ENSURE_SUCCESS(rv, rv);
- rv = avcConfigBox->Write();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-AVCSampleEntry::AVCSampleEntry(ISOControl* aControl)
- : VisualSampleEntry(NS_LITERAL_CSTRING("avc1"), aControl)
-{
- avcConfigBox = new AVCConfigurationBox(aControl);
- MOZ_COUNT_CTOR(AVCSampleEntry);
-}
-
-AVCSampleEntry::~AVCSampleEntry()
-{
- MOZ_COUNT_DTOR(AVCSampleEntry);
-}
-
-AVCConfigurationBox::AVCConfigurationBox(ISOControl* aControl)
- : Box(NS_LITERAL_CSTRING("avcC"), aControl)
-{
- MOZ_COUNT_CTOR(AVCConfigurationBox);
-}
-
-AVCConfigurationBox::~AVCConfigurationBox()
-{
- MOZ_COUNT_DTOR(AVCConfigurationBox);
-}
-
-nsresult
-AVCConfigurationBox::Generate(uint32_t* aBoxSize)
-{
- nsresult rv;
- FragmentBuffer* frag = mControl->GetFragment(Video_Track);
- rv = frag->GetCSD(avcConfig);
- NS_ENSURE_SUCCESS(rv, rv);
- size += avcConfig.Length();
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-AVCConfigurationBox::Write()
-{
- BoxSizeChecker checker(mControl, size);
- Box::Write();
-
- mControl->Write(avcConfig.Elements(), avcConfig.Length());
-
- return NS_OK;
-}
-
-}
diff --git a/dom/media/encoder/fmp4_muxer/AVCBox.h b/dom/media/encoder/fmp4_muxer/AVCBox.h
deleted file mode 100644
index 9640d9e8f..000000000
--- a/dom/media/encoder/fmp4_muxer/AVCBox.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef AVCBox_h_
-#define AVCBox_h_
-
-#include "nsTArray.h"
-#include "ISOMediaBoxes.h"
-
-namespace mozilla {
-
-class ISOControl;
-
-// 14496-12 8.5.2.2
-#define resolution_72_dpi 0x00480000
-#define video_depth 0x0018
-
-// 14496-15 5.3.4.1 'Sample description name and format'
-// Box type: 'avcC'
-class AVCConfigurationBox : public Box {
-public:
- // ISO BMFF members
-
- // avcConfig is CodecSpecificData from 14496-15 '5.3.4.1 Sample description
- // name and format.
- // These data are generated by encoder and we encapsulated the generated
- // bitstream into box directly.
- nsTArray<uint8_t> avcConfig;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // AVCConfigurationBox methods
- AVCConfigurationBox(ISOControl* aControl);
- ~AVCConfigurationBox();
-};
-
-// 14496-15 5.3.4.1 'Sample description name and format'
-// Box type: 'avc1'
-class AVCSampleEntry : public VisualSampleEntry {
-public:
- // ISO BMFF members
- RefPtr<AVCConfigurationBox> avcConfigBox;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // VisualSampleEntry methods
- AVCSampleEntry(ISOControl* aControl);
- ~AVCSampleEntry();
-};
-
-}
-
-#endif // AVCBox_h_
diff --git a/dom/media/encoder/fmp4_muxer/EVRCBox.cpp b/dom/media/encoder/fmp4_muxer/EVRCBox.cpp
deleted file mode 100644
index 096e4013d..000000000
--- a/dom/media/encoder/fmp4_muxer/EVRCBox.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ISOControl.h"
-#include "ISOMediaBoxes.h"
-#include "EVRCBox.h"
-#include "ISOTrackMetadata.h"
-
-namespace mozilla {
-
-nsresult
-EVRCSampleEntry::Generate(uint32_t* aBoxSize)
-{
- uint32_t box_size;
- nsresult rv = evrc_special_box->Generate(&box_size);
- NS_ENSURE_SUCCESS(rv, rv);
- size += box_size;
-
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-EVRCSampleEntry::Write()
-{
- BoxSizeChecker checker(mControl, size);
- nsresult rv;
- rv = AudioSampleEntry::Write();
- NS_ENSURE_SUCCESS(rv, rv);
- rv = evrc_special_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-EVRCSampleEntry::EVRCSampleEntry(ISOControl* aControl)
- : AudioSampleEntry(NS_LITERAL_CSTRING("sevc"), aControl)
-{
- evrc_special_box = new EVRCSpecificBox(aControl);
- MOZ_COUNT_CTOR(EVRCSampleEntry);
-}
-
-EVRCSampleEntry::~EVRCSampleEntry()
-{
- MOZ_COUNT_DTOR(EVRCSampleEntry);
-}
-
-nsresult
-EVRCSpecificBox::Generate(uint32_t* aBoxSize)
-{
- nsresult rv;
- FragmentBuffer* frag = mControl->GetFragment(Audio_Track);
- rv = frag->GetCSD(evrcDecSpecInfo);
- NS_ENSURE_SUCCESS(rv, rv);
-
- size += evrcDecSpecInfo.Length();
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-EVRCSpecificBox::Write()
-{
- BoxSizeChecker checker(mControl, size);
- Box::Write();
- mControl->Write(evrcDecSpecInfo.Elements(), evrcDecSpecInfo.Length());
- return NS_OK;
-}
-
-EVRCSpecificBox::EVRCSpecificBox(ISOControl* aControl)
- : Box(NS_LITERAL_CSTRING("devc"), aControl)
-{
- MOZ_COUNT_CTOR(EVRCSpecificBox);
-}
-
-EVRCSpecificBox::~EVRCSpecificBox()
-{
- MOZ_COUNT_DTOR(EVRCSpecificBox);
-}
-
-}
diff --git a/dom/media/encoder/fmp4_muxer/EVRCBox.h b/dom/media/encoder/fmp4_muxer/EVRCBox.h
deleted file mode 100644
index 31355849a..000000000
--- a/dom/media/encoder/fmp4_muxer/EVRCBox.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef EVRCBOX_h_
-#define EVRCBOX_h_
-
-#include "nsTArray.h"
-#include "MuxerOperation.h"
-
-namespace mozilla {
-
-class ISOControl;
-
-// 3GPP TS 26.244 6.7 'EVRCSpecificBox field for EVRCSampleEntry box'
-// Box type: 'devc'
-class EVRCSpecificBox : public Box {
-public:
- // 3GPP members
- nsTArray<uint8_t> evrcDecSpecInfo;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // EVRCSpecificBox methods
- EVRCSpecificBox(ISOControl* aControl);
- ~EVRCSpecificBox();
-};
-
-// 3GPP TS 26.244 6.5 'EVRCSampleEntry box'
-// Box type: 'sevc'
-class EVRCSampleEntry : public AudioSampleEntry {
-public:
- // 3GPP members
- RefPtr<EVRCSpecificBox> evrc_special_box;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // EVRCSampleEntry methods
- EVRCSampleEntry(ISOControl* aControl);
- ~EVRCSampleEntry();
-};
-
-}
-
-#endif // EVRCBOX_h_
diff --git a/dom/media/encoder/fmp4_muxer/ISOControl.cpp b/dom/media/encoder/fmp4_muxer/ISOControl.cpp
deleted file mode 100644
index 6addaeb30..000000000
--- a/dom/media/encoder/fmp4_muxer/ISOControl.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <time.h>
-#include "nsAutoPtr.h"
-#include "ISOControl.h"
-#include "ISOMediaBoxes.h"
-#include "EncodedFrameContainer.h"
-
-namespace mozilla {
-
-// For MP4 creation_time and modification_time offset from January 1, 1904 to
-// January 1, 1970.
-#define iso_time_offset 2082844800
-
-FragmentBuffer::FragmentBuffer(uint32_t aTrackType, uint32_t aFragDuration)
- : mTrackType(aTrackType)
- , mFragDuration(aFragDuration)
- , mMediaStartTime(0)
- , mFragmentNumber(0)
- , mLastFrameTimeOfLastFragment(0)
- , mEOS(false)
-{
- mFragArray.AppendElement();
- MOZ_COUNT_CTOR(FragmentBuffer);
-}
-
-FragmentBuffer::~FragmentBuffer()
-{
- MOZ_COUNT_DTOR(FragmentBuffer);
-}
-
-bool
-FragmentBuffer::HasEnoughData()
-{
- // Audio or video frame is enough to form a moof.
- return (mFragArray.Length() > 1);
-}
-
-nsresult
-FragmentBuffer::GetCSD(nsTArray<uint8_t>& aCSD)
-{
- if (!mCSDFrame) {
- return NS_ERROR_FAILURE;
- }
- aCSD.AppendElements(mCSDFrame->GetFrameData().Elements(),
- mCSDFrame->GetFrameData().Length());
-
- return NS_OK;
-}
-
-nsresult
-FragmentBuffer::AddFrame(EncodedFrame* aFrame)
-{
- // already EOS, it rejects all new data.
- if (mEOS) {
- MOZ_ASSERT(0);
- return NS_OK;
- }
-
- EncodedFrame::FrameType type = aFrame->GetFrameType();
- if (type == EncodedFrame::AAC_CSD || type == EncodedFrame::AVC_CSD ||
- type == EncodedFrame::AMR_AUDIO_CSD || type == EncodedFrame::EVRC_AUDIO_CSD) {
- mCSDFrame = aFrame;
- // Use CSD's timestamp as the start time. Encoder should send CSD frame first
- // and then data frames.
- mMediaStartTime = aFrame->GetTimeStamp();
- mFragmentNumber = 1;
- return NS_OK;
- }
-
- // if the timestamp is incorrect, abort it.
- if (aFrame->GetTimeStamp() < mMediaStartTime) {
- MOZ_ASSERT(false);
- return NS_ERROR_FAILURE;
- }
-
- mFragArray.LastElement().AppendElement(aFrame);
-
- // check if current fragment is reach the fragment duration.
- if ((aFrame->GetTimeStamp() - mMediaStartTime) >= (mFragDuration * mFragmentNumber)) {
- mFragArray.AppendElement();
- mFragmentNumber++;
- }
-
- return NS_OK;
-}
-
-nsresult
-FragmentBuffer::GetFirstFragment(nsTArray<RefPtr<EncodedFrame>>& aFragment,
- bool aFlush)
-{
- // It should be called only if there is a complete fragment in mFragArray.
- if (mFragArray.Length() <= 1 && !mEOS) {
- MOZ_ASSERT(false);
- return NS_ERROR_FAILURE;
- }
-
- if (aFlush) {
- aFragment.SwapElements(mFragArray.ElementAt(0));
- mFragArray.RemoveElementAt(0);
- } else {
- aFragment.AppendElements(mFragArray.ElementAt(0));
- }
- return NS_OK;
-}
-
-uint32_t
-FragmentBuffer::GetFirstFragmentSampleNumber()
-{
- return mFragArray.ElementAt(0).Length();
-}
-
-uint32_t
-FragmentBuffer::GetFirstFragmentSampleSize()
-{
- uint32_t size = 0;
- uint32_t len = mFragArray.ElementAt(0).Length();
- for (uint32_t i = 0; i < len; i++) {
- size += mFragArray.ElementAt(0).ElementAt(i)->GetFrameData().Length();
- }
- return size;
-}
-
-ISOControl::ISOControl(uint32_t aMuxingType)
- : mMuxingType(aMuxingType)
- , mAudioFragmentBuffer(nullptr)
- , mVideoFragmentBuffer(nullptr)
- , mFragNum(0)
- , mOutputSize(0)
- , mBitCount(0)
- , mBit(0)
-{
- // Create a data array for first mp4 Box, ftyp.
- mOutBuffers.SetLength(1);
- MOZ_COUNT_CTOR(ISOControl);
-}
-
-ISOControl::~ISOControl()
-{
- MOZ_COUNT_DTOR(ISOControl);
-}
-
-uint32_t
-ISOControl::GetNextTrackID()
-{
- return (mMetaArray.Length() + 1);
-}
-
-uint32_t
-ISOControl::GetTrackID(TrackMetadataBase::MetadataKind aKind)
-{
- for (uint32_t i = 0; i < mMetaArray.Length(); i++) {
- if (mMetaArray[i]->GetKind() == aKind) {
- return (i + 1);
- }
- }
-
- // Track ID shouldn't be 0. It must be something wrong here.
- MOZ_ASSERT(0);
- return 0;
-}
-
-nsresult
-ISOControl::SetMetadata(TrackMetadataBase* aTrackMeta)
-{
- if (aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AAC ||
- aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AMR ||
- aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AVC ||
- aTrackMeta->GetKind() == TrackMetadataBase::METADATA_EVRC) {
- mMetaArray.AppendElement(aTrackMeta);
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
-}
-
-nsresult
-ISOControl::GetAudioMetadata(RefPtr<AudioTrackMetadata>& aAudMeta)
-{
- for (uint32_t i = 0; i < mMetaArray.Length() ; i++) {
- if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AAC ||
- mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AMR ||
- mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_EVRC) {
- aAudMeta = static_cast<AudioTrackMetadata*>(mMetaArray[i].get());
- return NS_OK;
- }
- }
- return NS_ERROR_FAILURE;
-}
-
-nsresult
-ISOControl::GetVideoMetadata(RefPtr<VideoTrackMetadata>& aVidMeta)
-{
- for (uint32_t i = 0; i < mMetaArray.Length() ; i++) {
- if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AVC) {
- aVidMeta = static_cast<VideoTrackMetadata*>(mMetaArray[i].get());
- return NS_OK;
- }
- }
- return NS_ERROR_FAILURE;
-}
-
-bool
-ISOControl::HasAudioTrack()
-{
- RefPtr<AudioTrackMetadata> audMeta;
- GetAudioMetadata(audMeta);
- return audMeta;
-}
-
-bool
-ISOControl::HasVideoTrack()
-{
- RefPtr<VideoTrackMetadata> vidMeta;
- GetVideoMetadata(vidMeta);
- return vidMeta;
-}
-
-nsresult
-ISOControl::SetFragment(FragmentBuffer* aFragment)
-{
- if (aFragment->GetType() == Audio_Track) {
- mAudioFragmentBuffer = aFragment;
- } else {
- mVideoFragmentBuffer = aFragment;
- }
- return NS_OK;
-}
-
-FragmentBuffer*
-ISOControl::GetFragment(uint32_t aType)
-{
- if (aType == Audio_Track) {
- return mAudioFragmentBuffer;
- } else if (aType == Video_Track){
- return mVideoFragmentBuffer;
- }
- MOZ_ASSERT(0);
- return nullptr;
-}
-
-nsresult
-ISOControl::GetBufs(nsTArray<nsTArray<uint8_t>>* aOutputBufs)
-{
- uint32_t len = mOutBuffers.Length();
- for (uint32_t i = 0; i < len; i++) {
- mOutBuffers[i].SwapElements(*aOutputBufs->AppendElement());
- }
- return FlushBuf();
-}
-
-nsresult
-ISOControl::FlushBuf()
-{
- mOutBuffers.SetLength(1);
- return NS_OK;
-}
-
-uint32_t
-ISOControl::WriteAVData(nsTArray<uint8_t>& aArray)
-{
- MOZ_ASSERT(!mBitCount);
-
- uint32_t len = aArray.Length();
- if (!len) {
- return 0;
- }
-
- mOutputSize += len;
-
- // The last element already has data, allocated a new element for pointer
- // swapping.
- if (mOutBuffers.LastElement().Length()) {
- mOutBuffers.AppendElement();
- }
- // Swap the video/audio data pointer.
- mOutBuffers.LastElement().SwapElements(aArray);
- // Following data could be boxes, so appending a new uint8_t array here.
- mOutBuffers.AppendElement();
-
- return len;
-}
-
-uint32_t
-ISOControl::WriteBits(uint64_t aBits, size_t aNumBits)
-{
- uint8_t output_byte = 0;
-
- MOZ_ASSERT(aNumBits <= 64);
- // TODO: rewritten following with bitset?
- for (size_t i = aNumBits; i > 0; i--) {
- mBit |= (((aBits >> (i - 1)) & 1) << (8 - ++mBitCount));
- if (mBitCount == 8) {
- Write(&mBit, sizeof(uint8_t));
- mBit = 0;
- mBitCount = 0;
- output_byte++;
- }
- }
- return output_byte;
-}
-
-uint32_t
-ISOControl::Write(uint8_t* aBuf, uint32_t aSize)
-{
- mOutBuffers.LastElement().AppendElements(aBuf, aSize);
- mOutputSize += aSize;
- return aSize;
-}
-
-uint32_t
-ISOControl::Write(uint8_t aData)
-{
- MOZ_ASSERT(!mBitCount);
- Write((uint8_t*)&aData, sizeof(uint8_t));
- return sizeof(uint8_t);
-}
-
-uint32_t
-ISOControl::GetBufPos()
-{
- uint32_t len = mOutBuffers.Length();
- uint32_t pos = 0;
- for (uint32_t i = 0; i < len; i++) {
- pos += mOutBuffers.ElementAt(i).Length();
- }
- return pos;
-}
-
-uint32_t
-ISOControl::WriteFourCC(const char* aType)
-{
- // Bit operation should be aligned to byte before writing any byte data.
- MOZ_ASSERT(!mBitCount);
-
- uint32_t size = strlen(aType);
- if (size == 4) {
- return Write((uint8_t*)aType, size);
- }
-
- return 0;
-}
-
-nsresult
-ISOControl::GenerateFtyp()
-{
- nsresult rv;
- uint32_t size;
- nsAutoPtr<FileTypeBox> type_box(new FileTypeBox(this));
- rv = type_box->Generate(&size);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = type_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-nsresult
-ISOControl::GenerateMoov()
-{
- nsresult rv;
- uint32_t size;
- nsAutoPtr<MovieBox> moov_box(new MovieBox(this));
- rv = moov_box->Generate(&size);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = moov_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-nsresult
-ISOControl::GenerateMoof(uint32_t aTrackType)
-{
- mFragNum++;
-
- nsresult rv;
- uint32_t size;
- uint64_t first_sample_offset = mOutputSize;
- nsAutoPtr<MovieFragmentBox> moof_box(new MovieFragmentBox(aTrackType, this));
- nsAutoPtr<MediaDataBox> mdat_box(new MediaDataBox(aTrackType, this));
-
- rv = moof_box->Generate(&size);
- NS_ENSURE_SUCCESS(rv, rv);
- first_sample_offset += size;
- rv = mdat_box->Generate(&size);
- NS_ENSURE_SUCCESS(rv, rv);
- first_sample_offset += mdat_box->FirstSampleOffsetInMediaDataBox();
-
- // correct offset info
- nsTArray<RefPtr<MuxerOperation>> tfhds;
- rv = moof_box->Find(NS_LITERAL_CSTRING("tfhd"), tfhds);
- NS_ENSURE_SUCCESS(rv, rv);
- uint32_t len = tfhds.Length();
- for (uint32_t i = 0; i < len; i++) {
- TrackFragmentHeaderBox* tfhd = (TrackFragmentHeaderBox*) tfhds.ElementAt(i).get();
- rv = tfhd->UpdateBaseDataOffset(first_sample_offset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = moof_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mdat_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-uint32_t
-ISOControl::GetTime()
-{
- return (uint64_t)time(nullptr) + iso_time_offset;
-}
-
-}
diff --git a/dom/media/encoder/fmp4_muxer/ISOControl.h b/dom/media/encoder/fmp4_muxer/ISOControl.h
deleted file mode 100644
index 3c445caee..000000000
--- a/dom/media/encoder/fmp4_muxer/ISOControl.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef ISOCOMPOSITOR_H_
-#define ISOCOMPOSITOR_H_
-
-#include "mozilla/EndianUtils.h"
-#include "nsTArray.h"
-#include "ISOTrackMetadata.h"
-#include "EncodedFrameContainer.h"
-
-namespace mozilla {
-
-class Box;
-class ISOControl;
-
-/**
- * This class collects elementary stream data to form a fragment.
- * ISOMediaWriter will check if the data is enough; if yes, the corresponding
- * moof will be created and write to ISOControl.
- * Each audio and video has its own fragment and only one during the whole
- * life cycle, when a fragment is formed in ISOControl, Flush() needs to
- * be called to reset it.
- */
-class FragmentBuffer {
-public:
- // aTrackType: it could be Audio_Track or Video_Track.
- // aFragDuration: it is the fragment duration. (microsecond per unit)
- // Audio and video have the same fragment duration.
- FragmentBuffer(uint32_t aTrackType, uint32_t aFragDuration);
- ~FragmentBuffer();
-
- // Get samples of first fragment, that will swap all the elements in the
- // mFragArray[0] when aFlush = true, and caller is responsible for drop
- // EncodedFrame reference count.
- nsresult GetFirstFragment(nsTArray<RefPtr<EncodedFrame>>& aFragment,
- bool aFlush = false);
-
- // Add sample frame to the last element fragment of mFragArray. If sample
- // number is enough, it will append a new fragment element. And the new
- // sample will be added to the new fragment element of mFragArray.
- nsresult AddFrame(EncodedFrame* aFrame);
-
- // Get total sample size of first complete fragment size.
- uint32_t GetFirstFragmentSampleSize();
-
- // Get sample number of first complete fragment.
- uint32_t GetFirstFragmentSampleNumber();
-
- // Check if it accumulates enough frame data.
- // It returns true when data is enough to form a fragment.
- bool HasEnoughData();
-
- // Called by ISOMediaWriter when TrackEncoder has sent the last frame. The
- // remains frame data will form the last moof and move the state machine to
- // in ISOMediaWriter to last phrase.
- nsresult SetEndOfStream() {
- mEOS = true;
- return NS_OK;
- }
- bool EOS() { return mEOS; }
-
- // CSD (codec specific data), it is generated by encoder and the data depends
- // on codec type. This data will be sent as a special frame from encoder to
- // ISOMediaWriter and pass to this class via AddFrame().
- nsresult GetCSD(nsTArray<uint8_t>& aCSD);
-
- bool HasCSD() { return mCSDFrame; }
-
- uint32_t GetType() { return mTrackType; }
-
- void SetLastFragmentLastFrameTime(uint32_t aTime) {
- mLastFrameTimeOfLastFragment = aTime;
- }
-
- uint32_t GetLastFragmentLastFrameTime() {
- return mLastFrameTimeOfLastFragment;
- }
-
-private:
- uint32_t mTrackType;
-
- // Fragment duration, microsecond per unit.
- uint32_t mFragDuration;
-
- // Media start time, microsecond per unit.
- // Together with mFragDuration, mFragmentNumber and EncodedFrame->GetTimeStamp(),
- // when the difference between current frame time and mMediaStartTime is
- // exceeded current fragment ceiling timeframe, that means current fragment has
- // enough data and a new element in mFragArray will be added.
- uint64_t mMediaStartTime;
-
- // Current fragment number. It will be increase when a new element of
- // mFragArray is created.
- // Note:
- // It only means the fragment number of current accumulated frames, not
- // the current 'creating' fragment mFragNum in ISOControl.
- uint32_t mFragmentNumber;
-
- // The last frame time stamp of last fragment. It is for calculating the
- // play duration of first frame in current fragment. The frame duration is
- // defined as "current frame timestamp - last frame timestamp" here. So it
- // needs to keep the last timestamp of last fragment.
- uint32_t mLastFrameTimeOfLastFragment;
-
- // Array of fragments, each element has enough samples to form a
- // complete fragment.
- nsTArray<nsTArray<RefPtr<EncodedFrame>>> mFragArray;
-
- // Codec specific data frame, it will be generated by encoder and send to
- // ISOMediaWriter through WriteEncodedTrack(). The data will be vary depends
- // on codec type.
- RefPtr<EncodedFrame> mCSDFrame;
-
- // END_OF_STREAM from ContainerWriter
- bool mEOS;
-};
-
-/**
- * ISOControl will be carried to each box when box is created. It is the main
- * bridge for box to output stream to ContainerWriter and retrieve information.
- * ISOControl acts 3 different roles:
- * 1. Holds the pointer of audio metadata, video metadata, fragment and
- * pass them to boxes.
- * 2. Provide the functions to generate the base structure of MP4; they are
- * GenerateFtyp, GenerateMoov, GenerateMoof, and GenerateMfra.
- * 3. The actually writer used by MuxOperation::Write() in each box. It provides
- * writing methods for different kind of data; they are Write, WriteArray,
- * WriteBits...etc.
- */
-class ISOControl {
-
-friend class Box;
-
-public:
- ISOControl(uint32_t aMuxingType);
- ~ISOControl();
-
- nsresult GenerateFtyp();
- nsresult GenerateMoov();
- nsresult GenerateMoof(uint32_t aTrackType);
-
- // Swap elementary stream pointer to output buffers.
- uint32_t WriteAVData(nsTArray<uint8_t>& aArray);
-
- uint32_t Write(uint8_t* aBuf, uint32_t aSize);
-
- uint32_t Write(uint8_t aData);
-
- template <typename T>
- uint32_t Write(T aData) {
- MOZ_ASSERT(!mBitCount);
-
- aData = NativeEndian::swapToNetworkOrder(aData);
- Write((uint8_t*)&aData, sizeof(T));
- return sizeof(T);
- }
-
- template <typename T>
- uint32_t WriteArray(const T &aArray, uint32_t aSize) {
- MOZ_ASSERT(!mBitCount);
-
- uint32_t size = 0;
- for (uint32_t i = 0; i < aSize; i++) {
- size += Write(aArray[i]);
- }
- return size;
- }
-
- uint32_t WriteFourCC(const char* aType);
-
- // Bit writing. Note: it needs to be byte-boundary before using
- // others non-bit writing function.
- uint32_t WriteBits(uint64_t aBits, size_t aNumBits);
-
- // This is called by GetContainerData and swap all the buffers to aOutputBuffers.
- nsresult GetBufs(nsTArray<nsTArray<uint8_t>>* aOutputBufs);
-
- // Presentation time in seconds since midnight, Jan. 1, 1904, in UTC time.
- uint32_t GetTime();
-
- // current fragment number
- uint32_t GetCurFragmentNumber() { return mFragNum; }
-
- nsresult SetFragment(FragmentBuffer* aFragment);
- FragmentBuffer* GetFragment(uint32_t aType);
-
- uint32_t GetMuxingType() { return mMuxingType; }
-
- nsresult SetMetadata(TrackMetadataBase* aTrackMeta);
- nsresult GetAudioMetadata(RefPtr<AudioTrackMetadata>& aAudMeta);
- nsresult GetVideoMetadata(RefPtr<VideoTrackMetadata>& aVidMeta);
-
- // Track ID is the Metadata index in mMetaArray. It allows only 1 audio
- // track and 1 video track in this muxer. In this muxer, it is prohibt to have
- // mutiple audio track or video track in the same file.
- uint32_t GetTrackID(TrackMetadataBase::MetadataKind aKind);
- uint32_t GetNextTrackID();
-
- bool HasAudioTrack();
- bool HasVideoTrack();
-
-private:
- uint32_t GetBufPos();
- nsresult FlushBuf();
-
- // One of value in TYPE_XXX, defined in ISOMediaWriter.
- uint32_t mMuxingType;
-
- // Audio and video fragments are owned by ISOMediaWriter.
- // They don't need to worry about pointer going stale because ISOMediaWriter's
- // lifetime is longer than ISOControl.
- FragmentBuffer* mAudioFragmentBuffer;
- FragmentBuffer* mVideoFragmentBuffer;
-
- // Generated fragment number
- uint32_t mFragNum;
-
- // The (index + 1) will be the track ID.
- nsTArray<RefPtr<TrackMetadataBase>> mMetaArray;
-
- // Array of output buffers.
- // To save memory usage, audio/video sample will be swapped into a new element
- // of this array.
- //
- // For example,
- // mOutBuffers[0] --> boxes (allocated by muxer)
- // mOutBuffers[1] --> video raw data (allocated by encoder)
- // mOutBuffers[2] --> video raw data (allocated by encoder)
- // mOutBuffers[3] --> video raw data (allocated by encoder)
- // mOutBuffers[4] --> boxes (allocated by muxer)
- // mOutBuffers[5] --> audio raw data (allocated by encoder)
- // ...etc.
- //
- nsTArray<nsTArray<uint8_t>> mOutBuffers;
-
- // Accumulate output size from Write().
- uint64_t mOutputSize;
-
- // Bit writing operation. Note: the mBitCount should be 0 before any
- // byte-boundary writing method be called (Write(uint32_t), Write(uint16_t)...etc);
- // otherwise, there will be assertion on these functions.
- uint8_t mBitCount;
- uint8_t mBit;
-};
-
-}
-#endif
diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp b/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
deleted file mode 100644
index 32a0c577b..000000000
--- a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
+++ /dev/null
@@ -1,1550 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <climits>
-#include "TrackMetadataBase.h"
-#include "ISOMediaBoxes.h"
-#include "ISOControl.h"
-#include "ISOMediaWriter.h"
-#include "EncodedFrameContainer.h"
-#include "ISOTrackMetadata.h"
-#include "MP4ESDS.h"
-#include "AMRBox.h"
-#include "AVCBox.h"
-#include "EVRCBox.h"
-#include "VideoUtils.h"
-
-namespace mozilla {
-
-// 14496-12 6.2.2 'Data Types and fields'
-const uint32_t iso_matrix[] = { 0x00010000, 0, 0,
- 0, 0x00010000, 0,
- 0, 0, 0x40000000 };
-
-uint32_t
-set_sample_flags(bool aSync)
-{
- std::bitset<32> flags;
- flags.set(16, !aSync);
- return flags.to_ulong();
-}
-
-Box::BoxSizeChecker::BoxSizeChecker(ISOControl* aControl, uint32_t aSize)
-{
- mControl = aControl;
- ori_size = mControl->GetBufPos();
- box_size = aSize;
- MOZ_COUNT_CTOR(BoxSizeChecker);
-}
-
-Box::BoxSizeChecker::~BoxSizeChecker()
-{
- uint32_t cur_size = mControl->GetBufPos();
- if ((cur_size - ori_size) != box_size) {
- MOZ_ASSERT(false);
- }
-
- MOZ_COUNT_DTOR(BoxSizeChecker);
-}
-
-nsresult
-MediaDataBox::Generate(uint32_t* aBoxSize)
-{
- mFirstSampleOffset = size;
- mAllSampleSize = 0;
-
- if (mTrackType & Audio_Track) {
- FragmentBuffer* frag = mControl->GetFragment(Audio_Track);
- mAllSampleSize += frag->GetFirstFragmentSampleSize();
- }
- if (mTrackType & Video_Track) {
- FragmentBuffer* frag = mControl->GetFragment(Video_Track);
- mAllSampleSize += frag->GetFirstFragmentSampleSize();
- }
-
- size += mAllSampleSize;
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-MediaDataBox::Write()
-{
- nsresult rv;
- BoxSizeChecker checker(mControl, size);
- Box::Write();
- nsTArray<uint32_t> types;
- types.AppendElement(Audio_Track);
- types.AppendElement(Video_Track);
-
- for (uint32_t l = 0; l < types.Length(); l++) {
- if (mTrackType & types[l]) {
- FragmentBuffer* frag = mControl->GetFragment(types[l]);
- nsTArray<RefPtr<EncodedFrame>> frames;
-
- // Here is the last time we get fragment frames, flush it!
- rv = frag->GetFirstFragment(frames, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t len = frames.Length();
- for (uint32_t i = 0; i < len; i++) {
- nsTArray<uint8_t> frame_buffer;
- frames.ElementAt(i)->SwapOutFrameData(frame_buffer);
- mControl->WriteAVData(frame_buffer);
- }
- }
- }
-
- return NS_OK;
-}
-
-MediaDataBox::MediaDataBox(uint32_t aTrackType, ISOControl* aControl)
- : Box(NS_LITERAL_CSTRING("mdat"), aControl)
- , mAllSampleSize(0)
- , mFirstSampleOffset(0)
- , mTrackType(aTrackType)
-{
- MOZ_COUNT_CTOR(MediaDataBox);
-}
-
-MediaDataBox::~MediaDataBox()
-{
- MOZ_COUNT_DTOR(MediaDataBox);
-}
-
-uint32_t
-TrackRunBox::fillSampleTable()
-{
- uint32_t table_size = 0;
- nsresult rv;
- nsTArray<RefPtr<EncodedFrame>> frames;
- FragmentBuffer* frag = mControl->GetFragment(mTrackType);
-
- rv = frag->GetFirstFragment(frames);
- if (NS_FAILED(rv)) {
- return 0;
- }
- uint32_t len = frames.Length();
- sample_info_table = MakeUnique<tbl[]>(len);
- // Create sample table according to 14496-12 8.8.8.2.
- for (uint32_t i = 0; i < len; i++) {
- // Sample size.
- sample_info_table[i].sample_size = 0;
- if (flags.to_ulong() & flags_sample_size_present) {
- sample_info_table[i].sample_size = frames.ElementAt(i)->GetFrameData().Length();
- mAllSampleSize += sample_info_table[i].sample_size;
- table_size += sizeof(uint32_t);
- }
-
- // Sample flags.
- sample_info_table[i].sample_flags = 0;
- if (flags.to_ulong() & flags_sample_flags_present) {
- sample_info_table[i].sample_flags =
- set_sample_flags(
- (frames.ElementAt(i)->GetFrameType() == EncodedFrame::AVC_I_FRAME));
- table_size += sizeof(uint32_t);
- }
-
- // Sample duration.
- sample_info_table[i].sample_duration = 0;
- if (flags.to_ulong() & flags_sample_duration_present) {
- // Calculate each frame's duration, it is decided by "current frame
- // timestamp - last frame timestamp".
- uint64_t frame_time = 0;
- if (i == 0) {
- frame_time = frames.ElementAt(i)->GetTimeStamp() -
- frag->GetLastFragmentLastFrameTime();
- } else {
- frame_time = frames.ElementAt(i)->GetTimeStamp() -
- frames.ElementAt(i - 1)->GetTimeStamp();
- // Keep the last frame time of current fagment, it will be used to calculate
- // the first frame duration of next fragment.
- if ((len - 1) == i) {
- frag->SetLastFragmentLastFrameTime(frames.ElementAt(i)->GetTimeStamp());
- }
- }
-
- // In TrackRunBox, there should be exactly one type, either audio or video.
- MOZ_ASSERT((mTrackType & Video_Track) ^ (mTrackType & Audio_Track));
- sample_info_table[i].sample_duration = (mTrackType & Video_Track ?
- frame_time * mVideoMeta->GetVideoClockRate() / USECS_PER_S :
- frame_time * mAudioMeta->GetAudioSampleRate() / USECS_PER_S);
-
- table_size += sizeof(uint32_t);
- }
-
- sample_info_table[i].sample_composition_time_offset = 0;
- }
- return table_size;
-}
-
-nsresult
-TrackRunBox::Generate(uint32_t* aBoxSize)
-{
- FragmentBuffer* frag = mControl->GetFragment(mTrackType);
- sample_count = frag->GetFirstFragmentSampleNumber();
- size += sizeof(sample_count);
-
- // data_offset needs to be updated if there is other
- // TrackRunBox before this one.
- if (flags.to_ulong() & flags_data_offset_present) {
- data_offset = 0;
- size += sizeof(data_offset);
- }
- size += fillSampleTable();
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-TrackRunBox::SetDataOffset(uint32_t aOffset)
-{
- data_offset = aOffset;
- return NS_OK;
-}
-
-nsresult
-TrackRunBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(sample_count);
- if (flags.to_ulong() & flags_data_offset_present) {
- mControl->Write(data_offset);
- }
- for (uint32_t i = 0; i < sample_count; i++) {
- if (flags.to_ulong() & flags_sample_duration_present) {
- mControl->Write(sample_info_table[i].sample_duration);
- }
- if (flags.to_ulong() & flags_sample_size_present) {
- mControl->Write(sample_info_table[i].sample_size);
- }
- if (flags.to_ulong() & flags_sample_flags_present) {
- mControl->Write(sample_info_table[i].sample_flags);
- }
- }
-
- return NS_OK;
-}
-
-TrackRunBox::TrackRunBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("trun"), 0, aFlags, aControl)
- , sample_count(0)
- , data_offset(0)
- , first_sample_flags(0)
- , mAllSampleSize(0)
- , mTrackType(aType)
-{
- MOZ_COUNT_CTOR(TrackRunBox);
-}
-
-TrackRunBox::~TrackRunBox()
-{
- MOZ_COUNT_DTOR(TrackRunBox);
-}
-
-nsresult
-TrackFragmentHeaderBox::UpdateBaseDataOffset(uint64_t aOffset)
-{
- base_data_offset = aOffset;
- return NS_OK;
-}
-
-nsresult
-TrackFragmentHeaderBox::Generate(uint32_t* aBoxSize)
-{
- track_ID = (mTrackType == Audio_Track ?
- mControl->GetTrackID(mAudioMeta->GetKind()) :
- mControl->GetTrackID(mVideoMeta->GetKind()));
- size += sizeof(track_ID);
-
- if (flags.to_ulong() & base_data_offset_present) {
- // base_data_offset needs to add size of 'trun', 'tfhd' and
- // header of 'mdat' later.
- base_data_offset = 0;
- size += sizeof(base_data_offset);
- }
- if (flags.to_ulong() & default_sample_duration_present) {
- if (mTrackType == Video_Track) {
- if (!mVideoMeta->GetVideoFrameRate()) {
- // 0 means frame rate is variant, so it is wrong to write
- // default_sample_duration.
- MOZ_ASSERT(0);
- default_sample_duration = 0;
- } else {
- default_sample_duration = mVideoMeta->GetVideoClockRate() / mVideoMeta->GetVideoFrameRate();
- }
- } else if (mTrackType == Audio_Track) {
- default_sample_duration = mAudioMeta->GetAudioFrameDuration();
- } else {
- MOZ_ASSERT(0);
- return NS_ERROR_FAILURE;
- }
- size += sizeof(default_sample_duration);
- }
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-TrackFragmentHeaderBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(track_ID);
- if (flags.to_ulong() & base_data_offset_present) {
- mControl->Write(base_data_offset);
- }
- if (flags.to_ulong() & default_sample_duration_present) {
- mControl->Write(default_sample_duration);
- }
- return NS_OK;
-}
-
-TrackFragmentHeaderBox::TrackFragmentHeaderBox(uint32_t aType,
- uint32_t aFlags,
- ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("tfhd"), 0, aFlags, aControl)
- , track_ID(0)
- , base_data_offset(0)
- , default_sample_duration(0)
-{
- mTrackType = aType;
- MOZ_COUNT_CTOR(TrackFragmentHeaderBox);
-}
-
-TrackFragmentHeaderBox::~TrackFragmentHeaderBox()
-{
- MOZ_COUNT_DTOR(TrackFragmentHeaderBox);
-}
-
-TrackFragmentBox::TrackFragmentBox(uint32_t aType, ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("traf"), aControl)
- , mTrackType(aType)
-{
- // Flags in TrackFragmentHeaderBox.
- uint32_t tf_flags = base_data_offset_present;
-
- // Ideally, audio encoder generates audio frame in const rate. However, some
- // audio encoders don't do it so the audio frame duration needs to be checked
- // here.
- if ((mTrackType & Audio_Track) && mAudioMeta->GetAudioFrameDuration()) {
- tf_flags |= default_sample_duration_present;
- }
-
- boxes.AppendElement(new TrackFragmentHeaderBox(aType, tf_flags, aControl));
-
- // Always adds flags_data_offset_present in each TrackRunBox, Android
- // parser requires this flag to calculate the correct bitstream offset.
- uint32_t tr_flags = flags_sample_size_present | flags_data_offset_present;
-
- // Flags in TrackRunBox.
- // If there is no default sample duration exists, each frame duration needs to
- // be recored in the TrackRunBox.
- tr_flags |= (tf_flags & default_sample_duration_present ? 0 : flags_sample_duration_present);
-
- // For video, add sample_flags to record I frame.
- tr_flags |= (mTrackType & Video_Track ? flags_sample_flags_present : 0);
-
- boxes.AppendElement(new TrackRunBox(mTrackType, tr_flags, aControl));
- MOZ_COUNT_CTOR(TrackFragmentBox);
-}
-
-TrackFragmentBox::~TrackFragmentBox()
-{
- MOZ_COUNT_DTOR(TrackFragmentBox);
-}
-
-nsresult
-MovieFragmentHeaderBox::Generate(uint32_t* aBoxSize)
-{
- sequence_number = mControl->GetCurFragmentNumber();
- size += sizeof(sequence_number);
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-MovieFragmentHeaderBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(sequence_number);
- return NS_OK;
-}
-
-MovieFragmentHeaderBox::MovieFragmentHeaderBox(uint32_t aTrackType,
- ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("mfhd"), 0, 0, aControl)
- , sequence_number(0)
- , mTrackType(aTrackType)
-{
- MOZ_COUNT_CTOR(MovieFragmentHeaderBox);
-}
-
-MovieFragmentHeaderBox::~MovieFragmentHeaderBox()
-{
- MOZ_COUNT_DTOR(MovieFragmentHeaderBox);
-}
-
-MovieFragmentBox::MovieFragmentBox(uint32_t aType, ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("moof"), aControl)
- , mTrackType(aType)
-{
- boxes.AppendElement(new MovieFragmentHeaderBox(mTrackType, aControl));
-
- if (mTrackType & Audio_Track) {
- boxes.AppendElement(
- new TrackFragmentBox(Audio_Track, aControl));
- }
- if (mTrackType & Video_Track) {
- boxes.AppendElement(
- new TrackFragmentBox(Video_Track, aControl));
- }
- MOZ_COUNT_CTOR(MovieFragmentBox);
-}
-
-MovieFragmentBox::~MovieFragmentBox()
-{
- MOZ_COUNT_DTOR(MovieFragmentBox);
-}
-
-nsresult
-MovieFragmentBox::Generate(uint32_t* aBoxSize)
-{
- nsresult rv = DefaultContainerImpl::Generate(aBoxSize);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Correct data_offset if there are both audio and video track in
- // this fragment. This offset means the offset in the MediaDataBox.
- if (mTrackType & (Audio_Track | Video_Track)) {
- nsTArray<RefPtr<MuxerOperation>> truns;
- rv = Find(NS_LITERAL_CSTRING("trun"), truns);
- NS_ENSURE_SUCCESS(rv, rv);
- uint32_t len = truns.Length();
- uint32_t data_offset = 0;
- for (uint32_t i = 0; i < len; i++) {
- TrackRunBox* trun = (TrackRunBox*) truns.ElementAt(i).get();
- rv = trun->SetDataOffset(data_offset);
- NS_ENSURE_SUCCESS(rv, rv);
- data_offset += trun->GetAllSampleSize();
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-TrackExtendsBox::Generate(uint32_t* aBoxSize)
-{
- track_ID = (mTrackType == Audio_Track ?
- mControl->GetTrackID(mAudioMeta->GetKind()) :
- mControl->GetTrackID(mVideoMeta->GetKind()));
-
- if (mTrackType == Audio_Track) {
- default_sample_description_index = 1;
- default_sample_duration = mAudioMeta->GetAudioFrameDuration();
- default_sample_size = mAudioMeta->GetAudioFrameSize();
- default_sample_flags = set_sample_flags(1);
- } else if (mTrackType == Video_Track) {
- default_sample_description_index = 1;
- // Video meta data has assigned framerate, it implies that this video's
- // frame rate should be fixed.
- if (mVideoMeta->GetVideoFrameRate()) {
- default_sample_duration =
- mVideoMeta->GetVideoClockRate() / mVideoMeta->GetVideoFrameRate();
- }
- default_sample_size = 0;
- default_sample_flags = set_sample_flags(0);
- } else {
- MOZ_ASSERT(0);
- return NS_ERROR_FAILURE;
- }
-
- size += sizeof(track_ID) +
- sizeof(default_sample_description_index) +
- sizeof(default_sample_duration) +
- sizeof(default_sample_size) +
- sizeof(default_sample_flags);
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-TrackExtendsBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(track_ID);
- mControl->Write(default_sample_description_index);
- mControl->Write(default_sample_duration);
- mControl->Write(default_sample_size);
- mControl->Write(default_sample_flags);
-
- return NS_OK;
-}
-
-TrackExtendsBox::TrackExtendsBox(uint32_t aType, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("trex"), 0, 0, aControl)
- , track_ID(0)
- , default_sample_description_index(0)
- , default_sample_duration(0)
- , default_sample_size(0)
- , default_sample_flags(0)
- , mTrackType(aType)
-{
- MOZ_COUNT_CTOR(TrackExtendsBox);
-}
-
-TrackExtendsBox::~TrackExtendsBox()
-{
- MOZ_COUNT_DTOR(TrackExtendsBox);
-}
-
-MovieExtendsBox::MovieExtendsBox(ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("mvex"), aControl)
-{
- if (mAudioMeta) {
- boxes.AppendElement(new TrackExtendsBox(Audio_Track, aControl));
- }
- if (mVideoMeta) {
- boxes.AppendElement(new TrackExtendsBox(Video_Track, aControl));
- }
- MOZ_COUNT_CTOR(MovieExtendsBox);
-}
-
-MovieExtendsBox::~MovieExtendsBox()
-{
- MOZ_COUNT_DTOR(MovieExtendsBox);
-}
-
-nsresult
-ChunkOffsetBox::Generate(uint32_t* aBoxSize)
-{
- // We don't need time to sample table in fragmented mp4.
- entry_count = 0;
- size += sizeof(entry_count);
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-ChunkOffsetBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(entry_count);
- return NS_OK;
-}
-
-ChunkOffsetBox::ChunkOffsetBox(uint32_t aType, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("stco"), 0, 0, aControl)
- , entry_count(0)
-{
- MOZ_COUNT_CTOR(ChunkOffsetBox);
-}
-
-ChunkOffsetBox::~ChunkOffsetBox()
-{
- MOZ_COUNT_DTOR(ChunkOffsetBox);
-}
-
-nsresult
-SampleToChunkBox::Generate(uint32_t* aBoxSize)
-{
- // We don't need time to sample table in fragmented mp4
- entry_count = 0;
- size += sizeof(entry_count);
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-SampleToChunkBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(entry_count);
- return NS_OK;
-}
-
-SampleToChunkBox::SampleToChunkBox(uint32_t aType, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("stsc"), 0, 0, aControl)
- , entry_count(0)
-{
- MOZ_COUNT_CTOR(SampleToChunkBox);
-}
-
-SampleToChunkBox::~SampleToChunkBox()
-{
- MOZ_COUNT_DTOR(SampleToChunkBox);
-}
-
-nsresult
-TimeToSampleBox::Generate(uint32_t* aBoxSize)
-{
- // We don't need time to sample table in fragmented mp4.
- entry_count = 0;
- size += sizeof(entry_count);
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-TimeToSampleBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(entry_count);
- return NS_OK;
-}
-
-TimeToSampleBox::TimeToSampleBox(uint32_t aType, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("stts"), 0, 0, aControl)
- , entry_count(0)
-{
- MOZ_COUNT_CTOR(TimeToSampleBox);
-}
-
-TimeToSampleBox::~TimeToSampleBox()
-{
- MOZ_COUNT_DTOR(TimeToSampleBox);
-}
-
-nsresult
-SampleDescriptionBox::Generate(uint32_t* aBoxSize)
-{
- entry_count = 1;
- size += sizeof(entry_count);
-
- nsresult rv;
- uint32_t box_size;
- rv = sample_entry_box->Generate(&box_size);
- NS_ENSURE_SUCCESS(rv, rv);
- size += box_size;
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-SampleDescriptionBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- nsresult rv;
- mControl->Write(entry_count);
- rv = sample_entry_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-SampleDescriptionBox::SampleDescriptionBox(uint32_t aType, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("stsd"), 0, 0, aControl)
- , entry_count(0)
-{
- mTrackType = aType;
-
- switch (mTrackType) {
- case Audio_Track:
- {
- CreateAudioSampleEntry(sample_entry_box);
- }
- break;
- case Video_Track:
- {
- CreateVideoSampleEntry(sample_entry_box);
- }
- break;
- }
- MOZ_ASSERT(sample_entry_box);
- MOZ_COUNT_CTOR(SampleDescriptionBox);
-}
-
-nsresult
-SampleDescriptionBox::CreateAudioSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry)
-{
- if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AMR) {
- aSampleEntry = new AMRSampleEntry(mControl);
- } else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AAC) {
- aSampleEntry = new MP4AudioSampleEntry(mControl);
- } else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_EVRC) {
- aSampleEntry = new EVRCSampleEntry(mControl);
- } else {
- MOZ_ASSERT(0);
- }
- return NS_OK;
-}
-
-nsresult
-SampleDescriptionBox::CreateVideoSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry)
-{
- if (mVideoMeta->GetKind() == TrackMetadataBase::METADATA_AVC) {
- aSampleEntry = new AVCSampleEntry(mControl);
- } else {
- MOZ_ASSERT(0);
- }
- return NS_OK;
-}
-
-SampleDescriptionBox::~SampleDescriptionBox()
-{
- MOZ_COUNT_DTOR(SampleDescriptionBox);
-}
-
-nsresult
-SampleSizeBox::Generate(uint32_t* aBoxSize)
-{
- size += sizeof(sample_size) +
- sizeof(sample_count);
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-SampleSizeBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(sample_size);
- mControl->Write(sample_count);
- return NS_OK;
-}
-
-SampleSizeBox::SampleSizeBox(ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("stsz"), 0, 0, aControl)
- , sample_size(0)
- , sample_count(0)
-{
- MOZ_COUNT_CTOR(SampleSizeBox);
-}
-
-SampleSizeBox::~SampleSizeBox()
-{
- MOZ_COUNT_DTOR(SampleSizeBox);
-}
-
-SampleTableBox::SampleTableBox(uint32_t aType, ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("stbl"), aControl)
-{
- boxes.AppendElement(new SampleDescriptionBox(aType, aControl));
- boxes.AppendElement(new TimeToSampleBox(aType, aControl));
- boxes.AppendElement(new SampleToChunkBox(aType, aControl));
- boxes.AppendElement(new SampleSizeBox(aControl));
- boxes.AppendElement(new ChunkOffsetBox(aType, aControl));
- MOZ_COUNT_CTOR(SampleTableBox);
-}
-
-SampleTableBox::~SampleTableBox()
-{
- MOZ_COUNT_DTOR(SampleTableBox);
-}
-
-nsresult
-DataEntryUrlBox::Generate(uint32_t* aBoxSize)
-{
- // location is null here, do nothing
- size += location.Length();
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-DataEntryUrlBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- return NS_OK;
-}
-
-DataEntryUrlBox::DataEntryUrlBox()
- : FullBox(NS_LITERAL_CSTRING("url "), 0, 0, (ISOControl*) nullptr)
-{
- MOZ_COUNT_CTOR(DataEntryUrlBox);
-}
-
-DataEntryUrlBox::DataEntryUrlBox(ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("url "), 0, flags_media_at_the_same_file, aControl)
-{
- MOZ_COUNT_CTOR(DataEntryUrlBox);
-}
-
-DataEntryUrlBox::DataEntryUrlBox(const DataEntryUrlBox& aBox)
- : FullBox(aBox.boxType, aBox.version, aBox.flags.to_ulong(), aBox.mControl)
-{
- location = aBox.location;
- MOZ_COUNT_CTOR(DataEntryUrlBox);
-}
-
-DataEntryUrlBox::~DataEntryUrlBox()
-{
- MOZ_COUNT_DTOR(DataEntryUrlBox);
-}
-
-nsresult DataReferenceBox::Generate(uint32_t* aBoxSize)
-{
- entry_count = 1; // only allow on entry here
- size += sizeof(uint32_t);
-
- for (uint32_t i = 0; i < entry_count; i++) {
- uint32_t box_size = 0;
- DataEntryUrlBox* url = new DataEntryUrlBox(mControl);
- url->Generate(&box_size);
- size += box_size;
- urls.AppendElement(url);
- }
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult DataReferenceBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(entry_count);
-
- for (uint32_t i = 0; i < entry_count; i++) {
- urls[i]->Write();
- }
-
- return NS_OK;
-}
-
-DataReferenceBox::DataReferenceBox(ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("dref"), 0, 0, aControl)
- , entry_count(0)
-{
- MOZ_COUNT_CTOR(DataReferenceBox);
-}
-
-DataReferenceBox::~DataReferenceBox()
-{
- MOZ_COUNT_DTOR(DataReferenceBox);
-}
-
-DataInformationBox::DataInformationBox(ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("dinf"), aControl)
-{
- boxes.AppendElement(new DataReferenceBox(aControl));
- MOZ_COUNT_CTOR(DataInformationBox);
-}
-
-DataInformationBox::~DataInformationBox()
-{
- MOZ_COUNT_DTOR(DataInformationBox);
-}
-
-nsresult
-VideoMediaHeaderBox::Generate(uint32_t* aBoxSize)
-{
- size += sizeof(graphicsmode) +
- sizeof(opcolor);
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-VideoMediaHeaderBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(graphicsmode);
- mControl->WriteArray(opcolor, 3);
- return NS_OK;
-}
-
-VideoMediaHeaderBox::VideoMediaHeaderBox(ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("vmhd"), 0, 1, aControl)
- , graphicsmode(0)
-{
- memset(opcolor, 0 , sizeof(opcolor));
- MOZ_COUNT_CTOR(VideoMediaHeaderBox);
-}
-
-VideoMediaHeaderBox::~VideoMediaHeaderBox()
-{
- MOZ_COUNT_DTOR(VideoMediaHeaderBox);
-}
-
-nsresult
-SoundMediaHeaderBox::Generate(uint32_t* aBoxSize)
-{
- balance = 0;
- reserved = 0;
- size += sizeof(balance) +
- sizeof(reserved);
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-SoundMediaHeaderBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(balance);
- mControl->Write(reserved);
-
- return NS_OK;
-}
-
-SoundMediaHeaderBox::SoundMediaHeaderBox(ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("smhd"), 0, 0, aControl)
-{
- MOZ_COUNT_CTOR(SoundMediaHeaderBox);
-}
-
-SoundMediaHeaderBox::~SoundMediaHeaderBox()
-{
- MOZ_COUNT_DTOR(SoundMediaHeaderBox);
-}
-
-MediaInformationBox::MediaInformationBox(uint32_t aType, ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("minf"), aControl)
-{
- mTrackType = aType;
-
- if (mTrackType == Audio_Track) {
- boxes.AppendElement(new SoundMediaHeaderBox(aControl));
- } else if (mTrackType == Video_Track) {
- boxes.AppendElement(new VideoMediaHeaderBox(aControl));
- } else {
- MOZ_ASSERT(0);
- }
-
- boxes.AppendElement(new DataInformationBox(aControl));
- boxes.AppendElement(new SampleTableBox(aType, aControl));
- MOZ_COUNT_CTOR(MediaInformationBox);
-}
-
-MediaInformationBox::~MediaInformationBox()
-{
- MOZ_COUNT_DTOR(MediaInformationBox);
-}
-
-nsresult
-HandlerBox::Generate(uint32_t* aBoxSize)
-{
- pre_defined = 0;
- if (mTrackType == Audio_Track) {
- handler_type = FOURCC('s', 'o', 'u', 'n');
- } else if (mTrackType == Video_Track) {
- handler_type = FOURCC('v', 'i', 'd', 'e');
- }
-
- size += sizeof(pre_defined) +
- sizeof(handler_type) +
- sizeof(reserved);
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-HandlerBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(pre_defined);
- mControl->Write(handler_type);
- mControl->WriteArray(reserved, 3);
-
- return NS_OK;
-}
-
-HandlerBox::HandlerBox(uint32_t aType, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("hdlr"), 0, 0, aControl)
- , pre_defined(0)
- , handler_type(0)
-{
- mTrackType = aType;
- memset(reserved, 0 , sizeof(reserved));
- MOZ_COUNT_CTOR(HandlerBox);
-}
-
-HandlerBox::~HandlerBox()
-{
- MOZ_COUNT_DTOR(HandlerBox);
-}
-
-MediaHeaderBox::MediaHeaderBox(uint32_t aType, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("mdhd"), 0, 0, aControl)
- , creation_time(0)
- , modification_time(0)
- , timescale(0)
- , duration(0)
- , pad(0)
- , lang1(0)
- , lang2(0)
- , lang3(0)
- , pre_defined(0)
-{
- mTrackType = aType;
- MOZ_COUNT_CTOR(MediaHeaderBox);
-}
-
-MediaHeaderBox::~MediaHeaderBox()
-{
- MOZ_COUNT_DTOR(MediaHeaderBox);
-}
-
-uint32_t
-MediaHeaderBox::GetTimeScale()
-{
- if (mTrackType == Audio_Track) {
- return mAudioMeta->GetAudioSampleRate();
- }
-
- return mVideoMeta->GetVideoClockRate();
-}
-
-nsresult
-MediaHeaderBox::Generate(uint32_t* aBoxSize)
-{
- creation_time = mControl->GetTime();
- modification_time = mControl->GetTime();
- timescale = GetTimeScale();
- duration = 0; // fragmented mp4
-
- pad = 0;
- lang1 = 'u' - 0x60; // "und" underdetermined language
- lang2 = 'n' - 0x60;
- lang3 = 'd' - 0x60;
- size += (pad.size() + lang1.size() + lang2.size() + lang3.size()) / CHAR_BIT;
-
- pre_defined = 0;
- size += sizeof(creation_time) +
- sizeof(modification_time) +
- sizeof(timescale) +
- sizeof(duration) +
- sizeof(pre_defined);
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-MediaHeaderBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(creation_time);
- mControl->Write(modification_time);
- mControl->Write(timescale);
- mControl->Write(duration);
- mControl->WriteBits(pad.to_ulong(), pad.size());
- mControl->WriteBits(lang1.to_ulong(), lang1.size());
- mControl->WriteBits(lang2.to_ulong(), lang2.size());
- mControl->WriteBits(lang3.to_ulong(), lang3.size());
- mControl->Write(pre_defined);
-
- return NS_OK;
-}
-
-MovieBox::MovieBox(ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("moov"), aControl)
-{
- boxes.AppendElement(new MovieHeaderBox(aControl));
- if (aControl->HasAudioTrack()) {
- boxes.AppendElement(new TrackBox(Audio_Track, aControl));
- }
- if (aControl->HasVideoTrack()) {
- boxes.AppendElement(new TrackBox(Video_Track, aControl));
- }
- boxes.AppendElement(new MovieExtendsBox(aControl));
- MOZ_COUNT_CTOR(MovieBox);
-}
-
-MovieBox::~MovieBox()
-{
- MOZ_COUNT_DTOR(MovieBox);
-}
-
-nsresult
-MovieHeaderBox::Generate(uint32_t* aBoxSize)
-{
- creation_time = mControl->GetTime();
- modification_time = mControl->GetTime();
- timescale = GetTimeScale();
- duration = 0; // The duration is always 0 in fragmented mp4.
- next_track_ID = mControl->GetNextTrackID();
-
- size += sizeof(next_track_ID) +
- sizeof(creation_time) +
- sizeof(modification_time) +
- sizeof(timescale) +
- sizeof(duration) +
- sizeof(rate) +
- sizeof(volume) +
- sizeof(reserved16) +
- sizeof(reserved32) +
- sizeof(matrix) +
- sizeof(pre_defined);
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-MovieHeaderBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(creation_time);
- mControl->Write(modification_time);
- mControl->Write(timescale);
- mControl->Write(duration);
- mControl->Write(rate);
- mControl->Write(volume);
- mControl->Write(reserved16);
- mControl->WriteArray(reserved32, 2);
- mControl->WriteArray(matrix, 9);
- mControl->WriteArray(pre_defined, 6);
- mControl->Write(next_track_ID);
-
- return NS_OK;
-}
-
-uint32_t
-MovieHeaderBox::GetTimeScale()
-{
- // Only audio track in container.
- if (mAudioMeta && !mVideoMeta) {
- return mAudioMeta->GetAudioSampleRate();
- }
-
- // return video rate
- return mVideoMeta->GetVideoClockRate();
-}
-
-MovieHeaderBox::~MovieHeaderBox()
-{
- MOZ_COUNT_DTOR(MovieHeaderBox);
-}
-
-MovieHeaderBox::MovieHeaderBox(ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("mvhd"), 0, 0, aControl)
- , creation_time(0)
- , modification_time(0)
- , timescale(90000)
- , duration(0)
- , rate(0x00010000)
- , volume(0x0100)
- , reserved16(0)
- , next_track_ID(1)
-{
- memcpy(matrix, iso_matrix, sizeof(matrix));
- memset(reserved32, 0, sizeof(reserved32));
- memset(pre_defined, 0, sizeof(pre_defined));
- MOZ_COUNT_CTOR(MovieHeaderBox);
-}
-
-TrackHeaderBox::TrackHeaderBox(uint32_t aType, ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("tkhd"), 0,
- flags_track_enabled | flags_track_in_movie | flags_track_in_preview,
- aControl)
- , creation_time(0)
- , modification_time(0)
- , track_ID(0)
- , reserved(0)
- , duration(0)
- , layer(0)
- , alternate_group(0)
- , volume(0)
- , reserved3(0)
- , width(0)
- , height(0)
-{
- mTrackType = aType;
- memcpy(matrix, iso_matrix, sizeof(matrix));
- memset(reserved2, 0, sizeof(reserved2));
- MOZ_COUNT_CTOR(TrackHeaderBox);
-}
-
-TrackHeaderBox::~TrackHeaderBox()
-{
- MOZ_COUNT_DTOR(TrackHeaderBox);
-}
-
-nsresult
-TrackHeaderBox::Generate(uint32_t* aBoxSize)
-{
- creation_time = mControl->GetTime();
- modification_time = mControl->GetTime();
- track_ID = (mTrackType == Audio_Track ?
- mControl->GetTrackID(mAudioMeta->GetKind()) :
- mControl->GetTrackID(mVideoMeta->GetKind()));
- // fragmented mp4
- duration = 0;
-
- // volume, audiotrack is always 0x0100 in 14496-12 8.3.2.2
- volume = (mTrackType == Audio_Track ? 0x0100 : 0);
-
- if (mTrackType == Video_Track) {
- width = mVideoMeta->GetVideoDisplayWidth() << 16;
- height = mVideoMeta->GetVideoDisplayHeight() << 16;
- // Check display size, using the pixel size if any of them is invalid.
- if (!width || !height) {
- width = mVideoMeta->GetVideoWidth() << 16;
- height = mVideoMeta->GetVideoHeight() << 16;
- }
- }
-
- size += sizeof(creation_time) +
- sizeof(modification_time) +
- sizeof(track_ID) +
- sizeof(reserved) +
- sizeof(duration) +
- sizeof(reserved2) +
- sizeof(layer) +
- sizeof(alternate_group) +
- sizeof(volume) +
- sizeof(reserved3) +
- sizeof(matrix) +
- sizeof(width) +
- sizeof(height);
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-TrackHeaderBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- mControl->Write(creation_time);
- mControl->Write(modification_time);
- mControl->Write(track_ID);
- mControl->Write(reserved);
- mControl->Write(duration);
- mControl->WriteArray(reserved2, 2);
- mControl->Write(layer);
- mControl->Write(alternate_group);
- mControl->Write(volume);
- mControl->Write(reserved3);
- mControl->WriteArray(matrix, 9);
- mControl->Write(width);
- mControl->Write(height);
-
- return NS_OK;
-}
-
-nsresult
-FileTypeBox::Generate(uint32_t* aBoxSize)
-{
- minor_version = 0;
-
- if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_MP4) {
- if (!mControl->HasVideoTrack() && mControl->HasAudioTrack()) {
- major_brand = "M4A ";
- } else {
- major_brand = "MP42";
- }
- compatible_brands.AppendElement("mp42");
- compatible_brands.AppendElement("isom");
- } else if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_3GP) {
- major_brand = "3gp9";
- // According to 3GPP TS 26.244 V12.2.0, section 5.3.4, it's recommended to
- // list all compatible brands here. 3GP spec supports fragment from '3gp6'.
- compatible_brands.AppendElement("3gp9");
- compatible_brands.AppendElement("3gp8");
- compatible_brands.AppendElement("3gp7");
- compatible_brands.AppendElement("3gp6");
- compatible_brands.AppendElement("isom");
- } else if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_3G2) {
- major_brand = "3g2a";
- // 3GPP2 Release 0 and A and 3GPP Release 6 allow movie fragmentation
- compatible_brands.AppendElement("3gp9");
- compatible_brands.AppendElement("3gp8");
- compatible_brands.AppendElement("3gp7");
- compatible_brands.AppendElement("3gp6");
- compatible_brands.AppendElement("isom");
- compatible_brands.AppendElement("3g2c");
- compatible_brands.AppendElement("3g2b");
- compatible_brands.AppendElement("3g2a");
- } else {
- MOZ_ASSERT(0);
- }
-
- size += major_brand.Length() +
- sizeof(minor_version) +
- compatible_brands.Length() * 4;
-
- *aBoxSize = size;
-
- return NS_OK;
-}
-
-nsresult
-FileTypeBox::Write()
-{
- BoxSizeChecker checker(mControl, size);
- Box::Write();
- mControl->WriteFourCC(major_brand.get());
- mControl->Write(minor_version);
- uint32_t len = compatible_brands.Length();
- for (uint32_t i = 0; i < len; i++) {
- mControl->WriteFourCC(compatible_brands[i].get());
- }
-
- return NS_OK;
-}
-
-FileTypeBox::FileTypeBox(ISOControl* aControl)
- : Box(NS_LITERAL_CSTRING("ftyp"), aControl)
- , minor_version(0)
-{
- MOZ_COUNT_CTOR(FileTypeBox);
-}
-
-FileTypeBox::~FileTypeBox()
-{
- MOZ_COUNT_DTOR(FileTypeBox);
-}
-
-MediaBox::MediaBox(uint32_t aType, ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("mdia"), aControl)
-{
- mTrackType = aType;
- boxes.AppendElement(new MediaHeaderBox(aType, aControl));
- boxes.AppendElement(new HandlerBox(aType, aControl));
- boxes.AppendElement(new MediaInformationBox(aType, aControl));
- MOZ_COUNT_CTOR(MediaBox);
-}
-
-MediaBox::~MediaBox()
-{
- MOZ_COUNT_DTOR(MediaBox);
-}
-
-nsresult
-DefaultContainerImpl::Generate(uint32_t* aBoxSize)
-{
- nsresult rv;
- uint32_t box_size;
- uint32_t len = boxes.Length();
- for (uint32_t i = 0; i < len; i++) {
- rv = boxes.ElementAt(i)->Generate(&box_size);
- NS_ENSURE_SUCCESS(rv, rv);
- size += box_size;
- }
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-DefaultContainerImpl::Find(const nsACString& aType,
- nsTArray<RefPtr<MuxerOperation>>& aOperations)
-{
- nsresult rv = Box::Find(aType, aOperations);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t len = boxes.Length();
- for (uint32_t i = 0; i < len; i++) {
- rv = boxes.ElementAt(i)->Find(aType, aOperations);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-nsresult
-DefaultContainerImpl::Write()
-{
- BoxSizeChecker checker(mControl, size);
- Box::Write();
-
- nsresult rv;
- uint32_t len = boxes.Length();
- for (uint32_t i = 0; i < len; i++) {
- rv = boxes.ElementAt(i)->Write();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-DefaultContainerImpl::DefaultContainerImpl(const nsACString& aType,
- ISOControl* aControl)
- : Box(aType, aControl)
-{
-}
-
-nsresult
-Box::Write()
-{
- mControl->Write(size);
- mControl->WriteFourCC(boxType.get());
- return NS_OK;
-}
-
-nsresult
-Box::Find(const nsACString& aType, nsTArray<RefPtr<MuxerOperation>>& aOperations)
-{
- if (boxType == aType) {
- aOperations.AppendElement(this);
- }
- return NS_OK;
-}
-
-Box::Box(const nsACString& aType, ISOControl* aControl)
- : size(8), mControl(aControl)
-{
- MOZ_ASSERT(aType.Length() == 4);
- boxType = aType;
- aControl->GetAudioMetadata(mAudioMeta);
- aControl->GetVideoMetadata(mVideoMeta);
-}
-
-FullBox::FullBox(const nsACString& aType, uint8_t aVersion, uint32_t aFlags,
- ISOControl* aControl)
- : Box(aType, aControl)
-{
- std::bitset<24> tmp_flags(aFlags);
- version = aVersion;
- flags = tmp_flags;
- size += sizeof(version) + flags.size() / CHAR_BIT;
-}
-
-nsresult
-FullBox::Write()
-{
- Box::Write();
- mControl->Write(version);
- mControl->WriteBits(flags.to_ulong(), flags.size());
- return NS_OK;
-}
-
-TrackBox::TrackBox(uint32_t aTrackType, ISOControl* aControl)
- : DefaultContainerImpl(NS_LITERAL_CSTRING("trak"), aControl)
-{
- boxes.AppendElement(new TrackHeaderBox(aTrackType, aControl));
- boxes.AppendElement(new MediaBox(aTrackType, aControl));
- MOZ_COUNT_CTOR(TrackBox);
-}
-
-TrackBox::~TrackBox()
-{
- MOZ_COUNT_DTOR(TrackBox);
-}
-
-SampleEntryBox::SampleEntryBox(const nsACString& aFormat, ISOControl* aControl)
- : Box(aFormat, aControl)
- , data_reference_index(0)
-{
- data_reference_index = 1; // There is only one data reference in each track.
- size += sizeof(reserved) +
- sizeof(data_reference_index);
- memset(reserved, 0, sizeof(reserved));
-}
-
-nsresult
-SampleEntryBox::Write()
-{
- Box::Write();
- mControl->Write(reserved, sizeof(reserved));
- mControl->Write(data_reference_index);
- return NS_OK;
-}
-
-nsresult
-AudioSampleEntry::Write()
-{
- SampleEntryBox::Write();
- mControl->Write(sound_version);
- mControl->Write(reserved2, sizeof(reserved2));
- mControl->Write(channels);
- mControl->Write(sample_size);
- mControl->Write(compressionId);
- mControl->Write(packet_size);
- mControl->Write(timeScale);
- return NS_OK;
-}
-
-AudioSampleEntry::AudioSampleEntry(const nsACString& aFormat, ISOControl* aControl)
- : SampleEntryBox(aFormat, aControl)
- , sound_version(0)
- , channels(2)
- , sample_size(16)
- , compressionId(0)
- , packet_size(0)
- , timeScale(0)
-{
- memset(reserved2, 0 , sizeof(reserved2));
- channels = mAudioMeta->GetAudioChannels();
- timeScale = mAudioMeta->GetAudioSampleRate() << 16;
-
- size += sizeof(sound_version) +
- sizeof(reserved2) +
- sizeof(sample_size) +
- sizeof(channels) +
- sizeof(packet_size) +
- sizeof(compressionId) +
- sizeof(timeScale);
-
- MOZ_COUNT_CTOR(AudioSampleEntry);
-}
-
-AudioSampleEntry::~AudioSampleEntry()
-{
- MOZ_COUNT_DTOR(AudioSampleEntry);
-}
-
-nsresult
-VisualSampleEntry::Write()
-{
- SampleEntryBox::Write();
-
- mControl->Write(reserved, sizeof(reserved));
- mControl->Write(width);
- mControl->Write(height);
- mControl->Write(horizresolution);
- mControl->Write(vertresolution);
- mControl->Write(reserved2);
- mControl->Write(frame_count);
- mControl->Write(compressorName, sizeof(compressorName));
- mControl->Write(depth);
- mControl->Write(pre_defined);
-
- return NS_OK;
-}
-
-VisualSampleEntry::VisualSampleEntry(const nsACString& aFormat, ISOControl* aControl)
- : SampleEntryBox(aFormat, aControl)
- , width(0)
- , height(0)
- , horizresolution(resolution_72_dpi)
- , vertresolution(resolution_72_dpi)
- , reserved2(0)
- , frame_count(1)
- , depth(video_depth)
- , pre_defined(-1)
-{
- memset(reserved, 0 , sizeof(reserved));
- memset(compressorName, 0 , sizeof(compressorName));
-
- // both fields occupy 16 bits defined in 14496-2 6.2.3.
- width = mVideoMeta->GetVideoWidth();
- height = mVideoMeta->GetVideoHeight();
-
- size += sizeof(reserved) +
- sizeof(width) +
- sizeof(height) +
- sizeof(horizresolution) +
- sizeof(vertresolution) +
- sizeof(reserved2) +
- sizeof(frame_count) +
- sizeof(compressorName) +
- sizeof(depth) +
- sizeof(pre_defined);
-
- MOZ_COUNT_CTOR(VisualSampleEntry);
-}
-
-VisualSampleEntry::~VisualSampleEntry()
-{
- MOZ_COUNT_DTOR(VisualSampleEntry);
-}
-
-}
diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h b/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h
deleted file mode 100644
index a6dc1b046..000000000
--- a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h
+++ /dev/null
@@ -1,781 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef ISOMediaBoxes_h_
-#define ISOMediaBoxes_h_
-
-#include <bitset>
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nsAutoPtr.h"
-#include "MuxerOperation.h"
-#include "mozilla/UniquePtr.h"
-
-#define WRITE_FULLBOX(_compositor, _size) \
- BoxSizeChecker checker(_compositor, _size); \
- FullBox::Write();
-
-#define FOURCC(a, b, c, d) ( ((a) << 24) | ((b) << 16) | ((c) << 8) | (d) )
-
-namespace mozilla {
-
-/**
- * track type from spec 8.4.3.3
- */
-#define Audio_Track 0x01
-#define Video_Track 0x02
-
-class AudioTrackMetadata;
-class VideoTrackMetadata;
-class ISOControl;
-
-/**
- * This is the base class for all ISO media format boxes.
- * It provides the fields of box type(four CC) and size.
- * The data members in the beginning of a Box (or its descendants)
- * are the 14496-12 defined member. Other members prefix with 'm'
- * are private control data.
- *
- * This class is for inherited only, it shouldn't be instanced directly.
- */
-class Box : public MuxerOperation {
-protected:
- // ISO BMFF members
- uint32_t size; // 14496-12 4-2 'Object Structure'. Size of this box.
- nsCString boxType; // four CC name, all table names are listed in
- // 14496-12 table 1.
-
-public:
- // MuxerOperation methods
- nsresult Write() override;
- nsresult Find(const nsACString& aType,
- nsTArray<RefPtr<MuxerOperation>>& aOperations) override;
-
- // This helper class will compare the written size in Write() and the size in
- // Generate(). If their are not equal, it will assert.
- class BoxSizeChecker {
- public:
- BoxSizeChecker(ISOControl* aControl, uint32_t aSize);
- ~BoxSizeChecker();
-
- uint32_t ori_size;
- uint32_t box_size;
- ISOControl* mControl;
- };
-
-protected:
- Box() = delete;
- Box(const nsACString& aType, ISOControl* aControl);
-
- ISOControl* mControl;
- RefPtr<AudioTrackMetadata> mAudioMeta;
- RefPtr<VideoTrackMetadata> mVideoMeta;
-};
-
-/**
- * FullBox (and its descendants) is the box which contains the 'real' data
- * members. It is the edge in the ISO box structure and it doesn't contain
- * any box.
- *
- * This class is for inherited only, it shouldn't be instanced directly.
- */
-class FullBox : public Box {
-public:
- // ISO BMFF members
- uint8_t version; // 14496-12 4.2 'Object Structure'
- std::bitset<24> flags; //
-
- // MuxerOperation methods
- nsresult Write() override;
-
-protected:
- // FullBox methods
- FullBox(const nsACString& aType, uint8_t aVersion, uint32_t aFlags,
- ISOControl* aControl);
- FullBox() = delete;
-};
-
-/**
- * The default implementation of the container box.
- * Basically, the container box inherits this class and overrides the
- * constructor only.
- *
- * According to 14496-12 3.1.1 'container box', a container box is
- * 'box whose sole purpose is to contain and group a set of related boxes'
- *
- * This class is for inherited only, it shouldn't be instanced directly.
- */
-class DefaultContainerImpl : public Box {
-public:
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
- nsresult Find(const nsACString& aType,
- nsTArray<RefPtr<MuxerOperation>>& aOperations) override;
-
-protected:
- // DefaultContainerImpl methods
- DefaultContainerImpl(const nsACString& aType, ISOControl* aControl);
- DefaultContainerImpl() = delete;
-
- nsTArray<RefPtr<MuxerOperation>> boxes;
-};
-
-// 14496-12 4.3 'File Type Box'
-// Box type: 'ftyp'
-class FileTypeBox : public Box {
-public:
- // ISO BMFF members
- nsCString major_brand; // four chars
- uint32_t minor_version;
- nsTArray<nsCString> compatible_brands;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // FileTypeBox methods
- FileTypeBox(ISOControl* aControl);
- ~FileTypeBox();
-};
-
-// 14496-12 8.2.1 'Movie Box'
-// Box type: 'moov'
-// MovieBox contains MovieHeaderBox, TrackBox and MovieExtendsBox.
-class MovieBox : public DefaultContainerImpl {
-public:
- MovieBox(ISOControl* aControl);
- ~MovieBox();
-};
-
-// 14496-12 8.2.2 'Movie Header Box'
-// Box type: 'mvhd'
-class MovieHeaderBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t creation_time;
- uint32_t modification_time;
- uint32_t timescale;
- uint32_t duration;
- uint32_t rate;
- uint16_t volume;
- uint16_t reserved16;
- uint32_t reserved32[2];
- uint32_t matrix[9];
- uint32_t pre_defined[6];
- uint32_t next_track_ID;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // MovieHeaderBox methods
- MovieHeaderBox(ISOControl* aControl);
- ~MovieHeaderBox();
- uint32_t GetTimeScale();
-};
-
-// 14496-12 8.4.2 'Media Header Box'
-// Box type: 'mdhd'
-class MediaHeaderBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t creation_time;
- uint32_t modification_time;
- uint32_t timescale;
- uint32_t duration;
- std::bitset<1> pad;
- std::bitset<5> lang1;
- std::bitset<5> lang2;
- std::bitset<5> lang3;
- uint16_t pre_defined;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // MediaHeaderBox methods
- MediaHeaderBox(uint32_t aType, ISOControl* aControl);
- ~MediaHeaderBox();
- uint32_t GetTimeScale();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.3.1 'Track Box'
-// Box type: 'trak'
-// TrackBox contains TrackHeaderBox and MediaBox.
-class TrackBox : public DefaultContainerImpl {
-public:
- TrackBox(uint32_t aTrackType, ISOControl* aControl);
- ~TrackBox();
-};
-
-// 14496-12 8.1.1 'Media Data Box'
-// Box type: 'mdat'
-class MediaDataBox : public Box {
-public:
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // MediaDataBox methods
- uint32_t GetAllSampleSize() { return mAllSampleSize; }
- uint32_t FirstSampleOffsetInMediaDataBox() { return mFirstSampleOffset; }
- MediaDataBox(uint32_t aTrackType, ISOControl* aControl);
- ~MediaDataBox();
-
-protected:
- uint32_t mAllSampleSize; // All audio and video sample size in this box.
- uint32_t mFirstSampleOffset; // The offset of first sample in this box from
- // the beginning of this mp4 file.
- uint32_t mTrackType;
-};
-
-// flags for TrackRunBox::flags, 14496-12 8.8.8.1.
-#define flags_data_offset_present 0x000001
-#define flags_first_sample_flags_present 0x000002
-#define flags_sample_duration_present 0x000100
-#define flags_sample_size_present 0x000200
-#define flags_sample_flags_present 0x000400
-#define flags_sample_composition_time_offsets_present 0x000800
-
-// flag for TrackRunBox::tbl::sample_flags and TrackExtendsBox::default_sample_flags
-// which is defined in 14496-12 8.8.3.1.
-uint32_t set_sample_flags(bool aSync);
-
-// 14496-12 8.8.8 'Track Fragment Run Box'
-// Box type: 'trun'
-class TrackRunBox : public FullBox {
-public:
- // ISO BMFF members
- typedef struct {
- uint32_t sample_duration;
- uint32_t sample_size;
- uint32_t sample_flags;
- uint32_t sample_composition_time_offset;
- } tbl;
-
- uint32_t sample_count;
- // the following are optional fields
- uint32_t data_offset; // data offset exists when audio/video are present in file.
- uint32_t first_sample_flags;
- UniquePtr<tbl[]> sample_info_table;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // TrackRunBox methods
- uint32_t GetAllSampleSize() { return mAllSampleSize; }
- nsresult SetDataOffset(uint32_t aOffset);
-
- TrackRunBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl);
- ~TrackRunBox();
-
-protected:
- uint32_t fillSampleTable();
-
- uint32_t mAllSampleSize;
- uint32_t mTrackType;
-};
-
-// tf_flags in TrackFragmentHeaderBox, 14496-12 8.8.7.1.
-#define base_data_offset_present 0x000001
-#define sample_description_index_present 0x000002
-#define default_sample_duration_present 0x000008
-#define default_sample_size_present 0x000010
-#define default_sample_flags_present 0x000020
-#define duration_is_empty 0x010000
-#define default_base_is_moof 0x020000
-
-// 14496-12 8.8.7 'Track Fragment Header Box'
-// Box type: 'tfhd'
-class TrackFragmentHeaderBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t track_ID;
- uint64_t base_data_offset;
- uint32_t default_sample_duration;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // TrackFragmentHeaderBox methods
- nsresult UpdateBaseDataOffset(uint64_t aOffset); // The offset of the first
- // sample in file.
-
- TrackFragmentHeaderBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl);
- ~TrackFragmentHeaderBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.8.6 'Track Fragment Box'
-// Box type: 'traf'
-// TrackFragmentBox cotains TrackFragmentHeaderBox and TrackRunBox.
-class TrackFragmentBox : public DefaultContainerImpl {
-public:
- TrackFragmentBox(uint32_t aType, ISOControl* aControl);
- ~TrackFragmentBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.8.5 'Movie Fragment Header Box'
-// Box type: 'mfhd'
-class MovieFragmentHeaderBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t sequence_number;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // MovieFragmentHeaderBox methods
- MovieFragmentHeaderBox(uint32_t aType, ISOControl* aControl);
- ~MovieFragmentHeaderBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.8.4 'Movie Fragment Box'
-// Box type: 'moof'
-// MovieFragmentBox contains MovieFragmentHeaderBox and TrackFragmentBox.
-class MovieFragmentBox : public DefaultContainerImpl {
-public:
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
-
- // MovieFragmentBox methods
- MovieFragmentBox(uint32_t aType, ISOControl* aControl);
- ~MovieFragmentBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.8.3 'Track Extends Box'
-// Box type: 'trex'
-class TrackExtendsBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t track_ID;
- uint32_t default_sample_description_index;
- uint32_t default_sample_duration;
- uint32_t default_sample_size;
- uint32_t default_sample_flags;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // TrackExtendsBox methods
- TrackExtendsBox(uint32_t aType, ISOControl* aControl);
- ~TrackExtendsBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.8.1 'Movie Extends Box'
-// Box type: 'mvex'
-// MovieExtendsBox contains TrackExtendsBox.
-class MovieExtendsBox : public DefaultContainerImpl {
-public:
- MovieExtendsBox(ISOControl* aControl);
- ~MovieExtendsBox();
-};
-
-// 14496-12 8.7.5 'Chunk Offset Box'
-// Box type: 'stco'
-class ChunkOffsetBox : public FullBox {
-public:
- // ISO BMFF members
- typedef struct {
- uint32_t chunk_offset;
- } tbl;
-
- uint32_t entry_count;
- UniquePtr<tbl[]> sample_tbl;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // ChunkOffsetBox methods
- ChunkOffsetBox(uint32_t aType, ISOControl* aControl);
- ~ChunkOffsetBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.7.4 'Sample To Chunk Box'
-// Box type: 'stsc'
-class SampleToChunkBox : public FullBox {
-public:
- // ISO BMFF members
- typedef struct {
- uint32_t first_chunk;
- uint32_t sample_per_chunk;
- uint32_t sample_description_index;
- } tbl;
-
- uint32_t entry_count;
- UniquePtr<tbl[]> sample_tbl;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // SampleToChunkBox methods
- SampleToChunkBox(uint32_t aType, ISOControl* aControl);
- ~SampleToChunkBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.6.1.2 'Decoding Time to Sample Box'
-// Box type: 'stts'
-class TimeToSampleBox : public FullBox {
-public:
- // ISO BMFF members
- typedef struct {
- uint32_t sample_count;
- uint32_t sample_delta;
- } tbl;
-
- uint32_t entry_count;
- UniquePtr<tbl[]> sample_tbl;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // TimeToSampleBox methods
- TimeToSampleBox(uint32_t aType, ISOControl* aControl);
- ~TimeToSampleBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-/**
- * 14496-12 8.5.2 'Sample Description Box'
- * This is the base class for VisualSampleEntry and AudioSampleEntry.
- *
- * This class is for inherited only, it shouldn't be instanced directly.
- *
- * The inhertied tree of a codec box should be:
- *
- * +--> AVCSampleEntry
- * +--> VisualSampleEntryBox +
- * | +--> ...
- * SampleEntryBox +
- * | +--> MP4AudioSampleEntry
- * +--> AudioSampleEntryBox +
- * +--> AMRSampleEntry
- * +
- * +--> ...
- *
- */
-class SampleEntryBox : public Box {
-public:
- // ISO BMFF members
- uint8_t reserved[6];
- uint16_t data_reference_index;
-
- // sampleentrybox methods
- SampleEntryBox(const nsACString& aFormat, ISOControl* aControl);
-
- // MuxerOperation methods
- nsresult Write() override;
-
-protected:
- SampleEntryBox() = delete;
-};
-
-// 14496-12 8.5.2 'Sample Description Box'
-// Box type: 'stsd'
-class SampleDescriptionBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t entry_count;
- RefPtr<SampleEntryBox> sample_entry_box;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // SampleDescriptionBox methods
- SampleDescriptionBox(uint32_t aType, ISOControl* aControl);
- ~SampleDescriptionBox();
-
-protected:
- nsresult CreateAudioSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry);
- nsresult CreateVideoSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry);
-
- uint32_t mTrackType;
-};
-
-// 14496-12 8.5.2.2
-// The base class for audio codec box.
-// This class is for inherited only, it shouldn't be instanced directly.
-class AudioSampleEntry : public SampleEntryBox {
-public:
- // ISO BMFF members
- uint16_t sound_version;
- uint8_t reserved2[6];
- uint16_t channels;
- uint16_t sample_size;
- uint16_t compressionId;
- uint16_t packet_size;
- uint32_t timeScale; // (sample rate of media) <<16
-
- // MuxerOperation methods
- nsresult Write() override;
-
- ~AudioSampleEntry();
-
-protected:
- AudioSampleEntry(const nsACString& aFormat, ISOControl* aControl);
-};
-
-// 14496-12 8.5.2.2
-// The base class for video codec box.
-// This class is for inherited only, it shouldn't be instanced directly.
-class VisualSampleEntry : public SampleEntryBox {
-public:
- // ISO BMFF members
- uint8_t reserved[16];
- uint16_t width;
- uint16_t height;
-
- uint32_t horizresolution; // 72 dpi
- uint32_t vertresolution; // 72 dpi
- uint32_t reserved2;
- uint16_t frame_count; // 1, defined in 14496-12 8.5.2.2
-
- uint8_t compressorName[32];
- uint16_t depth; // 0x0018, defined in 14496-12 8.5.2.2;
- uint16_t pre_defined; // -1, defined in 14496-12 8.5.2.2;
-
- // MuxerOperation methods
- nsresult Write() override;
-
- // VisualSampleEntry methods
- ~VisualSampleEntry();
-
-protected:
- VisualSampleEntry(const nsACString& aFormat, ISOControl* aControl);
-};
-
-// 14496-12 8.7.3.2 'Sample Size Box'
-// Box type: 'stsz'
-class SampleSizeBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t sample_size;
- uint32_t sample_count;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // SampleSizeBox methods
- SampleSizeBox(ISOControl* aControl);
- ~SampleSizeBox();
-};
-
-// 14496-12 8.5.1 'Sample Table Box'
-// Box type: 'stbl'
-//
-// SampleTableBox contains SampleDescriptionBox,
-// TimeToSampleBox,
-// SampleToChunkBox,
-// SampleSizeBox and
-// ChunkOffsetBox.
-class SampleTableBox : public DefaultContainerImpl {
-public:
- SampleTableBox(uint32_t aType, ISOControl* aControl);
- ~SampleTableBox();
-};
-
-// 14496-12 8.7.2 'Data Reference Box'
-// Box type: 'url '
-class DataEntryUrlBox : public FullBox {
-public:
- // ISO BMFF members
- // flags in DataEntryUrlBox::flags
- const static uint16_t flags_media_at_the_same_file = 0x0001;
-
- nsCString location;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // DataEntryUrlBox methods
- DataEntryUrlBox();
- DataEntryUrlBox(ISOControl* aControl);
- DataEntryUrlBox(const DataEntryUrlBox& aBox);
- ~DataEntryUrlBox();
-};
-
-// 14496-12 8.7.2 'Data Reference Box'
-// Box type: 'dref'
-class DataReferenceBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t entry_count;
- nsTArray<nsAutoPtr<DataEntryUrlBox>> urls;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // DataReferenceBox methods
- DataReferenceBox(ISOControl* aControl);
- ~DataReferenceBox();
-};
-
-// 14496-12 8.7.1 'Data Information Box'
-// Box type: 'dinf'
-// DataInformationBox contains DataReferenceBox.
-class DataInformationBox : public DefaultContainerImpl {
-public:
- DataInformationBox(ISOControl* aControl);
- ~DataInformationBox();
-};
-
-// 14496-12 8.4.5.2 'Video Media Header Box'
-// Box type: 'vmhd'
-class VideoMediaHeaderBox : public FullBox {
-public:
- // ISO BMFF members
- uint16_t graphicsmode;
- uint16_t opcolor[3];
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // VideoMediaHeaderBox methods
- VideoMediaHeaderBox(ISOControl* aControl);
- ~VideoMediaHeaderBox();
-};
-
-// 14496-12 8.4.5.3 'Sound Media Header Box'
-// Box type: 'smhd'
-class SoundMediaHeaderBox : public FullBox {
-public:
- // ISO BMFF members
- uint16_t balance;
- uint16_t reserved;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // SoundMediaHeaderBox methods
- SoundMediaHeaderBox(ISOControl* aControl);
- ~SoundMediaHeaderBox();
-};
-
-// 14496-12 8.4.4 'Media Information Box'
-// Box type: 'minf'
-// MediaInformationBox contains SoundMediaHeaderBox, DataInformationBox and
-// SampleTableBox.
-class MediaInformationBox : public DefaultContainerImpl {
-public:
- MediaInformationBox(uint32_t aType, ISOControl* aControl);
- ~MediaInformationBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// flags for TrackHeaderBox::flags.
-#define flags_track_enabled 0x000001
-#define flags_track_in_movie 0x000002
-#define flags_track_in_preview 0x000004
-
-// 14496-12 8.3.2 'Track Header Box'
-// Box type: 'tkhd'
-class TrackHeaderBox : public FullBox {
-public:
- // ISO BMFF members
- // version = 0
- uint32_t creation_time;
- uint32_t modification_time;
- uint32_t track_ID;
- uint32_t reserved;
- uint32_t duration;
-
- uint32_t reserved2[2];
- uint16_t layer;
- uint16_t alternate_group;
- uint16_t volume;
- uint16_t reserved3;
- uint32_t matrix[9];
- uint32_t width;
- uint32_t height;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // TrackHeaderBox methods
- TrackHeaderBox(uint32_t aType, ISOControl* aControl);
- ~TrackHeaderBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.4.3 'Handler Reference Box'
-// Box type: 'hdlr'
-class HandlerBox : public FullBox {
-public:
- // ISO BMFF members
- uint32_t pre_defined;
- uint32_t handler_type;
- uint32_t reserved[3];
- nsCString name;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // HandlerBox methods
- HandlerBox(uint32_t aType, ISOControl* aControl);
- ~HandlerBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-// 14496-12 8.4.1 'Media Box'
-// Box type: 'mdia'
-// MediaBox contains MediaHeaderBox, HandlerBox, and MediaInformationBox.
-class MediaBox : public DefaultContainerImpl {
-public:
- MediaBox(uint32_t aType, ISOControl* aControl);
- ~MediaBox();
-
-protected:
- uint32_t mTrackType;
-};
-
-}
-#endif // ISOMediaBoxes_h_
diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaWriter.cpp b/dom/media/encoder/fmp4_muxer/ISOMediaWriter.cpp
deleted file mode 100644
index fa23616e9..000000000
--- a/dom/media/encoder/fmp4_muxer/ISOMediaWriter.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ISOMediaWriter.h"
-#include "ISOControl.h"
-#include "ISOMediaBoxes.h"
-#include "ISOTrackMetadata.h"
-#include "nsThreadUtils.h"
-#include "MediaEncoder.h"
-#include "VideoUtils.h"
-#include "GeckoProfiler.h"
-
-#undef LOG
-#ifdef MOZ_WIDGET_GONK
-#include <android/log.h>
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args);
-#else
-#define LOG(args, ...)
-#endif
-
-namespace mozilla {
-
-const static uint32_t FRAG_DURATION = 2 * USECS_PER_S; // microsecond per unit
-
-ISOMediaWriter::ISOMediaWriter(uint32_t aType, uint32_t aHint)
- : ContainerWriter()
- , mState(MUXING_HEAD)
- , mBlobReady(false)
- , mType(0)
-{
- if (aType & CREATE_AUDIO_TRACK) {
- mType |= Audio_Track;
- }
- if (aType & CREATE_VIDEO_TRACK) {
- mType |= Video_Track;
- }
- mControl = new ISOControl(aHint);
- MOZ_COUNT_CTOR(ISOMediaWriter);
-}
-
-ISOMediaWriter::~ISOMediaWriter()
-{
- MOZ_COUNT_DTOR(ISOMediaWriter);
-}
-
-nsresult
-ISOMediaWriter::RunState()
-{
- nsresult rv;
- switch (mState) {
- case MUXING_HEAD:
- {
- rv = mControl->GenerateFtyp();
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mControl->GenerateMoov();
- NS_ENSURE_SUCCESS(rv, rv);
- mState = MUXING_FRAG;
- break;
- }
- case MUXING_FRAG:
- {
- rv = mControl->GenerateMoof(mType);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool EOS;
- if (ReadyToRunState(EOS) && EOS) {
- mState = MUXING_DONE;
- }
- break;
- }
- case MUXING_DONE:
- {
- break;
- }
- }
- mBlobReady = true;
- return NS_OK;
-}
-
-nsresult
-ISOMediaWriter::WriteEncodedTrack(const EncodedFrameContainer& aData,
- uint32_t aFlags)
-{
- PROFILER_LABEL("ISOMediaWriter", "WriteEncodedTrack",
- js::ProfileEntry::Category::OTHER);
- // Muxing complete, it doesn't allowed to reentry again.
- if (mState == MUXING_DONE) {
- MOZ_ASSERT(false);
- return NS_ERROR_FAILURE;
- }
-
- FragmentBuffer* frag = nullptr;
- uint32_t len = aData.GetEncodedFrames().Length();
-
- if (!len) {
- // no frame? why bother to WriteEncodedTrack
- return NS_OK;
- }
- for (uint32_t i = 0; i < len; i++) {
- RefPtr<EncodedFrame> frame(aData.GetEncodedFrames()[i]);
- EncodedFrame::FrameType type = frame->GetFrameType();
- if (type == EncodedFrame::AAC_AUDIO_FRAME ||
- type == EncodedFrame::AAC_CSD ||
- type == EncodedFrame::AMR_AUDIO_FRAME ||
- type == EncodedFrame::AMR_AUDIO_CSD ||
- type == EncodedFrame::EVRC_AUDIO_FRAME ||
- type == EncodedFrame::EVRC_AUDIO_CSD) {
- frag = mAudioFragmentBuffer;
- } else if (type == EncodedFrame::AVC_I_FRAME ||
- type == EncodedFrame::AVC_P_FRAME ||
- type == EncodedFrame::AVC_B_FRAME ||
- type == EncodedFrame::AVC_CSD) {
- frag = mVideoFragmentBuffer;
- } else {
- MOZ_ASSERT(0);
- return NS_ERROR_FAILURE;
- }
-
- frag->AddFrame(frame);
- }
-
- // Encoder should send CSD (codec specific data) frame before sending the
- // audio/video frames. When CSD data is ready, it is sufficient to generate a
- // moov data. If encoder doesn't send CSD yet, muxer needs to wait before
- // generating anything.
- if (mType & Audio_Track && (!mAudioFragmentBuffer ||
- !mAudioFragmentBuffer->HasCSD())) {
- return NS_OK;
- }
- if (mType & Video_Track && (!mVideoFragmentBuffer ||
- !mVideoFragmentBuffer->HasCSD())) {
- return NS_OK;
- }
-
- // Only one FrameType in EncodedFrameContainer so it doesn't need to be
- // inside the for-loop.
- if (frag && (aFlags & END_OF_STREAM)) {
- frag->SetEndOfStream();
- }
-
- nsresult rv;
- bool EOS;
- if (ReadyToRunState(EOS)) {
- // Because track encoder won't generate new data after EOS, it needs to make
- // sure the state reaches MUXING_DONE when EOS is signaled.
- do {
- rv = RunState();
- } while (EOS && mState != MUXING_DONE);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-bool
-ISOMediaWriter::ReadyToRunState(bool& aEOS)
-{
- aEOS = false;
- bool bReadyToMux = true;
- if ((mType & Audio_Track) && (mType & Video_Track)) {
- if (!mAudioFragmentBuffer->HasEnoughData()) {
- bReadyToMux = false;
- }
- if (!mVideoFragmentBuffer->HasEnoughData()) {
- bReadyToMux = false;
- }
-
- if (mAudioFragmentBuffer->EOS() && mVideoFragmentBuffer->EOS()) {
- aEOS = true;
- bReadyToMux = true;
- }
- } else if (mType == Audio_Track) {
- if (!mAudioFragmentBuffer->HasEnoughData()) {
- bReadyToMux = false;
- }
- if (mAudioFragmentBuffer->EOS()) {
- aEOS = true;
- bReadyToMux = true;
- }
- } else if (mType == Video_Track) {
- if (!mVideoFragmentBuffer->HasEnoughData()) {
- bReadyToMux = false;
- }
- if (mVideoFragmentBuffer->EOS()) {
- aEOS = true;
- bReadyToMux = true;
- }
- }
-
- return bReadyToMux;
-}
-
-nsresult
-ISOMediaWriter::GetContainerData(nsTArray<nsTArray<uint8_t>>* aOutputBufs,
- uint32_t aFlags)
-{
- PROFILER_LABEL("ISOMediaWriter", "GetContainerData",
- js::ProfileEntry::Category::OTHER);
- if (mBlobReady) {
- if (mState == MUXING_DONE) {
- mIsWritingComplete = true;
- }
- mBlobReady = false;
- return mControl->GetBufs(aOutputBufs);
- }
- return NS_OK;
-}
-
-nsresult
-ISOMediaWriter::SetMetadata(TrackMetadataBase* aMetadata)
-{
- PROFILER_LABEL("ISOMediaWriter", "SetMetadata",
- js::ProfileEntry::Category::OTHER);
- if (aMetadata->GetKind() == TrackMetadataBase::METADATA_AAC ||
- aMetadata->GetKind() == TrackMetadataBase::METADATA_AMR ||
- aMetadata->GetKind() == TrackMetadataBase::METADATA_EVRC) {
- mControl->SetMetadata(aMetadata);
- mAudioFragmentBuffer = new FragmentBuffer(Audio_Track, FRAG_DURATION);
- mControl->SetFragment(mAudioFragmentBuffer);
- return NS_OK;
- }
- if (aMetadata->GetKind() == TrackMetadataBase::METADATA_AVC) {
- mControl->SetMetadata(aMetadata);
- mVideoFragmentBuffer = new FragmentBuffer(Video_Track, FRAG_DURATION);
- mControl->SetFragment(mVideoFragmentBuffer);
- return NS_OK;
- }
-
- return NS_ERROR_FAILURE;
-}
-
-} // namespace mozilla
diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaWriter.h b/dom/media/encoder/fmp4_muxer/ISOMediaWriter.h
deleted file mode 100644
index cccbbe3cb..000000000
--- a/dom/media/encoder/fmp4_muxer/ISOMediaWriter.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef ISOMediaWriter_h_
-#define ISOMediaWriter_h_
-
-#include "ContainerWriter.h"
-#include "nsAutoPtr.h"
-#include "nsIRunnable.h"
-
-namespace mozilla {
-
-class ISOControl;
-class FragmentBuffer;
-
-class ISOMediaWriter : public ContainerWriter
-{
-public:
- // Generate an fragmented MP4 stream, ISO/IEC 14496-12.
- // Brand names in 'ftyp' box are 'isom' and 'mp42'.
- const static uint32_t TYPE_FRAG_MP4 = 1 << 0;
-
- // Generate an fragmented 3GP stream, 3GPP TS 26.244,
- // '5.4.3 Basic profile'.
- // Brand names in 'ftyp' box are '3gp9' and 'isom'.
- const static uint32_t TYPE_FRAG_3GP = 1 << 1;
-
- // Generate an fragmented 3G2 stream, 3GPP2 C.S0050-B
- // Brand names in 'ftyp' box are '3g2c' and 'isom'
- const static uint32_t TYPE_FRAG_3G2 = 1 << 2;
-
- // aType is the combination of CREATE_AUDIO_TRACK and CREATE_VIDEO_TRACK.
- // It is a hint to muxer that the output streaming contains audio, video
- // or both.
- //
- // aHint is one of the value in TYPE_XXXXXXXX. It is a hint to muxer what kind
- // of ISO format should be generated.
- ISOMediaWriter(uint32_t aType, uint32_t aHint = TYPE_FRAG_MP4);
- ~ISOMediaWriter();
-
- // ContainerWriter methods
- nsresult WriteEncodedTrack(const EncodedFrameContainer &aData,
- uint32_t aFlags = 0) override;
-
- nsresult GetContainerData(nsTArray<nsTArray<uint8_t>>* aOutputBufs,
- uint32_t aFlags = 0) override;
-
- nsresult SetMetadata(TrackMetadataBase* aMetadata) override;
-
-protected:
- /**
- * The state of each state will generate one or more blob.
- * Each blob will be a moov, moof, moof... until receiving EOS.
- * The generated sequence is:
- *
- * moov -> moof -> moof -> ... -> moof -> moof
- *
- * Following is the details of each state.
- * MUXING_HEAD:
- * It collects the metadata to generate a moov. The state transits to
- * MUXING_HEAD after output moov blob.
- *
- * MUXING_FRAG:
- * It collects enough audio/video data to generate a fragment blob. This
- * will be repeated until END_OF_STREAM and then transiting to MUXING_DONE.
- *
- * MUXING_DONE:
- * End of ISOMediaWriter life cycle.
- */
- enum MuxState {
- MUXING_HEAD,
- MUXING_FRAG,
- MUXING_DONE,
- };
-
-private:
- nsresult RunState();
-
- // True if one of following conditions hold:
- // 1. Audio/Video accumulates enough data to generate a moof.
- // 2. Get EOS signal.
- // aEOS will be assigned to true if it gets EOS signal.
- bool ReadyToRunState(bool& aEOS);
-
- // The main class to generate and iso box. Its life time is same as
- // ISOMediaWriter and deleted only if ISOMediaWriter is destroyed.
- nsAutoPtr<ISOControl> mControl;
-
- // Buffers to keep audio/video data frames, they are created when metadata is
- // received. Only one instance for each media type is allowed and they will be
- // deleted only if ISOMediaWriter is destroyed.
- nsAutoPtr<FragmentBuffer> mAudioFragmentBuffer;
- nsAutoPtr<FragmentBuffer> mVideoFragmentBuffer;
-
- MuxState mState;
-
- // A flag to indicate the output buffer is ready to blob out.
- bool mBlobReady;
-
- // Combination of Audio_Track or Video_Track.
- uint32_t mType;
-};
-
-} // namespace mozilla
-
-#endif // ISOMediaWriter_h_
diff --git a/dom/media/encoder/fmp4_muxer/ISOTrackMetadata.h b/dom/media/encoder/fmp4_muxer/ISOTrackMetadata.h
deleted file mode 100644
index 3613e1e9e..000000000
--- a/dom/media/encoder/fmp4_muxer/ISOTrackMetadata.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef ISOTrackMetadata_h_
-#define ISOTrackMetadata_h_
-
-#include "TrackMetadataBase.h"
-
-namespace mozilla {
-
-class AACTrackMetadata : public AudioTrackMetadata {
-public:
- // AudioTrackMetadata members
- uint32_t GetAudioFrameDuration() override { return mFrameDuration; }
- uint32_t GetAudioFrameSize() override { return mFrameSize; }
- uint32_t GetAudioSampleRate() override { return mSampleRate; }
- uint32_t GetAudioChannels() override { return mChannels; }
-
- // TrackMetadataBase member
- MetadataKind GetKind() const override { return METADATA_AAC; }
-
- // AACTrackMetadata members
- AACTrackMetadata()
- : mSampleRate(0)
- , mFrameDuration(0)
- , mFrameSize(0)
- , mChannels(0) {
- MOZ_COUNT_CTOR(AACTrackMetadata);
- }
- ~AACTrackMetadata() { MOZ_COUNT_DTOR(AACTrackMetadata); }
-
- uint32_t mSampleRate; // From 14496-3 table 1.16, it could be 7350 ~ 96000.
- uint32_t mFrameDuration; // Audio frame duration based on SampleRate.
- uint32_t mFrameSize; // Audio frame size, 0 is variant size.
- uint32_t mChannels; // Channel number, it should be 1 or 2.
-};
-
-// AVC clock rate is 90k Hz.
-#define AVC_CLOCK_RATE 90000
-
-class AVCTrackMetadata : public VideoTrackMetadata {
-public:
- // VideoTrackMetadata members
- uint32_t GetVideoHeight() override { return mHeight; }
- uint32_t GetVideoWidth() override {return mWidth; }
- uint32_t GetVideoDisplayHeight() override { return mDisplayHeight; }
- uint32_t GetVideoDisplayWidth() override { return mDisplayWidth; }
- uint32_t GetVideoClockRate() override { return AVC_CLOCK_RATE; }
- uint32_t GetVideoFrameRate() override { return mFrameRate; }
-
- // TrackMetadataBase member
- MetadataKind GetKind() const override { return METADATA_AVC; }
-
- // AVCTrackMetadata
- AVCTrackMetadata()
- : mHeight(0)
- , mWidth(0)
- , mDisplayHeight(0)
- , mDisplayWidth(0)
- , mFrameRate(0) {
- MOZ_COUNT_CTOR(AVCTrackMetadata);
- }
- ~AVCTrackMetadata() { MOZ_COUNT_DTOR(AVCTrackMetadata); }
-
- uint32_t mHeight;
- uint32_t mWidth;
- uint32_t mDisplayHeight;
- uint32_t mDisplayWidth;
- uint32_t mFrameRate; // frames per second
-};
-
-
-// AMR sample rate is 8000 samples/s.
-#define AMR_SAMPLE_RATE 8000
-
-// Channel number is always 1.
-#define AMR_CHANNELS 1
-
-// AMR speech codec, 3GPP TS 26.071. Encoder and continer support AMR-NB only
-// currently.
-class AMRTrackMetadata : public AudioTrackMetadata {
-public:
- // AudioTrackMetadata members
- //
- // The number of sample sets generates by encoder is variant. So the
- // frame duration and frame size are both 0.
- uint32_t GetAudioFrameDuration() override { return 0; }
- uint32_t GetAudioFrameSize() override { return 0; }
- uint32_t GetAudioSampleRate() override { return AMR_SAMPLE_RATE; }
- uint32_t GetAudioChannels() override { return AMR_CHANNELS; }
-
- // TrackMetadataBase member
- MetadataKind GetKind() const override { return METADATA_AMR; }
-
- // AMRTrackMetadata members
- AMRTrackMetadata() { MOZ_COUNT_CTOR(AMRTrackMetadata); }
- ~AMRTrackMetadata() { MOZ_COUNT_DTOR(AMRTrackMetadata); }
-};
-
-// EVRC sample rate is 8000 samples/s.
-#define EVRC_SAMPLE_RATE 8000
-
-class EVRCTrackMetadata : public AudioTrackMetadata {
-public:
- // AudioTrackMetadata members
- //
- // The number of sample sets generates by encoder is variant. So the
- // frame duration and frame size are both 0.
- uint32_t GetAudioFrameDuration() override { return 0; }
- uint32_t GetAudioFrameSize() override { return 0; }
- uint32_t GetAudioSampleRate() override { return EVRC_SAMPLE_RATE; }
- uint32_t GetAudioChannels() override { return mChannels; }
-
- // TrackMetadataBase member
- MetadataKind GetKind() const override { return METADATA_EVRC; }
-
- // EVRCTrackMetadata members
- EVRCTrackMetadata()
- : mChannels(0) {
- MOZ_COUNT_CTOR(EVRCTrackMetadata);
- }
- ~EVRCTrackMetadata() { MOZ_COUNT_DTOR(EVRCTrackMetadata); }
-
- uint32_t mChannels; // Channel number, it should be 1 or 2.
-};
-
-}
-
-#endif // ISOTrackMetadata_h_
diff --git a/dom/media/encoder/fmp4_muxer/MP4ESDS.cpp b/dom/media/encoder/fmp4_muxer/MP4ESDS.cpp
deleted file mode 100644
index 72880b5cb..000000000
--- a/dom/media/encoder/fmp4_muxer/MP4ESDS.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <climits>
-#include "ISOControl.h"
-#include "ISOMediaBoxes.h"
-#include "MP4ESDS.h"
-
-namespace mozilla {
-
-nsresult
-MP4AudioSampleEntry::Generate(uint32_t* aBoxSize)
-{
- uint32_t box_size;
- nsresult rv = es->Generate(&box_size);
- NS_ENSURE_SUCCESS(rv, rv);
- size += box_size;
-
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-MP4AudioSampleEntry::Write()
-{
- BoxSizeChecker checker(mControl, size);
- nsresult rv;
- rv = AudioSampleEntry::Write();
- NS_ENSURE_SUCCESS(rv, rv);
- rv = es->Write();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-MP4AudioSampleEntry::MP4AudioSampleEntry(ISOControl* aControl)
- : AudioSampleEntry(NS_LITERAL_CSTRING("mp4a"), aControl)
-{
- es = new ESDBox(aControl);
- MOZ_COUNT_CTOR(MP4AudioSampleEntry);
-}
-
-MP4AudioSampleEntry::~MP4AudioSampleEntry()
-{
- MOZ_COUNT_DTOR(MP4AudioSampleEntry);
-}
-
-nsresult
-ESDBox::Generate(uint32_t* aBoxSize)
-{
- uint32_t box_size;
- es_descriptor->Generate(&box_size);
- size += box_size;
- *aBoxSize = size;
- return NS_OK;
-}
-
-nsresult
-ESDBox::Write()
-{
- WRITE_FULLBOX(mControl, size)
- es_descriptor->Write();
- return NS_OK;
-}
-
-ESDBox::ESDBox(ISOControl* aControl)
- : FullBox(NS_LITERAL_CSTRING("esds"), 0, 0, aControl)
-{
- es_descriptor = new ES_Descriptor(aControl);
- MOZ_COUNT_CTOR(ESDBox);
-}
-
-ESDBox::~ESDBox()
-{
- MOZ_COUNT_DTOR(ESDBox);
-}
-
-nsresult
-ES_Descriptor::Find(const nsACString& aType,
- nsTArray<RefPtr<MuxerOperation>>& aOperations)
-{
- // ES_Descriptor is not a real ISOMediaBox, so we return nothing here.
- return NS_OK;
-}
-
-nsresult
-ES_Descriptor::Write()
-{
- mControl->Write(tag);
- mControl->Write(length);
- mControl->Write(ES_ID);
- mControl->WriteBits(streamDependenceFlag.to_ulong(), streamDependenceFlag.size());
- mControl->WriteBits(URL_Flag.to_ulong(), URL_Flag.size());
- mControl->WriteBits(reserved.to_ulong(), reserved.size());
- mControl->WriteBits(streamPriority.to_ulong(), streamPriority.size());
- mControl->Write(DecodeSpecificInfo.Elements(), DecodeSpecificInfo.Length());
-
- return NS_OK;
-}
-
-nsresult
-ES_Descriptor::Generate(uint32_t* aBoxSize)
-{
- nsresult rv;
- // 14496-1 '8.3.4 DecoderConfigDescriptor'
- // 14496-1 '10.2.3 SL Packet Header Configuration'
- FragmentBuffer* frag = mControl->GetFragment(Audio_Track);
- rv = frag->GetCSD(DecodeSpecificInfo);
- NS_ENSURE_SUCCESS(rv, rv);
-
- length = sizeof(ES_ID) + 1;
- length += DecodeSpecificInfo.Length();
-
- *aBoxSize = sizeof(tag) + sizeof(length) + length;
- return NS_OK;
-}
-
-ES_Descriptor::ES_Descriptor(ISOControl* aControl)
- : tag(ESDescrTag)
- , length(0)
- , ES_ID(0)
- , streamDependenceFlag(0)
- , URL_Flag(0)
- , reserved(0)
- , streamPriority(0)
- , mControl(aControl)
-{
- MOZ_COUNT_CTOR(ES_Descriptor);
-}
-
-ES_Descriptor::~ES_Descriptor()
-{
- MOZ_COUNT_DTOR(ES_Descriptor);
-}
-
-}
diff --git a/dom/media/encoder/fmp4_muxer/MP4ESDS.h b/dom/media/encoder/fmp4_muxer/MP4ESDS.h
deleted file mode 100644
index ee91312c1..000000000
--- a/dom/media/encoder/fmp4_muxer/MP4ESDS.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef MP4ESDS_h_
-#define MP4ESDS_h_
-
-#include "nsTArray.h"
-#include "MuxerOperation.h"
-
-namespace mozilla {
-
-class ISOControl;
-
-/**
- * ESDS tag
- */
-#define ESDescrTag 0x03
-
-/**
- * 14496-1 '8.3.3 ES_Descriptor'.
- * It will get DecoderConfigDescriptor and SLConfigDescriptor from
- * AAC CSD data.
- */
-class ES_Descriptor : public MuxerOperation {
-public:
- // ISO BMFF members
- uint8_t tag; // ESDescrTag
- uint8_t length;
- uint16_t ES_ID;
- std::bitset<1> streamDependenceFlag;
- std::bitset<1> URL_Flag;
- std::bitset<1> reserved;
- std::bitset<5> streamPriority;
-
- nsTArray<uint8_t> DecodeSpecificInfo;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
- nsresult Find(const nsACString& aType,
- nsTArray<RefPtr<MuxerOperation>>& aOperations) override;
-
- // ES_Descriptor methods
- ES_Descriptor(ISOControl* aControl);
- ~ES_Descriptor();
-
-protected:
- ISOControl* mControl;
-};
-
-// 14496-14 5.6 'Sample Description Boxes'
-// Box type: 'esds'
-class ESDBox : public FullBox {
-public:
- // ISO BMFF members
- RefPtr<ES_Descriptor> es_descriptor;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // ESDBox methods
- ESDBox(ISOControl* aControl);
- ~ESDBox();
-};
-
-// 14496-14 5.6 'Sample Description Boxes'
-// Box type: 'mp4a'
-class MP4AudioSampleEntry : public AudioSampleEntry {
-public:
- // ISO BMFF members
- RefPtr<ESDBox> es;
-
- // MuxerOperation methods
- nsresult Generate(uint32_t* aBoxSize) override;
- nsresult Write() override;
-
- // MP4AudioSampleEntry methods
- MP4AudioSampleEntry(ISOControl* aControl);
- ~MP4AudioSampleEntry();
-};
-
-}
-
-#endif // MP4ESDS_h_
diff --git a/dom/media/encoder/fmp4_muxer/MuxerOperation.h b/dom/media/encoder/fmp4_muxer/MuxerOperation.h
deleted file mode 100644
index 0b83c89b0..000000000
--- a/dom/media/encoder/fmp4_muxer/MuxerOperation.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsString.h"
-#include "nsTArray.h"
-
-#ifndef MuxerOperation_h_
-#define MuxerOperation_h_
-
-namespace mozilla {
-
-/**
- * The interface for ISO box. All Boxes inherit from this interface.
- * Generate() and Write() are needed to be called to produce a complete box.
- *
- * Generate() will generate all the data structures and their size.
- *
- * Write() will write all data into muxing output stream (ISOControl actually)
- * and update the data which can't be known at Generate() (for example, the
- * offset of the video data in mp4 file).
- *
- * ISO base media format is composed of several container boxes and the contained
- * boxes. The container boxes hold a list of MuxerOperation which is implemented
- * by contained boxes. The contained boxes will be called via the list.
- * For example:
- * MovieBox (container) ---> boxes (array of MuxerOperation)
- * |---> MovieHeaderBox (full box)
- * |---> TrakBox (container)
- * |---> MovieExtendsBox (container)
- *
- * The complete box structure can be found at 14496-12 E.2 "The‘isom’brand".
- */
-class MuxerOperation {
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MuxerOperation)
-
- // Generate data of this box and its contained box, and calculate box size.
- virtual nsresult Generate(uint32_t* aBoxSize) = 0;
-
- // Write data to stream.
- virtual nsresult Write() = 0;
-
- // Find the box type via its name (name is the box type defined in 14496-12;
- // for example, 'moov' is the name of MovieBox).
- // It can only look child boxes including itself and the box in the boxes
- // list if exists. It can't look parent boxes.
- virtual nsresult Find(const nsACString& aType,
- nsTArray<RefPtr<MuxerOperation>>& aOperations) = 0;
-
-protected:
- virtual ~MuxerOperation() {}
-};
-
-}
-#endif
diff --git a/dom/media/encoder/fmp4_muxer/moz.build b/dom/media/encoder/fmp4_muxer/moz.build
deleted file mode 100644
index 5ff274be5..000000000
--- a/dom/media/encoder/fmp4_muxer/moz.build
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXPORTS += [
- 'ISOMediaWriter.h',
- 'ISOTrackMetadata.h',
-]
-
-UNIFIED_SOURCES += [
- 'AMRBox.cpp',
- 'AVCBox.cpp',
- 'EVRCBox.cpp',
- 'ISOControl.cpp',
- 'ISOMediaBoxes.cpp',
- 'ISOMediaWriter.cpp',
- 'MP4ESDS.cpp',
-]
-
-FINAL_LIBRARY = 'xul'
diff --git a/dom/media/encoder/moz.build b/dom/media/encoder/moz.build
index 0d5cdc16f..f29430cb0 100644
--- a/dom/media/encoder/moz.build
+++ b/dom/media/encoder/moz.build
@@ -7,9 +7,6 @@
with Files('*'):
BUG_COMPONENT = ('Core', 'Video/Audio: Recording')
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- DIRS += ['fmp4_muxer']
-
EXPORTS += [
'ContainerWriter.h',
'EncodedFrameContainer.h',
@@ -37,16 +34,6 @@ FINAL_LIBRARY = 'xul'
# These includes are from Android JB, for use of MediaCodec.
LOCAL_INCLUDES += ['/ipc/chromium/src']
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] > '15':
- LOCAL_INCLUDES += [
- '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/av/include/media',
- 'frameworks/native/include',
- 'frameworks/native/opengl/include',
- ]
-
- ]
-
include('/ipc/chromium/chromium-config.mozbuild')
# Suppress some GCC warnings being treated as errors:
diff --git a/dom/media/gmp/GMPChild.cpp b/dom/media/gmp/GMPChild.cpp
index f8e75e299..14b06cc72 100644
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -18,7 +18,6 @@
#include "gmp-video-decode.h"
#include "gmp-video-encode.h"
#include "GMPPlatform.h"
-#include "mozilla/dom/CrashReporterChild.h"
#include "mozilla/ipc/ProcessChild.h"
#include "GMPUtils.h"
#include "prio.h"
@@ -26,7 +25,6 @@
#include "widevine-adapter/WidevineAdapter.h"
using namespace mozilla::ipc;
-using mozilla::dom::CrashReporterChild;
static const int MAX_VOUCHER_LENGTH = 500000;
@@ -36,12 +34,6 @@ static const int MAX_VOUCHER_LENGTH = 500000;
#include <unistd.h> // for _exit()
#endif
-#if defined(MOZ_GMP_SANDBOX)
-#if defined(XP_MACOSX)
-#include "mozilla/Sandbox.h"
-#endif
-#endif
-
namespace mozilla {
#undef LOG
@@ -131,7 +123,6 @@ GetPluginFile(const nsAString& aPluginPath,
return true;
}
-#if !defined(XP_MACOSX) || !defined(MOZ_GMP_SANDBOX)
static bool
GetPluginFile(const nsAString& aPluginPath,
nsCOMPtr<nsIFile>& aLibFile)
@@ -139,110 +130,6 @@ GetPluginFile(const nsAString& aPluginPath,
nsCOMPtr<nsIFile> unusedlibDir;
return GetPluginFile(aPluginPath, unusedlibDir, aLibFile);
}
-#endif
-
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
-static nsCString
-GetNativeTarget(nsIFile* aFile)
-{
- bool isLink;
- nsCString path;
- aFile->IsSymlink(&isLink);
- if (isLink) {
- aFile->GetNativeTarget(path);
- } else {
- aFile->GetNativePath(path);
- }
- return path;
-}
-
-static bool
-GetPluginPaths(const nsAString& aPluginPath,
- nsCString &aPluginDirectoryPath,
- nsCString &aPluginFilePath)
-{
- nsCOMPtr<nsIFile> libDirectory, libFile;
- if (!GetPluginFile(aPluginPath, libDirectory, libFile)) {
- return false;
- }
-
- // Mac sandbox rules expect paths to actual files and directories -- not
- // soft links.
- libDirectory->Normalize();
- aPluginDirectoryPath = GetNativeTarget(libDirectory);
-
- libFile->Normalize();
- aPluginFilePath = GetNativeTarget(libFile);
-
- return true;
-}
-
-static bool
-GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath)
-{
- nsAutoCString appPath;
- nsAutoCString appBinaryPath(
- (CommandLine::ForCurrentProcess()->argv()[0]).c_str());
-
- nsAutoCString::const_iterator start, end;
- appBinaryPath.BeginReading(start);
- appBinaryPath.EndReading(end);
- if (RFindInReadable(NS_LITERAL_CSTRING(".app/Contents/MacOS/"), start, end)) {
- end = start;
- ++end; ++end; ++end; ++end;
- appBinaryPath.BeginReading(start);
- appPath.Assign(Substring(start, end));
- } else {
- return false;
- }
-
- nsCOMPtr<nsIFile> app, appBinary;
- nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appPath),
- true, getter_AddRefs(app));
- if (NS_FAILED(rv)) {
- return false;
- }
- rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appBinaryPath),
- true, getter_AddRefs(appBinary));
- if (NS_FAILED(rv)) {
- return false;
- }
-
- // Mac sandbox rules expect paths to actual files and directories -- not
- // soft links.
- aAppPath = GetNativeTarget(app);
- appBinaryPath = GetNativeTarget(appBinary);
-
- return true;
-}
-
-bool
-GMPChild::SetMacSandboxInfo(MacSandboxPluginType aPluginType)
-{
- if (!mGMPLoader) {
- return false;
- }
- nsAutoCString pluginDirectoryPath, pluginFilePath;
- if (!GetPluginPaths(mPluginPath, pluginDirectoryPath, pluginFilePath)) {
- return false;
- }
- nsAutoCString appPath, appBinaryPath;
- if (!GetAppPaths(appPath, appBinaryPath)) {
- return false;
- }
-
- MacSandboxInfo info;
- info.type = MacSandboxType_Plugin;
- info.pluginInfo.type = aPluginType;
- info.pluginInfo.pluginPath.assign(pluginDirectoryPath.get());
- info.pluginInfo.pluginBinaryPath.assign(pluginFilePath.get());
- info.appPath.assign(appPath.get());
- info.appBinaryPath.assign(appBinaryPath.get());
-
- mGMPLoader->SetSandboxInfo(&info);
- return true;
-}
-#endif // XP_MACOSX && MOZ_GMP_SANDBOX
bool
GMPChild::Init(const nsAString& aPluginPath,
@@ -324,14 +211,6 @@ GMPChild::RecvPreloadLibs(const nsCString& aLibs)
bool
GMPChild::GetUTF8LibPath(nsACString& aOutLibPath)
{
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
- nsAutoCString pluginDirectoryPath, pluginFilePath;
- if (!GetPluginPaths(mPluginPath, pluginDirectoryPath, pluginFilePath)) {
- MOZ_CRASH("Error scanning plugin path");
- }
- aOutLibPath.Assign(pluginFilePath);
- return true;
-#else
nsCOMPtr<nsIFile> libFile;
if (!GetPluginFile(mPluginPath, libFile)) {
return false;
@@ -347,7 +226,6 @@ GMPChild::GetUTF8LibPath(nsACString& aOutLibPath)
aOutLibPath = NS_ConvertUTF16toUTF8(path);
return true;
-#endif
}
bool
@@ -377,17 +255,6 @@ GMPChild::AnswerStartPlugin(const nsString& aAdapter)
}
bool isWidevine = aAdapter.EqualsLiteral("widevine");
-#if defined(MOZ_GMP_SANDBOX) && defined(XP_MACOSX)
- MacSandboxPluginType pluginType = MacSandboxPluginType_GMPlugin_Default;
- if (isWidevine) {
- pluginType = MacSandboxPluginType_GMPlugin_EME_Widevine;
- }
- if (!SetMacSandboxInfo(pluginType)) {
- NS_WARNING("Failed to set Mac GMP sandbox info");
- delete platformAPI;
- return false;
- }
-#endif
GMPAdapter* adapter = (isWidevine) ? new WidevineAdapter() : nullptr;
if (!mGMPLoader->Load(libPath.get(),
@@ -462,19 +329,6 @@ GMPChild::ProcessingError(Result aCode, const char* aReason)
}
}
-mozilla::dom::PCrashReporterChild*
-GMPChild::AllocPCrashReporterChild(const NativeThreadId& aThread)
-{
- return new CrashReporterChild();
-}
-
-bool
-GMPChild::DeallocPCrashReporterChild(PCrashReporterChild* aCrashReporter)
-{
- delete aCrashReporter;
- return true;
-}
-
PGMPTimerChild*
GMPChild::AllocPGMPTimerChild()
{
diff --git a/dom/media/gmp/GMPChild.h b/dom/media/gmp/GMPChild.h
index d5314cf96..722e4c7a9 100644
--- a/dom/media/gmp/GMPChild.h
+++ b/dom/media/gmp/GMPChild.h
@@ -40,10 +40,6 @@ public:
// GMPAsyncShutdownHost
void ShutdownComplete() override;
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
- bool SetMacSandboxInfo(MacSandboxPluginType aPluginType);
-#endif
-
private:
friend class GMPContentChild;
@@ -56,9 +52,6 @@ private:
bool AnswerStartPlugin(const nsString& aAdapter) override;
bool RecvPreloadLibs(const nsCString& aLibs) override;
- PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) override;
- bool DeallocPCrashReporterChild(PCrashReporterChild*) override;
-
PGMPTimerChild* AllocPGMPTimerChild() override;
bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) override;
diff --git a/dom/media/gmp/GMPLoader.cpp b/dom/media/gmp/GMPLoader.cpp
index c10208a49..0bccdd0b1 100644
--- a/dom/media/gmp/GMPLoader.cpp
+++ b/dom/media/gmp/GMPLoader.cpp
@@ -44,10 +44,6 @@ public:
void Shutdown() override;
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
- void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) override;
-#endif
-
private:
SandboxStarter* mSandboxStarter;
UniquePtr<GMPAdapter> mAdapter;
@@ -208,15 +204,6 @@ GMPLoaderImpl::Shutdown()
}
}
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
-void
-GMPLoaderImpl::SetSandboxInfo(MacSandboxInfo* aSandboxInfo)
-{
- if (mSandboxStarter) {
- mSandboxStarter->SetSandboxInfo(aSandboxInfo);
- }
-}
-#endif
} // namespace gmp
} // namespace mozilla
diff --git a/dom/media/gmp/GMPLoader.h b/dom/media/gmp/GMPLoader.h
index 60581be2d..8e6b3cfac 100644
--- a/dom/media/gmp/GMPLoader.h
+++ b/dom/media/gmp/GMPLoader.h
@@ -12,10 +12,6 @@
#include "gmp-entrypoints.h"
#include "mozilla/UniquePtr.h"
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
-#include "mozilla/Sandbox.h"
-#endif
-
namespace mozilla {
namespace gmp {
@@ -23,12 +19,6 @@ class SandboxStarter {
public:
virtual ~SandboxStarter() {}
virtual bool Start(const char* aLibPath) = 0;
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
- // On OS X we need to set Mac-specific sandbox info just before we start the
- // sandbox, which we don't yet know when the GMPLoader and SandboxStarter
- // objects are created.
- virtual void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) = 0;
-#endif
};
// Interface that adapts a plugin to the GMP API.
@@ -94,13 +84,6 @@ public:
// Calls the GMPShutdown function exported by the GMP lib, and unloads the
// plugin library.
virtual void Shutdown() = 0;
-
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
- // On OS X we need to set Mac-specific sandbox info just before we start the
- // sandbox, which we don't yet know when the GMPLoader and SandboxStarter
- // objects are created.
- virtual void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) = 0;
-#endif
};
// On Desktop, this function resides in plugin-container.
diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp
index 00bc97777..40c3e5141 100644
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -18,15 +18,10 @@
#include "nsIObserverService.h"
#include "GMPTimerParent.h"
#include "runnable_utils.h"
-#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
-#include "mozilla/SandboxInfo.h"
-#endif
#include "GMPContentParent.h"
#include "MediaPrefs.h"
#include "VideoUtils.h"
-#include "mozilla/dom/CrashReporterParent.h"
-using mozilla::dom::CrashReporterParent;
using mozilla::ipc::GeckoChildProcessHost;
#include "mozilla/Telemetry.h"
@@ -583,22 +578,6 @@ GMPParent::ActorDestroy(ActorDestroyReason aWhy)
}
}
-mozilla::dom::PCrashReporterParent*
-GMPParent::AllocPCrashReporterParent(const NativeThreadId& aThread)
-{
- MOZ_ASSERT(false, "Should only be sent if crash reporting is enabled.");
- CrashReporterParent* cr = new CrashReporterParent();
- cr->SetChildData(aThread, GeckoProcessType_GMPlugin);
- return cr;
-}
-
-bool
-GMPParent::DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter)
-{
- delete aCrashReporter;
- return true;
-}
-
PGMPStorageParent*
GMPParent::AllocPGMPStorageParent()
{
@@ -749,14 +728,6 @@ GMPParent::ReadGMPInfoFile(nsIFile* aFile)
if (cap.mAPIName.EqualsLiteral(GMP_API_DECRYPTOR)) {
mCanDecrypt = true;
-#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
- if (!mozilla::SandboxInfo::Get().CanSandboxMedia()) {
- printf_stderr("GMPParent::ReadGMPMetaData: Plugin \"%s\" is an EME CDM"
- " but this system can't sandbox it; not loading.\n",
- mDisplayName.get());
- return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
- }
-#endif
#ifdef XP_WIN
// Adobe GMP doesn't work without SSE2. Check the tags to see if
// the decryptor is for the Adobe GMP, and refuse to load it if
diff --git a/dom/media/gmp/GMPParent.h b/dom/media/gmp/GMPParent.h
index 4f91ec5ba..dacd6feeb 100644
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -168,9 +168,6 @@ private:
RefPtr<GenericPromise> ReadChromiumManifestFile(nsIFile* aFile); // GMP thread.
void ActorDestroy(ActorDestroyReason aWhy) override;
- PCrashReporterParent* AllocPCrashReporterParent(const NativeThreadId& aThread) override;
- bool DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter) override;
-
bool RecvPGMPStorageConstructor(PGMPStorageParent* actor) override;
PGMPStorageParent* AllocPGMPStorageParent() override;
bool DeallocPGMPStorageParent(PGMPStorageParent* aActor) override;
diff --git a/dom/media/gmp/GMPProcessParent.cpp b/dom/media/gmp/GMPProcessParent.cpp
index 2fe7306a4..ef58175e8 100644
--- a/dom/media/gmp/GMPProcessParent.cpp
+++ b/dom/media/gmp/GMPProcessParent.cpp
@@ -8,9 +8,6 @@
#include "GMPUtils.h"
#include "nsIFile.h"
#include "nsIRunnable.h"
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-#include "WinUtils.h"
-#endif
#include "base/string_util.h"
#include "base/process_util.h"
@@ -56,38 +53,7 @@ GMPProcessParent::Launch(int32_t aTimeoutMs)
vector<string> args;
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
- std::wstring wGMPPath = UTF8ToWide(mGMPPath.c_str());
-
- // The sandbox doesn't allow file system rules where the paths contain
- // symbolic links or junction points. Sometimes the Users folder has been
- // moved to another drive using a junction point, so allow for this specific
- // case. See bug 1236680 for details.
- if (!widget::WinUtils::ResolveJunctionPointsAndSymLinks(wGMPPath)) {
- GMP_LOG("ResolveJunctionPointsAndSymLinks failed for GMP path=%S",
- wGMPPath.c_str());
- NS_WARNING("ResolveJunctionPointsAndSymLinks failed for GMP path.");
- return false;
- }
- GMP_LOG("GMPProcessParent::Launch() resolved path to %S", wGMPPath.c_str());
-
- // If the GMP path is a network path that is not mapped to a drive letter,
- // then we need to fix the path format for the sandbox rule.
- wchar_t volPath[MAX_PATH];
- if (::GetVolumePathNameW(wGMPPath.c_str(), volPath, MAX_PATH) &&
- ::GetDriveTypeW(volPath) == DRIVE_REMOTE &&
- wGMPPath.compare(0, 2, L"\\\\") == 0) {
- std::wstring sandboxGMPPath(wGMPPath);
- sandboxGMPPath.insert(1, L"??\\UNC");
- mAllowedFilesRead.push_back(sandboxGMPPath + L"\\*");
- } else {
- mAllowedFilesRead.push_back(wGMPPath + L"\\*");
- }
-
- args.push_back(WideToUTF8(wGMPPath));
-#else
args.push_back(mGMPPath);
-#endif
args.push_back(string(voucherPath.BeginReading(), voucherPath.EndReading()));
diff --git a/dom/media/gmp/GMPService.cpp b/dom/media/gmp/GMPService.cpp
index 65f4037ee..1901210da 100644
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -25,9 +25,6 @@
#include "nsComponentManagerUtils.h"
#include "runnable_utils.h"
#include "VideoUtils.h"
-#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
-#include "mozilla/SandboxInfo.h"
-#endif
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
@@ -485,14 +482,6 @@ GeckoMediaPluginService::GetGMPDecryptor(GMPCrashHelper* aHelper,
const nsACString& aNodeId,
UniquePtr<GetGMPDecryptorCallback>&& aCallback)
{
-#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
- if (!SandboxInfo::Get().CanSandboxMedia()) {
- NS_WARNING("GeckoMediaPluginService::GetGMPDecryptor: "
- "EME decryption not available without sandboxing support.");
- return NS_ERROR_NOT_AVAILABLE;
- }
-#endif
-
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
NS_ENSURE_ARG(aCallback);
diff --git a/dom/media/gmp/GMPServiceParent.cpp b/dom/media/gmp/GMPServiceParent.cpp
index f25c36811..2b4831cd6 100644
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -27,9 +27,6 @@
#include "nsComponentManagerUtils.h"
#include "runnable_utils.h"
#include "VideoUtils.h"
-#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
-#include "mozilla/SandboxInfo.h"
-#endif
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
@@ -273,11 +270,7 @@ GeckoMediaPluginServiceParent::InitStorage()
// Directory service is main thread only, so cache the profile dir here
// so that we can use it off main thread.
-#ifdef MOZ_WIDGET_GONK
- nsresult rv = NS_NewLocalFile(NS_LITERAL_STRING("/data/b2g/mozilla"), false, getter_AddRefs(mStorageBaseDir));
-#else
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mStorageBaseDir));
-#endif
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -960,15 +953,6 @@ GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId,
RefPtr<GMPParent>
CreateGMPParent()
{
-#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
- if (!SandboxInfo::Get().CanSandboxMedia()) {
- if (!MediaPrefs::GMPAllowInsecure()) {
- NS_WARNING("Denying media plugin load due to lack of sandboxing.");
- return nullptr;
- }
- NS_WARNING("Loading media plugin despite lack of sandboxing.");
- }
-#endif
return new GMPParent();
}
diff --git a/dom/media/gmp/PGMP.ipdl b/dom/media/gmp/PGMP.ipdl
index b421f0280..e1738d010 100644
--- a/dom/media/gmp/PGMP.ipdl
+++ b/dom/media/gmp/PGMP.ipdl
@@ -3,7 +3,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-include protocol PCrashReporter;
include protocol PGMPContent;
include protocol PGMPTimer;
include protocol PGMPStorage;
@@ -17,12 +16,10 @@ intr protocol PGMP
{
parent opens PGMPContent;
- manages PCrashReporter;
manages PGMPTimer;
manages PGMPStorage;
parent:
- async PCrashReporter(NativeThreadId tid);
async PGMPTimer();
async PGMPStorage();
diff --git a/dom/media/gmp/rlz/GMPDeviceBinding.cpp b/dom/media/gmp/rlz/GMPDeviceBinding.cpp
index c8aee2bcd..3525f0462 100644
--- a/dom/media/gmp/rlz/GMPDeviceBinding.cpp
+++ b/dom/media/gmp/rlz/GMPDeviceBinding.cpp
@@ -12,10 +12,6 @@
#ifdef XP_WIN
#include "windows.h"
-#ifdef MOZ_SANDBOX
-#include <intrin.h>
-#include <assert.h>
-#endif
#endif
#if defined(HASH_NODE_ID_WITH_DEVICE_ID)
@@ -35,10 +31,6 @@
#ifdef XP_WIN
#include "windows.h"
-#ifdef MOZ_SANDBOX
-#include <intrin.h>
-#include <assert.h>
-#endif
#endif
#ifdef XP_MACOSX
diff --git a/dom/media/gmp/rlz/moz.build b/dom/media/gmp/rlz/moz.build
index f366c2b5d..5e85357f1 100644
--- a/dom/media/gmp/rlz/moz.build
+++ b/dom/media/gmp/rlz/moz.build
@@ -13,13 +13,6 @@ UNIFIED_SOURCES += [
'GMPDeviceBinding.cpp',
]
-if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] in ['WINNT', 'Darwin']:
- DEFINES['HASH_NODE_ID_WITH_DEVICE_ID'] = 1;
- UNIFIED_SOURCES += [
- 'lib/string_utils.cc',
- 'sha256.c',
- ]
-
if CONFIG['OS_TARGET'] == 'WINNT':
UNIFIED_SOURCES += [
'win/lib/machine_id_win.cc',
diff --git a/dom/media/ipc/VideoDecoderChild.cpp b/dom/media/ipc/VideoDecoderChild.cpp
index d1b1d23fc..f01d3c659 100644
--- a/dom/media/ipc/VideoDecoderChild.cpp
+++ b/dom/media/ipc/VideoDecoderChild.cpp
@@ -238,6 +238,7 @@ VideoDecoderChild::Shutdown()
SendShutdown();
}
mInitialized = false;
+ mCallback = nullptr;
}
bool
diff --git a/dom/media/ipc/VideoDecoderManagerParent.cpp b/dom/media/ipc/VideoDecoderManagerParent.cpp
index a111b5e53..4ff9acf19 100644
--- a/dom/media/ipc/VideoDecoderManagerParent.cpp
+++ b/dom/media/ipc/VideoDecoderManagerParent.cpp
@@ -194,7 +194,7 @@ VideoDecoderManagerParent::RecvReadback(const SurfaceDescriptorGPUVideo& aSD, Su
}
RefPtr<SourceSurface> source = image->GetAsSourceSurface();
- if (!image) {
+ if (!source) {
*aResult = null_t();
return true;
}
diff --git a/dom/media/mediasink/DecodedStream.cpp b/dom/media/mediasink/DecodedStream.cpp
index 9501a6cde..00bc5ea49 100644
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -181,17 +181,22 @@ DecodedStreamData::DecodedStreamData(OutputStreamManager* aOutputStreamManager,
, mOutputStreamManager(aOutputStreamManager)
{
mStream->AddListener(mListener);
- mOutputStreamManager->Connect(mStream);
+ TrackID audioTrack = TRACK_NONE;
+ TrackID videoTrack = TRACK_NONE;
// Initialize tracks.
if (aInit.mInfo.HasAudio()) {
- mStream->AddAudioTrack(aInit.mInfo.mAudio.mTrackId,
+ audioTrack = aInit.mInfo.mAudio.mTrackId;
+ mStream->AddAudioTrack(audioTrack,
aInit.mInfo.mAudio.mRate,
0, new AudioSegment());
}
if (aInit.mInfo.HasVideo()) {
- mStream->AddTrack(aInit.mInfo.mVideo.mTrackId, 0, new VideoSegment());
+ videoTrack = aInit.mInfo.mVideo.mTrackId;
+ mStream->AddTrack(videoTrack, 0, new VideoSegment());
}
+
+ mOutputStreamManager->Connect(mStream, audioTrack, videoTrack);
}
DecodedStreamData::~DecodedStreamData()
diff --git a/dom/media/mediasink/OutputStreamManager.cpp b/dom/media/mediasink/OutputStreamManager.cpp
index d5685837a..7ecc203ed 100644
--- a/dom/media/mediasink/OutputStreamManager.cpp
+++ b/dom/media/mediasink/OutputStreamManager.cpp
@@ -13,29 +13,41 @@ OutputStreamData::~OutputStreamData()
{
MOZ_ASSERT(NS_IsMainThread());
// Break the connection to the input stream if necessary.
- if (mPort) {
- mPort->Destroy();
+ for (RefPtr<MediaInputPort>& port : mPorts) {
+ port->Destroy();
}
}
void
-OutputStreamData::Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream)
+OutputStreamData::Init(OutputStreamManager* aOwner,
+ ProcessedMediaStream* aStream,
+ TrackID aNextAvailableTrackID)
{
mOwner = aOwner;
mStream = aStream;
+ mNextAvailableTrackID = aNextAvailableTrackID;
}
bool
-OutputStreamData::Connect(MediaStream* aStream)
+OutputStreamData::Connect(MediaStream* aStream,
+ TrackID aInputAudioTrackID,
+ TrackID aInputVideoTrackID)
{
MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!mPort, "Already connected?");
+ MOZ_ASSERT(mPorts.IsEmpty(), "Already connected?");
if (mStream->IsDestroyed()) {
return false;
}
- mPort = mStream->AllocateInputPort(aStream);
+ for (TrackID tid : {aInputAudioTrackID, aInputVideoTrackID}) {
+ if (tid == TRACK_NONE) {
+ continue;
+ }
+ MOZ_ASSERT(IsTrackIDExplicit(tid));
+ mPorts.AppendElement(mStream->AllocateInputPort(
+ aStream, tid, mNextAvailableTrackID++));
+ }
return true;
}
@@ -51,11 +63,11 @@ OutputStreamData::Disconnect()
return false;
}
- // Disconnect the existing port if necessary.
- if (mPort) {
- mPort->Destroy();
- mPort = nullptr;
+ // Disconnect any existing port.
+ for (RefPtr<MediaInputPort>& port : mPorts) {
+ port->Destroy();
}
+ mPorts.Clear();
return true;
}
@@ -71,8 +83,16 @@ OutputStreamData::Graph() const
return mStream->Graph();
}
+TrackID
+OutputStreamData::NextAvailableTrackID() const
+{
+ return mNextAvailableTrackID;
+}
+
void
-OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
+OutputStreamManager::Add(ProcessedMediaStream* aStream,
+ TrackID aNextAvailableTrackID,
+ bool aFinishWhenEnded)
{
MOZ_ASSERT(NS_IsMainThread());
// All streams must belong to the same graph.
@@ -84,12 +104,12 @@ OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
}
OutputStreamData* p = mStreams.AppendElement();
- p->Init(this, aStream);
+ p->Init(this, aStream, aNextAvailableTrackID);
// Connect to the input stream if we have one. Otherwise the output stream
// will be connected in Connect().
if (mInputStream) {
- p->Connect(mInputStream);
+ p->Connect(mInputStream, mInputAudioTrackID, mInputVideoTrackID);
}
}
@@ -106,12 +126,35 @@ OutputStreamManager::Remove(MediaStream* aStream)
}
void
-OutputStreamManager::Connect(MediaStream* aStream)
+OutputStreamManager::Clear()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ mStreams.Clear();
+}
+
+TrackID
+OutputStreamManager::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ for (const OutputStreamData& out : mStreams) {
+ if (out.Equals(aOutputStream)) {
+ return out.NextAvailableTrackID();
+ }
+ }
+ return TRACK_INVALID;
+}
+
+void
+OutputStreamManager::Connect(MediaStream* aStream,
+ TrackID aAudioTrackID,
+ TrackID aVideoTrackID)
{
MOZ_ASSERT(NS_IsMainThread());
mInputStream = aStream;
+ mInputAudioTrackID = aAudioTrackID;
+ mInputVideoTrackID = aVideoTrackID;
for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
- if (!mStreams[i].Connect(aStream)) {
+ if (!mStreams[i].Connect(aStream, mInputAudioTrackID, mInputVideoTrackID)) {
// Probably the DOMMediaStream was GCed. Clean up.
mStreams.RemoveElementAt(i);
}
@@ -123,6 +166,8 @@ OutputStreamManager::Disconnect()
{
MOZ_ASSERT(NS_IsMainThread());
mInputStream = nullptr;
+ mInputAudioTrackID = TRACK_INVALID;
+ mInputVideoTrackID = TRACK_INVALID;
for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
if (!mStreams[i].Disconnect()) {
// Probably the DOMMediaStream was GCed. Clean up.
diff --git a/dom/media/mediasink/OutputStreamManager.h b/dom/media/mediasink/OutputStreamManager.h
index 7f91a60c1..941a86cf0 100644
--- a/dom/media/mediasink/OutputStreamManager.h
+++ b/dom/media/mediasink/OutputStreamManager.h
@@ -9,6 +9,7 @@
#include "mozilla/RefPtr.h"
#include "nsTArray.h"
+#include "MediaSegment.h"
namespace mozilla {
@@ -21,11 +22,13 @@ class ProcessedMediaStream;
class OutputStreamData {
public:
~OutputStreamData();
- void Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream);
+ void Init(OutputStreamManager* aOwner,
+ ProcessedMediaStream* aStream,
+ TrackID aNextAvailableTrackID);
- // Connect mStream to the input stream.
+ // Connect the given input stream's audio and video tracks to mStream.
// Return false is mStream is already destroyed, otherwise true.
- bool Connect(MediaStream* aStream);
+ bool Connect(MediaStream* aStream, TrackID aAudioTrackID, TrackID aVideoTrackID);
// Disconnect mStream from its input stream.
// Return false is mStream is already destroyed, otherwise true.
bool Disconnect();
@@ -34,12 +37,16 @@ public:
bool Equals(MediaStream* aStream) const;
// Return the graph mStream belongs to.
MediaStreamGraph* Graph() const;
+ // The next TrackID that will not cause a collision in mStream.
+ TrackID NextAvailableTrackID() const;
private:
OutputStreamManager* mOwner;
RefPtr<ProcessedMediaStream> mStream;
- // mPort connects our mStream to an input stream.
- RefPtr<MediaInputPort> mPort;
+ // mPort connects an input stream to our mStream.
+ nsTArray<RefPtr<MediaInputPort>> mPorts;
+ // For guaranteeing TrackID uniqueness in our mStream.
+ TrackID mNextAvailableTrackID = TRACK_INVALID;
};
class OutputStreamManager {
@@ -47,18 +54,26 @@ class OutputStreamManager {
public:
// Add the output stream to the collection.
- void Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
+ void Add(ProcessedMediaStream* aStream,
+ TrackID aNextAvailableTrackID,
+ bool aFinishWhenEnded);
// Remove the output stream from the collection.
void Remove(MediaStream* aStream);
+ // Clear all output streams from the collection.
+ void Clear();
+ // The next TrackID that will not cause a collision in aOutputStream.
+ TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const;
// Return true if the collection empty.
bool IsEmpty() const
{
MOZ_ASSERT(NS_IsMainThread());
return mStreams.IsEmpty();
}
- // Connect all output streams in the collection to the input stream.
- void Connect(MediaStream* aStream);
- // Disconnect all output streams from the input stream.
+ // Connect the given input stream's tracks to all output streams.
+ void Connect(MediaStream* aStream,
+ TrackID aAudioTrackID,
+ TrackID aVideoTrackID);
+ // Disconnect the input stream to all output streams.
void Disconnect();
// Return the graph these streams belong to or null if empty.
MediaStreamGraph* Graph() const
@@ -72,6 +87,8 @@ private:
// Keep the input stream so we can connect the output streams that
// are added after Connect().
RefPtr<MediaStream> mInputStream;
+ TrackID mInputAudioTrackID = TRACK_INVALID;
+ TrackID mInputVideoTrackID = TRACK_INVALID;
nsTArray<OutputStreamData> mStreams;
};
diff --git a/dom/media/mediasource/ContainerParser.cpp b/dom/media/mediasource/ContainerParser.cpp
index 5267e9315..4ae37d7e9 100644
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -390,7 +390,7 @@ private:
"ftyp", "moov", // init segment
"pdin", "free", "sidx", // optional prior moov box
"styp", "moof", "mdat", // media segment
- "mfra", "skip", "meta", "meco", "ssix", "prft" // others.
+ "mfra", "skip", "meta", "meco", "ssix", "prft", // others.
"pssh", // optional with encrypted EME, though ignored.
"emsg", // ISO23009-1:2014 Section 5.10.3.3
"bloc", "uuid" // boxes accepted by chrome.
@@ -588,8 +588,8 @@ public:
return false;
}
size_t header_length = have_crc ? 9 : 7;
- size_t data_length = (((*aData)[3] & 0x03) << 11) ||
- (((*aData)[4] & 0xff) << 3) ||
+ size_t data_length = (((*aData)[3] & 0x03) << 11) |
+ (((*aData)[4] & 0xff) << 3) |
(((*aData)[5] & 0xe0) >> 5);
uint8_t frames = ((*aData)[6] & 0x03) + 1;
MOZ_ASSERT(frames > 0);
diff --git a/dom/media/moz.build b/dom/media/moz.build
index d1885793b..4d036a5f6 100644
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -169,11 +169,6 @@ IPDL_SOURCES += [
'webrtc/PWebrtcGlobal.ipdl'
]
-if CONFIG['MOZ_B2G']:
- EXPORTS.mozilla += [
- 'MediaPermissionGonk.h',
- ]
-
EXPORTS.mozilla.dom += [
'AudioStreamTrack.h',
'AudioTrack.h',
@@ -270,11 +265,6 @@ UNIFIED_SOURCES += [
if CONFIG['OS_TARGET'] == 'WINNT':
SOURCES += [ 'ThreadPoolCOMListener.cpp' ]
-if CONFIG['MOZ_B2G']:
- SOURCES += [
- 'MediaPermissionGonk.cpp',
- ]
-
# DecoderTraits.cpp needs to be built separately because of Mac OS X headers.
SOURCES += [
'DecoderTraits.cpp',
@@ -325,9 +315,6 @@ else:
if CONFIG['ANDROID_VERSION'] > '15':
DEFINES['MOZ_OMX_WEBM_DECODER'] = True
-if CONFIG['MOZ_GONK_MEDIACODEC']:
- DEFINES['MOZ_GONK_MEDIACODEC'] = True
-
include('/ipc/chromium/chromium-config.mozbuild')
# Suppress some GCC warnings being treated as errors:
diff --git a/dom/media/ogg/OggCodecState.cpp b/dom/media/ogg/OggCodecState.cpp
index 6830639e8..d03508411 100644
--- a/dom/media/ogg/OggCodecState.cpp
+++ b/dom/media/ogg/OggCodecState.cpp
@@ -18,18 +18,6 @@
#include <opus/opus.h>
#include "opus/opus_multistream.h"
-// On Android JellyBean, the hardware.h header redefines version_major and
-// version_minor, which breaks our build. See:
-// https://bugzilla.mozilla.org/show_bug.cgi?id=912702#c6
-#ifdef MOZ_WIDGET_GONK
-#ifdef version_major
-#undef version_major
-#endif
-#ifdef version_minor
-#undef version_minor
-#endif
-#endif
-
namespace mozilla {
extern LazyLogModule gMediaDecoderLog;
@@ -1241,12 +1229,13 @@ already_AddRefed<MediaRawData>
OpusState::PacketOutAsMediaRawData()
{
ogg_packet* packet = PacketPeek();
- uint32_t frames = 0;
- const int64_t endFrame = packet->granulepos;
-
if (!packet) {
return nullptr;
}
+
+ uint32_t frames = 0;
+ const int64_t endFrame = packet->granulepos;
+
if (packet->e_o_s) {
frames = GetOpusDeltaGP(packet);
}
diff --git a/dom/media/ogg/OggWriter.cpp b/dom/media/ogg/OggWriter.cpp
index bb0dca67b..e1aa93eaf 100644
--- a/dom/media/ogg/OggWriter.cpp
+++ b/dom/media/ogg/OggWriter.cpp
@@ -7,12 +7,7 @@
#include "GeckoProfiler.h"
#undef LOG
-#ifdef MOZ_WIDGET_GONK
-#include <android/log.h>
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args);
-#else
#define LOG(args, ...)
-#endif
namespace mozilla {
diff --git a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
index 0b31fb0f9..8cb5c8578 100644
--- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
@@ -69,15 +69,21 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
mCodecContext->extradata_size = mExtraData->Length();
// FFmpeg may use SIMD instructions to access the data which reads the
// data in 32 bytes block. Must ensure we have enough data to read.
+#if LIBAVCODEC_VERSION_MAJOR >= 58
+ mExtraData->AppendElements(AV_INPUT_BUFFER_PADDING_SIZE);
+#else
mExtraData->AppendElements(FF_INPUT_BUFFER_PADDING_SIZE);
+#endif
mCodecContext->extradata = mExtraData->Elements();
} else {
mCodecContext->extradata_size = 0;
}
+#if LIBAVCODEC_VERSION_MAJOR < 57
if (codec->capabilities & CODEC_CAP_DR1) {
mCodecContext->flags |= CODEC_FLAG_EMU_EDGE;
}
+#endif
if (mLib->avcodec_open2(mCodecContext, codec, nullptr) < 0) {
NS_WARNING("Couldn't initialise ffmpeg decoder");
diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
index f3dc00ad7..6302882a6 100644
--- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
@@ -69,12 +69,14 @@ FFmpegLibWrapper::Link()
AV_FUNC_55 = 1 << 2,
AV_FUNC_56 = 1 << 3,
AV_FUNC_57 = 1 << 4,
+ AV_FUNC_58 = 1 << 5,
AV_FUNC_AVUTIL_53 = AV_FUNC_53 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_54 = AV_FUNC_54 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_55 = AV_FUNC_55 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_56 = AV_FUNC_56 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_57 = AV_FUNC_57 | AV_FUNC_AVUTIL_MASK,
- AV_FUNC_AVCODEC_ALL = AV_FUNC_53 | AV_FUNC_54 | AV_FUNC_55 | AV_FUNC_56 | AV_FUNC_57,
+ AV_FUNC_AVUTIL_58 = AV_FUNC_58 | AV_FUNC_AVUTIL_MASK,
+ AV_FUNC_AVCODEC_ALL = AV_FUNC_53 | AV_FUNC_54 | AV_FUNC_55 | AV_FUNC_56 | AV_FUNC_57 | AV_FUNC_58,
AV_FUNC_AVUTIL_ALL = AV_FUNC_AVCODEC_ALL | AV_FUNC_AVUTIL_MASK
};
@@ -94,6 +96,9 @@ FFmpegLibWrapper::Link()
case 57:
version = AV_FUNC_57;
break;
+ case 58:
+ version = AV_FUNC_58;
+ break;
default:
FFMPEG_LOG("Unknown avcodec version");
Unlink();
@@ -142,9 +147,9 @@ FFmpegLibWrapper::Link()
AV_FUNC(av_log_set_level, AV_FUNC_AVUTIL_ALL)
AV_FUNC(av_malloc, AV_FUNC_AVUTIL_ALL)
AV_FUNC(av_freep, AV_FUNC_AVUTIL_ALL)
- AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
- AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
- AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
+ AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57 | AV_FUNC_AVUTIL_58))
+ AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57 | AV_FUNC_AVUTIL_58))
+ AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57 | AV_FUNC_AVUTIL_58))
AV_FUNC_OPTION(av_frame_get_colorspace, AV_FUNC_AVUTIL_ALL)
#undef AV_FUNC
#undef AV_FUNC_OPTION
@@ -175,4 +180,4 @@ FFmpegLibWrapper::Unlink()
PodZero(this);
}
-} // namespace mozilla \ No newline at end of file
+} // namespace mozilla
diff --git a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
index fdbe77ef7..4671499e5 100644
--- a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
@@ -27,12 +27,15 @@ static FFmpegLibWrapper sLibAV;
static const char* sLibs[] = {
#if defined(XP_DARWIN)
+ "libavcodec.58.dylib",
"libavcodec.57.dylib",
"libavcodec.56.dylib",
"libavcodec.55.dylib",
"libavcodec.54.dylib",
"libavcodec.53.dylib",
#else
+ "libavcodec.so.58",
+ "libavcodec-ffmpeg.so.58",
"libavcodec-ffmpeg.so.57",
"libavcodec-ffmpeg.so.56",
"libavcodec.so.57",
@@ -134,6 +137,7 @@ FFmpegRuntimeLinker::CreateDecoderModule()
case 55:
case 56: module = FFmpegDecoderModule<55>::Create(&sLibAV); break;
case 57: module = FFmpegDecoderModule<57>::Create(&sLibAV); break;
+ case 58: module = FFmpegDecoderModule<58>::Create(&sLibAV); break;
default: module = nullptr;
}
return module.forget();
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
index 5c1b6c97b..aec1e9136 100644
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
@@ -181,8 +181,8 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample, bool* aGotFrame)
#endif
)) {
while (inputSize) {
- uint8_t* data;
- int size;
+ uint8_t* data = inputData;
+ int size = inputSize;
int len = mLib->av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
inputData, inputSize,
aSample->mTime, aSample->mTimecode,
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/COPYING.LGPLv2.1 b/dom/media/platforms/ffmpeg/ffmpeg58/include/COPYING.LGPLv2.1
new file mode 100644
index 000000000..00b4fedfe
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/COPYING.LGPLv2.1
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/avcodec.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/avcodec.h
new file mode 100644
index 000000000..fb0c6fae7
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/avcodec.h
@@ -0,0 +1,6146 @@
+/*
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_AVCODEC_H
+#define AVCODEC_AVCODEC_H
+
+/**
+ * @file
+ * @ingroup libavc
+ * Libavcodec external API header
+ */
+
+#include <errno.h>
+#include "libavutil/samplefmt.h"
+#include "libavutil/attributes.h"
+#include "libavutil/avutil.h"
+#include "libavutil/buffer.h"
+#include "libavutil/cpu.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/dict.h"
+#include "libavutil/frame.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/log.h"
+#include "libavutil/pixfmt.h"
+#include "libavutil/rational.h"
+
+#include "version.h"
+
+/**
+ * @defgroup libavc libavcodec
+ * Encoding/Decoding Library
+ *
+ * @{
+ *
+ * @defgroup lavc_decoding Decoding
+ * @{
+ * @}
+ *
+ * @defgroup lavc_encoding Encoding
+ * @{
+ * @}
+ *
+ * @defgroup lavc_codec Codecs
+ * @{
+ * @defgroup lavc_codec_native Native Codecs
+ * @{
+ * @}
+ * @defgroup lavc_codec_wrappers External library wrappers
+ * @{
+ * @}
+ * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge
+ * @{
+ * @}
+ * @}
+ * @defgroup lavc_internal Internal
+ * @{
+ * @}
+ * @}
+ */
+
+/**
+ * @ingroup libavc
+ * @defgroup lavc_encdec send/receive encoding and decoding API overview
+ * @{
+ *
+ * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/
+ * avcodec_receive_packet() functions provide an encode/decode API, which
+ * decouples input and output.
+ *
+ * The API is very similar for encoding/decoding and audio/video, and works as
+ * follows:
+ * - Set up and open the AVCodecContext as usual.
+ * - Send valid input:
+ * - For decoding, call avcodec_send_packet() to give the decoder raw
+ * compressed data in an AVPacket.
+ * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame
+ * containing uncompressed audio or video.
+ * In both cases, it is recommended that AVPackets and AVFrames are
+ * refcounted, or libavcodec might have to copy the input data. (libavformat
+ * always returns refcounted AVPackets, and av_frame_get_buffer() allocates
+ * refcounted AVFrames.)
+ * - Receive output in a loop. Periodically call one of the avcodec_receive_*()
+ * functions and process their output:
+ * - For decoding, call avcodec_receive_frame(). On success, it will return
+ * an AVFrame containing uncompressed audio or video data.
+ * - For encoding, call avcodec_receive_packet(). On success, it will return
+ * an AVPacket with a compressed frame.
+ * Repeat this call until it returns AVERROR(EAGAIN) or an error. The
+ * AVERROR(EAGAIN) return value means that new input data is required to
+ * return new output. In this case, continue with sending input. For each
+ * input frame/packet, the codec will typically return 1 output frame/packet,
+ * but it can also be 0 or more than 1.
+ *
+ * At the beginning of decoding or encoding, the codec might accept multiple
+ * input frames/packets without returning a frame, until its internal buffers
+ * are filled. This situation is handled transparently if you follow the steps
+ * outlined above.
+ *
+ * In theory, sending input can result in EAGAIN - this should happen only if
+ * not all output was received. You can use this to structure alternative decode
+ * or encode loops other than the one suggested above. For example, you could
+ * try sending new input on each iteration, and try to receive output if that
+ * returns EAGAIN.
+ *
+ * End of stream situations. These require "flushing" (aka draining) the codec,
+ * as the codec might buffer multiple frames or packets internally for
+ * performance or out of necessity (consider B-frames).
+ * This is handled as follows:
+ * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding)
+ * or avcodec_send_frame() (encoding) functions. This will enter draining
+ * mode.
+ * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet()
+ * (encoding) in a loop until AVERROR_EOF is returned. The functions will
+ * not return AVERROR(EAGAIN), unless you forgot to enter draining mode.
+ * - Before decoding can be resumed again, the codec has to be reset with
+ * avcodec_flush_buffers().
+ *
+ * Using the API as outlined above is highly recommended. But it is also
+ * possible to call functions outside of this rigid schema. For example, you can
+ * call avcodec_send_packet() repeatedly without calling
+ * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed
+ * until the codec's internal buffer has been filled up (which is typically of
+ * size 1 per output frame, after initial input), and then reject input with
+ * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to
+ * read at least some output.
+ *
+ * Not all codecs will follow a rigid and predictable dataflow; the only
+ * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on
+ * one end implies that a receive/send call on the other end will succeed, or
+ * at least will not fail with AVERROR(EAGAIN). In general, no codec will
+ * permit unlimited buffering of input or output.
+ *
+ * This API replaces the following legacy functions:
+ * - avcodec_decode_video2() and avcodec_decode_audio4():
+ * Use avcodec_send_packet() to feed input to the decoder, then use
+ * avcodec_receive_frame() to receive decoded frames after each packet.
+ * Unlike with the old video decoding API, multiple frames might result from
+ * a packet. For audio, splitting the input packet into frames by partially
+ * decoding packets becomes transparent to the API user. You never need to
+ * feed an AVPacket to the API twice (unless it is rejected with AVERROR(EAGAIN) - then
+ * no data was read from the packet).
+ * Additionally, sending a flush/draining packet is required only once.
+ * - avcodec_encode_video2()/avcodec_encode_audio2():
+ * Use avcodec_send_frame() to feed input to the encoder, then use
+ * avcodec_receive_packet() to receive encoded packets.
+ * Providing user-allocated buffers for avcodec_receive_packet() is not
+ * possible.
+ * - The new API does not handle subtitles yet.
+ *
+ * Mixing new and old function calls on the same AVCodecContext is not allowed,
+ * and will result in undefined behavior.
+ *
+ * Some codecs might require using the new API; using the old API will return
+ * an error when calling it. All codecs support the new API.
+ *
+ * A codec is not allowed to return AVERROR(EAGAIN) for both sending and receiving. This
+ * would be an invalid state, which could put the codec user into an endless
+ * loop. The API has no concept of time either: it cannot happen that trying to
+ * do avcodec_send_packet() results in AVERROR(EAGAIN), but a repeated call 1 second
+ * later accepts the packet (with no other receive/flush API calls involved).
+ * The API is a strict state machine, and the passage of time is not supposed
+ * to influence it. Some timing-dependent behavior might still be deemed
+ * acceptable in certain cases. But it must never result in both send/receive
+ * returning EAGAIN at the same time at any point. It must also absolutely be
+ * avoided that the current state is "unstable" and can "flip-flop" between
+ * the send/receive APIs allowing progress. For example, it's not allowed that
+ * the codec randomly decides that it actually wants to consume a packet now
+ * instead of returning a frame, after it just returned AVERROR(EAGAIN) on an
+ * avcodec_send_packet() call.
+ * @}
+ */
+
+/**
+ * @defgroup lavc_core Core functions/structures.
+ * @ingroup libavc
+ *
+ * Basic definitions, functions for querying libavcodec capabilities,
+ * allocating core structures, etc.
+ * @{
+ */
+
+
+/**
+ * Identify the syntax and semantics of the bitstream.
+ * The principle is roughly:
+ * Two decoders with the same ID can decode the same streams.
+ * Two encoders with the same ID can encode compatible streams.
+ * There may be slight deviations from the principle due to implementation
+ * details.
+ *
+ * If you add a codec ID to this list, add it so that
+ * 1. no value of an existing codec ID changes (that would break ABI),
+ * 2. it is as close as possible to similar codecs
+ *
+ * After adding new codec IDs, do not forget to add an entry to the codec
+ * descriptor list and bump libavcodec minor version.
+ */
+enum AVCodecID {
+ AV_CODEC_ID_NONE,
+
+ /* video codecs */
+ AV_CODEC_ID_MPEG1VIDEO,
+ AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding
+ AV_CODEC_ID_H261,
+ AV_CODEC_ID_H263,
+ AV_CODEC_ID_RV10,
+ AV_CODEC_ID_RV20,
+ AV_CODEC_ID_MJPEG,
+ AV_CODEC_ID_MJPEGB,
+ AV_CODEC_ID_LJPEG,
+ AV_CODEC_ID_SP5X,
+ AV_CODEC_ID_JPEGLS,
+ AV_CODEC_ID_MPEG4,
+ AV_CODEC_ID_RAWVIDEO,
+ AV_CODEC_ID_MSMPEG4V1,
+ AV_CODEC_ID_MSMPEG4V2,
+ AV_CODEC_ID_MSMPEG4V3,
+ AV_CODEC_ID_WMV1,
+ AV_CODEC_ID_WMV2,
+ AV_CODEC_ID_H263P,
+ AV_CODEC_ID_H263I,
+ AV_CODEC_ID_FLV1,
+ AV_CODEC_ID_SVQ1,
+ AV_CODEC_ID_SVQ3,
+ AV_CODEC_ID_DVVIDEO,
+ AV_CODEC_ID_HUFFYUV,
+ AV_CODEC_ID_CYUV,
+ AV_CODEC_ID_H264,
+ AV_CODEC_ID_INDEO3,
+ AV_CODEC_ID_VP3,
+ AV_CODEC_ID_THEORA,
+ AV_CODEC_ID_ASV1,
+ AV_CODEC_ID_ASV2,
+ AV_CODEC_ID_FFV1,
+ AV_CODEC_ID_4XM,
+ AV_CODEC_ID_VCR1,
+ AV_CODEC_ID_CLJR,
+ AV_CODEC_ID_MDEC,
+ AV_CODEC_ID_ROQ,
+ AV_CODEC_ID_INTERPLAY_VIDEO,
+ AV_CODEC_ID_XAN_WC3,
+ AV_CODEC_ID_XAN_WC4,
+ AV_CODEC_ID_RPZA,
+ AV_CODEC_ID_CINEPAK,
+ AV_CODEC_ID_WS_VQA,
+ AV_CODEC_ID_MSRLE,
+ AV_CODEC_ID_MSVIDEO1,
+ AV_CODEC_ID_IDCIN,
+ AV_CODEC_ID_8BPS,
+ AV_CODEC_ID_SMC,
+ AV_CODEC_ID_FLIC,
+ AV_CODEC_ID_TRUEMOTION1,
+ AV_CODEC_ID_VMDVIDEO,
+ AV_CODEC_ID_MSZH,
+ AV_CODEC_ID_ZLIB,
+ AV_CODEC_ID_QTRLE,
+ AV_CODEC_ID_TSCC,
+ AV_CODEC_ID_ULTI,
+ AV_CODEC_ID_QDRAW,
+ AV_CODEC_ID_VIXL,
+ AV_CODEC_ID_QPEG,
+ AV_CODEC_ID_PNG,
+ AV_CODEC_ID_PPM,
+ AV_CODEC_ID_PBM,
+ AV_CODEC_ID_PGM,
+ AV_CODEC_ID_PGMYUV,
+ AV_CODEC_ID_PAM,
+ AV_CODEC_ID_FFVHUFF,
+ AV_CODEC_ID_RV30,
+ AV_CODEC_ID_RV40,
+ AV_CODEC_ID_VC1,
+ AV_CODEC_ID_WMV3,
+ AV_CODEC_ID_LOCO,
+ AV_CODEC_ID_WNV1,
+ AV_CODEC_ID_AASC,
+ AV_CODEC_ID_INDEO2,
+ AV_CODEC_ID_FRAPS,
+ AV_CODEC_ID_TRUEMOTION2,
+ AV_CODEC_ID_BMP,
+ AV_CODEC_ID_CSCD,
+ AV_CODEC_ID_MMVIDEO,
+ AV_CODEC_ID_ZMBV,
+ AV_CODEC_ID_AVS,
+ AV_CODEC_ID_SMACKVIDEO,
+ AV_CODEC_ID_NUV,
+ AV_CODEC_ID_KMVC,
+ AV_CODEC_ID_FLASHSV,
+ AV_CODEC_ID_CAVS,
+ AV_CODEC_ID_JPEG2000,
+ AV_CODEC_ID_VMNC,
+ AV_CODEC_ID_VP5,
+ AV_CODEC_ID_VP6,
+ AV_CODEC_ID_VP6F,
+ AV_CODEC_ID_TARGA,
+ AV_CODEC_ID_DSICINVIDEO,
+ AV_CODEC_ID_TIERTEXSEQVIDEO,
+ AV_CODEC_ID_TIFF,
+ AV_CODEC_ID_GIF,
+ AV_CODEC_ID_DXA,
+ AV_CODEC_ID_DNXHD,
+ AV_CODEC_ID_THP,
+ AV_CODEC_ID_SGI,
+ AV_CODEC_ID_C93,
+ AV_CODEC_ID_BETHSOFTVID,
+ AV_CODEC_ID_PTX,
+ AV_CODEC_ID_TXD,
+ AV_CODEC_ID_VP6A,
+ AV_CODEC_ID_AMV,
+ AV_CODEC_ID_VB,
+ AV_CODEC_ID_PCX,
+ AV_CODEC_ID_SUNRAST,
+ AV_CODEC_ID_INDEO4,
+ AV_CODEC_ID_INDEO5,
+ AV_CODEC_ID_MIMIC,
+ AV_CODEC_ID_RL2,
+ AV_CODEC_ID_ESCAPE124,
+ AV_CODEC_ID_DIRAC,
+ AV_CODEC_ID_BFI,
+ AV_CODEC_ID_CMV,
+ AV_CODEC_ID_MOTIONPIXELS,
+ AV_CODEC_ID_TGV,
+ AV_CODEC_ID_TGQ,
+ AV_CODEC_ID_TQI,
+ AV_CODEC_ID_AURA,
+ AV_CODEC_ID_AURA2,
+ AV_CODEC_ID_V210X,
+ AV_CODEC_ID_TMV,
+ AV_CODEC_ID_V210,
+ AV_CODEC_ID_DPX,
+ AV_CODEC_ID_MAD,
+ AV_CODEC_ID_FRWU,
+ AV_CODEC_ID_FLASHSV2,
+ AV_CODEC_ID_CDGRAPHICS,
+ AV_CODEC_ID_R210,
+ AV_CODEC_ID_ANM,
+ AV_CODEC_ID_BINKVIDEO,
+ AV_CODEC_ID_IFF_ILBM,
+#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM
+ AV_CODEC_ID_KGV1,
+ AV_CODEC_ID_YOP,
+ AV_CODEC_ID_VP8,
+ AV_CODEC_ID_PICTOR,
+ AV_CODEC_ID_ANSI,
+ AV_CODEC_ID_A64_MULTI,
+ AV_CODEC_ID_A64_MULTI5,
+ AV_CODEC_ID_R10K,
+ AV_CODEC_ID_MXPEG,
+ AV_CODEC_ID_LAGARITH,
+ AV_CODEC_ID_PRORES,
+ AV_CODEC_ID_JV,
+ AV_CODEC_ID_DFA,
+ AV_CODEC_ID_WMV3IMAGE,
+ AV_CODEC_ID_VC1IMAGE,
+ AV_CODEC_ID_UTVIDEO,
+ AV_CODEC_ID_BMV_VIDEO,
+ AV_CODEC_ID_VBLE,
+ AV_CODEC_ID_DXTORY,
+ AV_CODEC_ID_V410,
+ AV_CODEC_ID_XWD,
+ AV_CODEC_ID_CDXL,
+ AV_CODEC_ID_XBM,
+ AV_CODEC_ID_ZEROCODEC,
+ AV_CODEC_ID_MSS1,
+ AV_CODEC_ID_MSA1,
+ AV_CODEC_ID_TSCC2,
+ AV_CODEC_ID_MTS2,
+ AV_CODEC_ID_CLLC,
+ AV_CODEC_ID_MSS2,
+ AV_CODEC_ID_VP9,
+ AV_CODEC_ID_AIC,
+ AV_CODEC_ID_ESCAPE130,
+ AV_CODEC_ID_G2M,
+ AV_CODEC_ID_WEBP,
+ AV_CODEC_ID_HNM4_VIDEO,
+ AV_CODEC_ID_HEVC,
+#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC
+ AV_CODEC_ID_FIC,
+ AV_CODEC_ID_ALIAS_PIX,
+ AV_CODEC_ID_BRENDER_PIX,
+ AV_CODEC_ID_PAF_VIDEO,
+ AV_CODEC_ID_EXR,
+ AV_CODEC_ID_VP7,
+ AV_CODEC_ID_SANM,
+ AV_CODEC_ID_SGIRLE,
+ AV_CODEC_ID_MVC1,
+ AV_CODEC_ID_MVC2,
+ AV_CODEC_ID_HQX,
+ AV_CODEC_ID_TDSC,
+ AV_CODEC_ID_HQ_HQA,
+ AV_CODEC_ID_HAP,
+ AV_CODEC_ID_DDS,
+ AV_CODEC_ID_DXV,
+ AV_CODEC_ID_SCREENPRESSO,
+ AV_CODEC_ID_RSCC,
+
+ AV_CODEC_ID_Y41P = 0x8000,
+ AV_CODEC_ID_AVRP,
+ AV_CODEC_ID_012V,
+ AV_CODEC_ID_AVUI,
+ AV_CODEC_ID_AYUV,
+ AV_CODEC_ID_TARGA_Y216,
+ AV_CODEC_ID_V308,
+ AV_CODEC_ID_V408,
+ AV_CODEC_ID_YUV4,
+ AV_CODEC_ID_AVRN,
+ AV_CODEC_ID_CPIA,
+ AV_CODEC_ID_XFACE,
+ AV_CODEC_ID_SNOW,
+ AV_CODEC_ID_SMVJPEG,
+ AV_CODEC_ID_APNG,
+ AV_CODEC_ID_DAALA,
+ AV_CODEC_ID_CFHD,
+ AV_CODEC_ID_TRUEMOTION2RT,
+ AV_CODEC_ID_M101,
+ AV_CODEC_ID_MAGICYUV,
+ AV_CODEC_ID_SHEERVIDEO,
+ AV_CODEC_ID_YLC,
+ AV_CODEC_ID_PSD,
+ AV_CODEC_ID_PIXLET,
+ AV_CODEC_ID_SPEEDHQ,
+ AV_CODEC_ID_FMVC,
+ AV_CODEC_ID_SCPR,
+ AV_CODEC_ID_CLEARVIDEO,
+ AV_CODEC_ID_XPM,
+ AV_CODEC_ID_AV1,
+ AV_CODEC_ID_BITPACKED,
+ AV_CODEC_ID_MSCC,
+ AV_CODEC_ID_SRGC,
+ AV_CODEC_ID_SVG,
+ AV_CODEC_ID_GDV,
+ AV_CODEC_ID_FITS,
+
+ /* various PCM "codecs" */
+ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
+ AV_CODEC_ID_PCM_S16LE = 0x10000,
+ AV_CODEC_ID_PCM_S16BE,
+ AV_CODEC_ID_PCM_U16LE,
+ AV_CODEC_ID_PCM_U16BE,
+ AV_CODEC_ID_PCM_S8,
+ AV_CODEC_ID_PCM_U8,
+ AV_CODEC_ID_PCM_MULAW,
+ AV_CODEC_ID_PCM_ALAW,
+ AV_CODEC_ID_PCM_S32LE,
+ AV_CODEC_ID_PCM_S32BE,
+ AV_CODEC_ID_PCM_U32LE,
+ AV_CODEC_ID_PCM_U32BE,
+ AV_CODEC_ID_PCM_S24LE,
+ AV_CODEC_ID_PCM_S24BE,
+ AV_CODEC_ID_PCM_U24LE,
+ AV_CODEC_ID_PCM_U24BE,
+ AV_CODEC_ID_PCM_S24DAUD,
+ AV_CODEC_ID_PCM_ZORK,
+ AV_CODEC_ID_PCM_S16LE_PLANAR,
+ AV_CODEC_ID_PCM_DVD,
+ AV_CODEC_ID_PCM_F32BE,
+ AV_CODEC_ID_PCM_F32LE,
+ AV_CODEC_ID_PCM_F64BE,
+ AV_CODEC_ID_PCM_F64LE,
+ AV_CODEC_ID_PCM_BLURAY,
+ AV_CODEC_ID_PCM_LXF,
+ AV_CODEC_ID_S302M,
+ AV_CODEC_ID_PCM_S8_PLANAR,
+ AV_CODEC_ID_PCM_S24LE_PLANAR,
+ AV_CODEC_ID_PCM_S32LE_PLANAR,
+ AV_CODEC_ID_PCM_S16BE_PLANAR,
+
+ AV_CODEC_ID_PCM_S64LE = 0x10800,
+ AV_CODEC_ID_PCM_S64BE,
+ AV_CODEC_ID_PCM_F16LE,
+ AV_CODEC_ID_PCM_F24LE,
+
+ /* various ADPCM codecs */
+ AV_CODEC_ID_ADPCM_IMA_QT = 0x11000,
+ AV_CODEC_ID_ADPCM_IMA_WAV,
+ AV_CODEC_ID_ADPCM_IMA_DK3,
+ AV_CODEC_ID_ADPCM_IMA_DK4,
+ AV_CODEC_ID_ADPCM_IMA_WS,
+ AV_CODEC_ID_ADPCM_IMA_SMJPEG,
+ AV_CODEC_ID_ADPCM_MS,
+ AV_CODEC_ID_ADPCM_4XM,
+ AV_CODEC_ID_ADPCM_XA,
+ AV_CODEC_ID_ADPCM_ADX,
+ AV_CODEC_ID_ADPCM_EA,
+ AV_CODEC_ID_ADPCM_G726,
+ AV_CODEC_ID_ADPCM_CT,
+ AV_CODEC_ID_ADPCM_SWF,
+ AV_CODEC_ID_ADPCM_YAMAHA,
+ AV_CODEC_ID_ADPCM_SBPRO_4,
+ AV_CODEC_ID_ADPCM_SBPRO_3,
+ AV_CODEC_ID_ADPCM_SBPRO_2,
+ AV_CODEC_ID_ADPCM_THP,
+ AV_CODEC_ID_ADPCM_IMA_AMV,
+ AV_CODEC_ID_ADPCM_EA_R1,
+ AV_CODEC_ID_ADPCM_EA_R3,
+ AV_CODEC_ID_ADPCM_EA_R2,
+ AV_CODEC_ID_ADPCM_IMA_EA_SEAD,
+ AV_CODEC_ID_ADPCM_IMA_EA_EACS,
+ AV_CODEC_ID_ADPCM_EA_XAS,
+ AV_CODEC_ID_ADPCM_EA_MAXIS_XA,
+ AV_CODEC_ID_ADPCM_IMA_ISS,
+ AV_CODEC_ID_ADPCM_G722,
+ AV_CODEC_ID_ADPCM_IMA_APC,
+ AV_CODEC_ID_ADPCM_VIMA,
+
+ AV_CODEC_ID_ADPCM_AFC = 0x11800,
+ AV_CODEC_ID_ADPCM_IMA_OKI,
+ AV_CODEC_ID_ADPCM_DTK,
+ AV_CODEC_ID_ADPCM_IMA_RAD,
+ AV_CODEC_ID_ADPCM_G726LE,
+ AV_CODEC_ID_ADPCM_THP_LE,
+ AV_CODEC_ID_ADPCM_PSX,
+ AV_CODEC_ID_ADPCM_AICA,
+ AV_CODEC_ID_ADPCM_IMA_DAT4,
+ AV_CODEC_ID_ADPCM_MTAF,
+
+ /* AMR */
+ AV_CODEC_ID_AMR_NB = 0x12000,
+ AV_CODEC_ID_AMR_WB,
+
+ /* RealAudio codecs*/
+ AV_CODEC_ID_RA_144 = 0x13000,
+ AV_CODEC_ID_RA_288,
+
+ /* various DPCM codecs */
+ AV_CODEC_ID_ROQ_DPCM = 0x14000,
+ AV_CODEC_ID_INTERPLAY_DPCM,
+ AV_CODEC_ID_XAN_DPCM,
+ AV_CODEC_ID_SOL_DPCM,
+
+ AV_CODEC_ID_SDX2_DPCM = 0x14800,
+ AV_CODEC_ID_GREMLIN_DPCM,
+
+ /* audio codecs */
+ AV_CODEC_ID_MP2 = 0x15000,
+ AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3
+ AV_CODEC_ID_AAC,
+ AV_CODEC_ID_AC3,
+ AV_CODEC_ID_DTS,
+ AV_CODEC_ID_VORBIS,
+ AV_CODEC_ID_DVAUDIO,
+ AV_CODEC_ID_WMAV1,
+ AV_CODEC_ID_WMAV2,
+ AV_CODEC_ID_MACE3,
+ AV_CODEC_ID_MACE6,
+ AV_CODEC_ID_VMDAUDIO,
+ AV_CODEC_ID_FLAC,
+ AV_CODEC_ID_MP3ADU,
+ AV_CODEC_ID_MP3ON4,
+ AV_CODEC_ID_SHORTEN,
+ AV_CODEC_ID_ALAC,
+ AV_CODEC_ID_WESTWOOD_SND1,
+ AV_CODEC_ID_GSM, ///< as in Berlin toast format
+ AV_CODEC_ID_QDM2,
+ AV_CODEC_ID_COOK,
+ AV_CODEC_ID_TRUESPEECH,
+ AV_CODEC_ID_TTA,
+ AV_CODEC_ID_SMACKAUDIO,
+ AV_CODEC_ID_QCELP,
+ AV_CODEC_ID_WAVPACK,
+ AV_CODEC_ID_DSICINAUDIO,
+ AV_CODEC_ID_IMC,
+ AV_CODEC_ID_MUSEPACK7,
+ AV_CODEC_ID_MLP,
+ AV_CODEC_ID_GSM_MS, /* as found in WAV */
+ AV_CODEC_ID_ATRAC3,
+ AV_CODEC_ID_APE,
+ AV_CODEC_ID_NELLYMOSER,
+ AV_CODEC_ID_MUSEPACK8,
+ AV_CODEC_ID_SPEEX,
+ AV_CODEC_ID_WMAVOICE,
+ AV_CODEC_ID_WMAPRO,
+ AV_CODEC_ID_WMALOSSLESS,
+ AV_CODEC_ID_ATRAC3P,
+ AV_CODEC_ID_EAC3,
+ AV_CODEC_ID_SIPR,
+ AV_CODEC_ID_MP1,
+ AV_CODEC_ID_TWINVQ,
+ AV_CODEC_ID_TRUEHD,
+ AV_CODEC_ID_MP4ALS,
+ AV_CODEC_ID_ATRAC1,
+ AV_CODEC_ID_BINKAUDIO_RDFT,
+ AV_CODEC_ID_BINKAUDIO_DCT,
+ AV_CODEC_ID_AAC_LATM,
+ AV_CODEC_ID_QDMC,
+ AV_CODEC_ID_CELT,
+ AV_CODEC_ID_G723_1,
+ AV_CODEC_ID_G729,
+ AV_CODEC_ID_8SVX_EXP,
+ AV_CODEC_ID_8SVX_FIB,
+ AV_CODEC_ID_BMV_AUDIO,
+ AV_CODEC_ID_RALF,
+ AV_CODEC_ID_IAC,
+ AV_CODEC_ID_ILBC,
+ AV_CODEC_ID_OPUS,
+ AV_CODEC_ID_COMFORT_NOISE,
+ AV_CODEC_ID_TAK,
+ AV_CODEC_ID_METASOUND,
+ AV_CODEC_ID_PAF_AUDIO,
+ AV_CODEC_ID_ON2AVC,
+ AV_CODEC_ID_DSS_SP,
+ AV_CODEC_ID_CODEC2,
+
+ AV_CODEC_ID_FFWAVESYNTH = 0x15800,
+ AV_CODEC_ID_SONIC,
+ AV_CODEC_ID_SONIC_LS,
+ AV_CODEC_ID_EVRC,
+ AV_CODEC_ID_SMV,
+ AV_CODEC_ID_DSD_LSBF,
+ AV_CODEC_ID_DSD_MSBF,
+ AV_CODEC_ID_DSD_LSBF_PLANAR,
+ AV_CODEC_ID_DSD_MSBF_PLANAR,
+ AV_CODEC_ID_4GV,
+ AV_CODEC_ID_INTERPLAY_ACM,
+ AV_CODEC_ID_XMA1,
+ AV_CODEC_ID_XMA2,
+ AV_CODEC_ID_DST,
+ AV_CODEC_ID_ATRAC3AL,
+ AV_CODEC_ID_ATRAC3PAL,
+ AV_CODEC_ID_DOLBY_E,
+ AV_CODEC_ID_APTX,
+ AV_CODEC_ID_APTX_HD,
+ AV_CODEC_ID_SBC,
+
+ /* subtitle codecs */
+ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs.
+ AV_CODEC_ID_DVD_SUBTITLE = 0x17000,
+ AV_CODEC_ID_DVB_SUBTITLE,
+ AV_CODEC_ID_TEXT, ///< raw UTF-8 text
+ AV_CODEC_ID_XSUB,
+ AV_CODEC_ID_SSA,
+ AV_CODEC_ID_MOV_TEXT,
+ AV_CODEC_ID_HDMV_PGS_SUBTITLE,
+ AV_CODEC_ID_DVB_TELETEXT,
+ AV_CODEC_ID_SRT,
+
+ AV_CODEC_ID_MICRODVD = 0x17800,
+ AV_CODEC_ID_EIA_608,
+ AV_CODEC_ID_JACOSUB,
+ AV_CODEC_ID_SAMI,
+ AV_CODEC_ID_REALTEXT,
+ AV_CODEC_ID_STL,
+ AV_CODEC_ID_SUBVIEWER1,
+ AV_CODEC_ID_SUBVIEWER,
+ AV_CODEC_ID_SUBRIP,
+ AV_CODEC_ID_WEBVTT,
+ AV_CODEC_ID_MPL2,
+ AV_CODEC_ID_VPLAYER,
+ AV_CODEC_ID_PJS,
+ AV_CODEC_ID_ASS,
+ AV_CODEC_ID_HDMV_TEXT_SUBTITLE,
+
+ /* other specific kind of codecs (generally used for attachments) */
+ AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs.
+ AV_CODEC_ID_TTF = 0x18000,
+
+ AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream.
+ AV_CODEC_ID_BINTEXT = 0x18800,
+ AV_CODEC_ID_XBIN,
+ AV_CODEC_ID_IDF,
+ AV_CODEC_ID_OTF,
+ AV_CODEC_ID_SMPTE_KLV,
+ AV_CODEC_ID_DVD_NAV,
+ AV_CODEC_ID_TIMED_ID3,
+ AV_CODEC_ID_BIN_DATA,
+
+
+ AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it
+
+ AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS
+ * stream (only used by libavformat) */
+ AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems
+ * stream (only used by libavformat) */
+ AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information.
+ AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket
+};
+
+/**
+ * This struct describes the properties of a single codec described by an
+ * AVCodecID.
+ * @see avcodec_descriptor_get()
+ */
+typedef struct AVCodecDescriptor {
+ enum AVCodecID id;
+ enum AVMediaType type;
+ /**
+ * Name of the codec described by this descriptor. It is non-empty and
+ * unique for each codec descriptor. It should contain alphanumeric
+ * characters and '_' only.
+ */
+ const char *name;
+ /**
+ * A more descriptive name for this codec. May be NULL.
+ */
+ const char *long_name;
+ /**
+ * Codec properties, a combination of AV_CODEC_PROP_* flags.
+ */
+ int props;
+ /**
+ * MIME type(s) associated with the codec.
+ * May be NULL; if not, a NULL-terminated array of MIME types.
+ * The first item is always non-NULL and is the preferred MIME type.
+ */
+ const char *const *mime_types;
+ /**
+ * If non-NULL, an array of profiles recognized for this codec.
+ * Terminated with FF_PROFILE_UNKNOWN.
+ */
+ const struct AVProfile *profiles;
+} AVCodecDescriptor;
+
+/**
+ * Codec uses only intra compression.
+ * Video and audio codecs only.
+ */
+#define AV_CODEC_PROP_INTRA_ONLY (1 << 0)
+/**
+ * Codec supports lossy compression. Audio and video codecs only.
+ * @note a codec may support both lossy and lossless
+ * compression modes
+ */
+#define AV_CODEC_PROP_LOSSY (1 << 1)
+/**
+ * Codec supports lossless compression. Audio and video codecs only.
+ */
+#define AV_CODEC_PROP_LOSSLESS (1 << 2)
+/**
+ * Codec supports frame reordering. That is, the coded order (the order in which
+ * the encoded packets are output by the encoders / stored / input to the
+ * decoders) may be different from the presentation order of the corresponding
+ * frames.
+ *
+ * For codecs that do not have this property set, PTS and DTS should always be
+ * equal.
+ */
+#define AV_CODEC_PROP_REORDER (1 << 3)
+/**
+ * Subtitle codec is bitmap based
+ * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field.
+ */
+#define AV_CODEC_PROP_BITMAP_SUB (1 << 16)
+/**
+ * Subtitle codec is text based.
+ * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field.
+ */
+#define AV_CODEC_PROP_TEXT_SUB (1 << 17)
+
+/**
+ * @ingroup lavc_decoding
+ * Required number of additionally allocated bytes at the end of the input bitstream for decoding.
+ * This is mainly needed because some optimized bitstream readers read
+ * 32 or 64 bit at once and could read over the end.<br>
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged
+ * MPEG bitstreams could cause overread and segfault.
+ */
+#define AV_INPUT_BUFFER_PADDING_SIZE 64
+
+/**
+ * @ingroup lavc_encoding
+ * minimum encoding buffer size
+ * Used to avoid some checks during header writing.
+ */
+#define AV_INPUT_BUFFER_MIN_SIZE 16384
+
+/**
+ * @ingroup lavc_decoding
+ */
+enum AVDiscard{
+ /* We leave some space between them for extensions (drop some
+ * keyframes for intra-only or drop just some bidir frames). */
+ AVDISCARD_NONE =-16, ///< discard nothing
+ AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi
+ AVDISCARD_NONREF = 8, ///< discard all non reference
+ AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames
+ AVDISCARD_NONINTRA= 24, ///< discard all non intra frames
+ AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes
+ AVDISCARD_ALL = 48, ///< discard all
+};
+
+enum AVAudioServiceType {
+ AV_AUDIO_SERVICE_TYPE_MAIN = 0,
+ AV_AUDIO_SERVICE_TYPE_EFFECTS = 1,
+ AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2,
+ AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3,
+ AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4,
+ AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5,
+ AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6,
+ AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7,
+ AV_AUDIO_SERVICE_TYPE_KARAOKE = 8,
+ AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI
+};
+
+/**
+ * @ingroup lavc_encoding
+ */
+typedef struct RcOverride{
+ int start_frame;
+ int end_frame;
+ int qscale; // If this is 0 then quality_factor will be used instead.
+ float quality_factor;
+} RcOverride;
+
+/* encoding support
+ These flags can be passed in AVCodecContext.flags before initialization.
+ Note: Not everything is supported yet.
+*/
+
+/**
+ * Allow decoders to produce frames with data planes that are not aligned
+ * to CPU requirements (e.g. due to cropping).
+ */
+#define AV_CODEC_FLAG_UNALIGNED (1 << 0)
+/**
+ * Use fixed qscale.
+ */
+#define AV_CODEC_FLAG_QSCALE (1 << 1)
+/**
+ * 4 MV per MB allowed / advanced prediction for H.263.
+ */
+#define AV_CODEC_FLAG_4MV (1 << 2)
+/**
+ * Output even those frames that might be corrupted.
+ */
+#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3)
+/**
+ * Use qpel MC.
+ */
+#define AV_CODEC_FLAG_QPEL (1 << 4)
+/**
+ * Use internal 2pass ratecontrol in first pass mode.
+ */
+#define AV_CODEC_FLAG_PASS1 (1 << 9)
+/**
+ * Use internal 2pass ratecontrol in second pass mode.
+ */
+#define AV_CODEC_FLAG_PASS2 (1 << 10)
+/**
+ * loop filter.
+ */
+#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11)
+/**
+ * Only decode/encode grayscale.
+ */
+#define AV_CODEC_FLAG_GRAY (1 << 13)
+/**
+ * error[?] variables will be set during encoding.
+ */
+#define AV_CODEC_FLAG_PSNR (1 << 15)
+/**
+ * Input bitstream might be truncated at a random location
+ * instead of only at frame boundaries.
+ */
+#define AV_CODEC_FLAG_TRUNCATED (1 << 16)
+/**
+ * Use interlaced DCT.
+ */
+#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18)
+/**
+ * Force low delay.
+ */
+#define AV_CODEC_FLAG_LOW_DELAY (1 << 19)
+/**
+ * Place global headers in extradata instead of every keyframe.
+ */
+#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
+/**
+ * Use only bitexact stuff (except (I)DCT).
+ */
+#define AV_CODEC_FLAG_BITEXACT (1 << 23)
+/* Fx : Flag for H.263+ extra options */
+/**
+ * H.263 advanced intra coding / MPEG-4 AC prediction
+ */
+#define AV_CODEC_FLAG_AC_PRED (1 << 24)
+/**
+ * interlaced motion estimation
+ */
+#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29)
+#define AV_CODEC_FLAG_CLOSED_GOP (1U << 31)
+
+/**
+ * Allow non spec compliant speedup tricks.
+ */
+#define AV_CODEC_FLAG2_FAST (1 << 0)
+/**
+ * Skip bitstream encoding.
+ */
+#define AV_CODEC_FLAG2_NO_OUTPUT (1 << 2)
+/**
+ * Place global headers at every keyframe instead of in extradata.
+ */
+#define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3)
+
+/**
+ * timecode is in drop frame format. DEPRECATED!!!!
+ */
+#define AV_CODEC_FLAG2_DROP_FRAME_TIMECODE (1 << 13)
+
+/**
+ * Input bitstream might be truncated at a packet boundaries
+ * instead of only at frame boundaries.
+ */
+#define AV_CODEC_FLAG2_CHUNKS (1 << 15)
+/**
+ * Discard cropping information from SPS.
+ */
+#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16)
+
+/**
+ * Show all frames before the first keyframe
+ */
+#define AV_CODEC_FLAG2_SHOW_ALL (1 << 22)
+/**
+ * Export motion vectors through frame side data
+ */
+#define AV_CODEC_FLAG2_EXPORT_MVS (1 << 28)
+/**
+ * Do not skip samples and export skip information as frame side data
+ */
+#define AV_CODEC_FLAG2_SKIP_MANUAL (1 << 29)
+/**
+ * Do not reset ASS ReadOrder field on flush (subtitles decoding)
+ */
+#define AV_CODEC_FLAG2_RO_FLUSH_NOOP (1 << 30)
+
+/* Unsupported options :
+ * Syntax Arithmetic coding (SAC)
+ * Reference Picture Selection
+ * Independent Segment Decoding */
+/* /Fx */
+/* codec capabilities */
+
+/**
+ * Decoder can use draw_horiz_band callback.
+ */
+#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0)
+/**
+ * Codec uses get_buffer() for allocating buffers and supports custom allocators.
+ * If not set, it might not use get_buffer() at all or use operations that
+ * assume the buffer was allocated by avcodec_default_get_buffer.
+ */
+#define AV_CODEC_CAP_DR1 (1 << 1)
+#define AV_CODEC_CAP_TRUNCATED (1 << 3)
+/**
+ * Encoder or decoder requires flushing with NULL input at the end in order to
+ * give the complete and correct output.
+ *
+ * NOTE: If this flag is not set, the codec is guaranteed to never be fed with
+ * with NULL data. The user can still send NULL data to the public encode
+ * or decode function, but libavcodec will not pass it along to the codec
+ * unless this flag is set.
+ *
+ * Decoders:
+ * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL,
+ * avpkt->size=0 at the end to get the delayed data until the decoder no longer
+ * returns frames.
+ *
+ * Encoders:
+ * The encoder needs to be fed with NULL data at the end of encoding until the
+ * encoder no longer returns data.
+ *
+ * NOTE: For encoders implementing the AVCodec.encode2() function, setting this
+ * flag also means that the encoder must set the pts and duration for
+ * each output packet. If this flag is not set, the pts and duration will
+ * be determined by libavcodec from the input frame.
+ */
+#define AV_CODEC_CAP_DELAY (1 << 5)
+/**
+ * Codec can be fed a final frame with a smaller size.
+ * This can be used to prevent truncation of the last audio samples.
+ */
+#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6)
+
+/**
+ * Codec can output multiple frames per AVPacket
+ * Normally demuxers return one frame at a time, demuxers which do not do
+ * are connected to a parser to split what they return into proper frames.
+ * This flag is reserved to the very rare category of codecs which have a
+ * bitstream that cannot be split into frames without timeconsuming
+ * operations like full decoding. Demuxers carrying such bitstreams thus
+ * may return multiple frames in a packet. This has many disadvantages like
+ * prohibiting stream copy in many cases thus it should only be considered
+ * as a last resort.
+ */
+#define AV_CODEC_CAP_SUBFRAMES (1 << 8)
+/**
+ * Codec is experimental and is thus avoided in favor of non experimental
+ * encoders
+ */
+#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9)
+/**
+ * Codec should fill in channel configuration and samplerate instead of container
+ */
+#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10)
+/**
+ * Codec supports frame-level multithreading.
+ */
+#define AV_CODEC_CAP_FRAME_THREADS (1 << 12)
+/**
+ * Codec supports slice-based (or partition-based) multithreading.
+ */
+#define AV_CODEC_CAP_SLICE_THREADS (1 << 13)
+/**
+ * Codec supports changed parameters at any point.
+ */
+#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14)
+/**
+ * Codec supports avctx->thread_count == 0 (auto).
+ */
+#define AV_CODEC_CAP_AUTO_THREADS (1 << 15)
+/**
+ * Audio encoder supports receiving a different number of samples in each call.
+ */
+#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16)
+/**
+ * Decoder is not a preferred choice for probing.
+ * This indicates that the decoder is not a good choice for probing.
+ * It could for example be an expensive to spin up hardware decoder,
+ * or it could simply not provide a lot of useful information about
+ * the stream.
+ * A decoder marked with this flag should only be used as last resort
+ * choice for probing.
+ */
+#define AV_CODEC_CAP_AVOID_PROBING (1 << 17)
+/**
+ * Codec is intra only.
+ */
+#define AV_CODEC_CAP_INTRA_ONLY 0x40000000
+/**
+ * Codec is lossless.
+ */
+#define AV_CODEC_CAP_LOSSLESS 0x80000000
+
+/**
+ * Codec is backed by a hardware implementation. Typically used to
+ * identify a non-hwaccel hardware decoder. For information about hwaccels, use
+ * avcodec_get_hw_config() instead.
+ */
+#define AV_CODEC_CAP_HARDWARE (1 << 18)
+
+/**
+ * Codec is potentially backed by a hardware implementation, but not
+ * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the
+ * implementation provides some sort of internal fallback.
+ */
+#define AV_CODEC_CAP_HYBRID (1 << 19)
+
+/**
+ * Pan Scan area.
+ * This specifies the area which should be displayed.
+ * Note there may be multiple such areas for one frame.
+ */
+typedef struct AVPanScan {
+ /**
+ * id
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ int id;
+
+ /**
+ * width and height in 1/16 pel
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ int width;
+ int height;
+
+ /**
+ * position of the top left corner in 1/16 pel for up to 3 fields/frames
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ int16_t position[3][2];
+} AVPanScan;
+
+/**
+ * This structure describes the bitrate properties of an encoded bitstream. It
+ * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD
+ * parameters for H.264/HEVC.
+ */
+typedef struct AVCPBProperties {
+ /**
+ * Maximum bitrate of the stream, in bits per second.
+ * Zero if unknown or unspecified.
+ */
+ int max_bitrate;
+ /**
+ * Minimum bitrate of the stream, in bits per second.
+ * Zero if unknown or unspecified.
+ */
+ int min_bitrate;
+ /**
+ * Average bitrate of the stream, in bits per second.
+ * Zero if unknown or unspecified.
+ */
+ int avg_bitrate;
+
+ /**
+ * The size of the buffer to which the ratecontrol is applied, in bits.
+ * Zero if unknown or unspecified.
+ */
+ int buffer_size;
+
+ /**
+ * The delay between the time the packet this structure is associated with
+ * is received and the time when it should be decoded, in periods of a 27MHz
+ * clock.
+ *
+ * UINT64_MAX when unknown or unspecified.
+ */
+ uint64_t vbv_delay;
+} AVCPBProperties;
+
+/**
+ * The decoder will keep a reference to the frame and may reuse it later.
+ */
+#define AV_GET_BUFFER_FLAG_REF (1 << 0)
+
+/**
+ * @defgroup lavc_packet AVPacket
+ *
+ * Types and functions for working with AVPacket.
+ * @{
+ */
+enum AVPacketSideDataType {
+ /**
+ * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE
+ * bytes worth of palette. This side data signals that a new palette is
+ * present.
+ */
+ AV_PKT_DATA_PALETTE,
+
+ /**
+ * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format
+ * that the extradata buffer was changed and the receiving side should
+ * act upon it appropriately. The new extradata is embedded in the side
+ * data buffer and should be immediately used for processing the current
+ * frame or packet.
+ */
+ AV_PKT_DATA_NEW_EXTRADATA,
+
+ /**
+ * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows:
+ * @code
+ * u32le param_flags
+ * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT)
+ * s32le channel_count
+ * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT)
+ * u64le channel_layout
+ * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE)
+ * s32le sample_rate
+ * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS)
+ * s32le width
+ * s32le height
+ * @endcode
+ */
+ AV_PKT_DATA_PARAM_CHANGE,
+
+ /**
+ * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of
+ * structures with info about macroblocks relevant to splitting the
+ * packet into smaller packets on macroblock edges (e.g. as for RFC 2190).
+ * That is, it does not necessarily contain info about all macroblocks,
+ * as long as the distance between macroblocks in the info is smaller
+ * than the target payload size.
+ * Each MB info structure is 12 bytes, and is laid out as follows:
+ * @code
+ * u32le bit offset from the start of the packet
+ * u8 current quantizer at the start of the macroblock
+ * u8 GOB number
+ * u16le macroblock address within the GOB
+ * u8 horizontal MV predictor
+ * u8 vertical MV predictor
+ * u8 horizontal MV predictor for block number 3
+ * u8 vertical MV predictor for block number 3
+ * @endcode
+ */
+ AV_PKT_DATA_H263_MB_INFO,
+
+ /**
+ * This side data should be associated with an audio stream and contains
+ * ReplayGain information in form of the AVReplayGain struct.
+ */
+ AV_PKT_DATA_REPLAYGAIN,
+
+ /**
+ * This side data contains a 3x3 transformation matrix describing an affine
+ * transformation that needs to be applied to the decoded video frames for
+ * correct presentation.
+ *
+ * See libavutil/display.h for a detailed description of the data.
+ */
+ AV_PKT_DATA_DISPLAYMATRIX,
+
+ /**
+ * This side data should be associated with a video stream and contains
+ * Stereoscopic 3D information in form of the AVStereo3D struct.
+ */
+ AV_PKT_DATA_STEREO3D,
+
+ /**
+ * This side data should be associated with an audio stream and corresponds
+ * to enum AVAudioServiceType.
+ */
+ AV_PKT_DATA_AUDIO_SERVICE_TYPE,
+
+ /**
+ * This side data contains quality related information from the encoder.
+ * @code
+ * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad).
+ * u8 picture type
+ * u8 error count
+ * u16 reserved
+ * u64le[error count] sum of squared differences between encoder in and output
+ * @endcode
+ */
+ AV_PKT_DATA_QUALITY_STATS,
+
+ /**
+ * This side data contains an integer value representing the stream index
+ * of a "fallback" track. A fallback track indicates an alternate
+ * track to use when the current track can not be decoded for some reason.
+ * e.g. no decoder available for codec.
+ */
+ AV_PKT_DATA_FALLBACK_TRACK,
+
+ /**
+ * This side data corresponds to the AVCPBProperties struct.
+ */
+ AV_PKT_DATA_CPB_PROPERTIES,
+
+ /**
+ * Recommmends skipping the specified number of samples
+ * @code
+ * u32le number of samples to skip from start of this packet
+ * u32le number of samples to skip from end of this packet
+ * u8 reason for start skip
+ * u8 reason for end skip (0=padding silence, 1=convergence)
+ * @endcode
+ */
+ AV_PKT_DATA_SKIP_SAMPLES,
+
+ /**
+ * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that
+ * the packet may contain "dual mono" audio specific to Japanese DTV
+ * and if it is true, recommends only the selected channel to be used.
+ * @code
+ * u8 selected channels (0=mail/left, 1=sub/right, 2=both)
+ * @endcode
+ */
+ AV_PKT_DATA_JP_DUALMONO,
+
+ /**
+ * A list of zero terminated key/value strings. There is no end marker for
+ * the list, so it is required to rely on the side data size to stop.
+ */
+ AV_PKT_DATA_STRINGS_METADATA,
+
+ /**
+ * Subtitle event position
+ * @code
+ * u32le x1
+ * u32le y1
+ * u32le x2
+ * u32le y2
+ * @endcode
+ */
+ AV_PKT_DATA_SUBTITLE_POSITION,
+
+ /**
+ * Data found in BlockAdditional element of matroska container. There is
+ * no end marker for the data, so it is required to rely on the side data
+ * size to recognize the end. 8 byte id (as found in BlockAddId) followed
+ * by data.
+ */
+ AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
+
+ /**
+ * The optional first identifier line of a WebVTT cue.
+ */
+ AV_PKT_DATA_WEBVTT_IDENTIFIER,
+
+ /**
+ * The optional settings (rendering instructions) that immediately
+ * follow the timestamp specifier of a WebVTT cue.
+ */
+ AV_PKT_DATA_WEBVTT_SETTINGS,
+
+ /**
+ * A list of zero terminated key/value strings. There is no end marker for
+ * the list, so it is required to rely on the side data size to stop. This
+ * side data includes updated metadata which appeared in the stream.
+ */
+ AV_PKT_DATA_METADATA_UPDATE,
+
+ /**
+ * MPEGTS stream ID, this is required to pass the stream ID
+ * information from the demuxer to the corresponding muxer.
+ */
+ AV_PKT_DATA_MPEGTS_STREAM_ID,
+
+ /**
+ * Mastering display metadata (based on SMPTE-2086:2014). This metadata
+ * should be associated with a video stream and contains data in the form
+ * of the AVMasteringDisplayMetadata struct.
+ */
+ AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
+
+ /**
+ * This side data should be associated with a video stream and corresponds
+ * to the AVSphericalMapping structure.
+ */
+ AV_PKT_DATA_SPHERICAL,
+
+ /**
+ * Content light level (based on CTA-861.3). This metadata should be
+ * associated with a video stream and contains data in the form of the
+ * AVContentLightMetadata struct.
+ */
+ AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
+
+ /**
+ * ATSC A53 Part 4 Closed Captions. This metadata should be associated with
+ * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data.
+ * The number of bytes of CC data is AVPacketSideData.size.
+ */
+ AV_PKT_DATA_A53_CC,
+
+ /**
+ * This side data is encryption initialization data.
+ * The format is not part of ABI, use av_encryption_init_info_* methods to
+ * access.
+ */
+ AV_PKT_DATA_ENCRYPTION_INIT_INFO,
+
+ /**
+ * This side data contains encryption info for how to decrypt the packet.
+ * The format is not part of ABI, use av_encryption_info_* methods to access.
+ */
+ AV_PKT_DATA_ENCRYPTION_INFO,
+
+ /**
+ * The number of side data types.
+ * This is not part of the public API/ABI in the sense that it may
+ * change when new side data types are added.
+ * This must stay the last enum value.
+ * If its value becomes huge, some code using it
+ * needs to be updated as it assumes it to be smaller than other limits.
+ */
+ AV_PKT_DATA_NB
+};
+
+#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED
+
+typedef struct AVPacketSideData {
+ uint8_t *data;
+ int size;
+ enum AVPacketSideDataType type;
+} AVPacketSideData;
+
+/**
+ * This structure stores compressed data. It is typically exported by demuxers
+ * and then passed as input to decoders, or received as output from encoders and
+ * then passed to muxers.
+ *
+ * For video, it should typically contain one compressed frame. For audio it may
+ * contain several compressed frames. Encoders are allowed to output empty
+ * packets, with no compressed data, containing only side data
+ * (e.g. to update some stream parameters at the end of encoding).
+ *
+ * AVPacket is one of the few structs in FFmpeg, whose size is a part of public
+ * ABI. Thus it may be allocated on stack and no new fields can be added to it
+ * without libavcodec and libavformat major bump.
+ *
+ * The semantics of data ownership depends on the buf field.
+ * If it is set, the packet data is dynamically allocated and is
+ * valid indefinitely until a call to av_packet_unref() reduces the
+ * reference count to 0.
+ *
+ * If the buf field is not set av_packet_ref() would make a copy instead
+ * of increasing the reference count.
+ *
+ * The side data is always allocated with av_malloc(), copied by
+ * av_packet_ref() and freed by av_packet_unref().
+ *
+ * @see av_packet_ref
+ * @see av_packet_unref
+ */
+typedef struct AVPacket {
+ /**
+ * A reference to the reference-counted buffer where the packet data is
+ * stored.
+ * May be NULL, then the packet data is not reference-counted.
+ */
+ AVBufferRef *buf;
+ /**
+ * Presentation timestamp in AVStream->time_base units; the time at which
+ * the decompressed packet will be presented to the user.
+ * Can be AV_NOPTS_VALUE if it is not stored in the file.
+ * pts MUST be larger or equal to dts as presentation cannot happen before
+ * decompression, unless one wants to view hex dumps. Some formats misuse
+ * the terms dts and pts/cts to mean something different. Such timestamps
+ * must be converted to true pts/dts before they are stored in AVPacket.
+ */
+ int64_t pts;
+ /**
+ * Decompression timestamp in AVStream->time_base units; the time at which
+ * the packet is decompressed.
+ * Can be AV_NOPTS_VALUE if it is not stored in the file.
+ */
+ int64_t dts;
+ uint8_t *data;
+ int size;
+ int stream_index;
+ /**
+ * A combination of AV_PKT_FLAG values
+ */
+ int flags;
+ /**
+ * Additional packet data that can be provided by the container.
+ * Packet can contain several types of side information.
+ */
+ AVPacketSideData *side_data;
+ int side_data_elems;
+
+ /**
+ * Duration of this packet in AVStream->time_base units, 0 if unknown.
+ * Equals next_pts - this_pts in presentation order.
+ */
+ int64_t duration;
+
+ int64_t pos; ///< byte position in stream, -1 if unknown
+
+#if FF_API_CONVERGENCE_DURATION
+ /**
+ * @deprecated Same as the duration field, but as int64_t. This was required
+ * for Matroska subtitles, whose duration values could overflow when the
+ * duration field was still an int.
+ */
+ attribute_deprecated
+ int64_t convergence_duration;
+#endif
+} AVPacket;
+#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe
+#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted
+/**
+ * Flag is used to discard packets which are required to maintain valid
+ * decoder state but are not required for output and should be dropped
+ * after decoding.
+ **/
+#define AV_PKT_FLAG_DISCARD 0x0004
+/**
+ * The packet comes from a trusted source.
+ *
+ * Otherwise-unsafe constructs such as arbitrary pointers to data
+ * outside the packet may be followed.
+ */
+#define AV_PKT_FLAG_TRUSTED 0x0008
+/**
+ * Flag is used to indicate packets that contain frames that can
+ * be discarded by the decoder. I.e. Non-reference frames.
+ */
+#define AV_PKT_FLAG_DISPOSABLE 0x0010
+
+
+enum AVSideDataParamChangeFlags {
+ AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001,
+ AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002,
+ AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004,
+ AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008,
+};
+/**
+ * @}
+ */
+
+struct AVCodecInternal;
+
+enum AVFieldOrder {
+ AV_FIELD_UNKNOWN,
+ AV_FIELD_PROGRESSIVE,
+ AV_FIELD_TT, //< Top coded_first, top displayed first
+ AV_FIELD_BB, //< Bottom coded first, bottom displayed first
+ AV_FIELD_TB, //< Top coded first, bottom displayed first
+ AV_FIELD_BT, //< Bottom coded first, top displayed first
+};
+
+/**
+ * main external API structure.
+ * New fields can be added to the end with minor version bumps.
+ * Removal, reordering and changes to existing fields require a major
+ * version bump.
+ * You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user
+ * applications.
+ * The name string for AVOptions options matches the associated command line
+ * parameter name and can be found in libavcodec/options_table.h
+ * The AVOption/command line parameter names differ in some cases from the C
+ * structure field names for historic reasons or brevity.
+ * sizeof(AVCodecContext) must not be used outside libav*.
+ */
+typedef struct AVCodecContext {
+ /**
+ * information on struct for av_log
+ * - set by avcodec_alloc_context3
+ */
+ const AVClass *av_class;
+ int log_level_offset;
+
+ enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */
+ const struct AVCodec *codec;
+ enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */
+
+ /**
+ * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
+ * This is used to work around some encoder bugs.
+ * A demuxer should set this to what is stored in the field used to identify the codec.
+ * If there are multiple such fields in a container then the demuxer should choose the one
+ * which maximizes the information about the used codec.
+ * If the codec tag field in a container is larger than 32 bits then the demuxer should
+ * remap the longer ID to 32 bits with a table or other structure. Alternatively a new
+ * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated
+ * first.
+ * - encoding: Set by user, if not then the default based on codec_id will be used.
+ * - decoding: Set by user, will be converted to uppercase by libavcodec during init.
+ */
+ unsigned int codec_tag;
+
+ void *priv_data;
+
+ /**
+ * Private context used for internal data.
+ *
+ * Unlike priv_data, this is not codec-specific. It is used in general
+ * libavcodec functions.
+ */
+ struct AVCodecInternal *internal;
+
+ /**
+ * Private data of the user, can be used to carry app specific stuff.
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ void *opaque;
+
+ /**
+ * the average bitrate
+ * - encoding: Set by user; unused for constant quantizer encoding.
+ * - decoding: Set by user, may be overwritten by libavcodec
+ * if this info is available in the stream
+ */
+ int64_t bit_rate;
+
+ /**
+ * number of bits the bitstream is allowed to diverge from the reference.
+ * the reference can be CBR (for CBR pass1) or VBR (for pass2)
+ * - encoding: Set by user; unused for constant quantizer encoding.
+ * - decoding: unused
+ */
+ int bit_rate_tolerance;
+
+ /**
+ * Global quality for codecs which cannot change it per frame.
+ * This should be proportional to MPEG-1/2/4 qscale.
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int global_quality;
+
+ /**
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int compression_level;
+#define FF_COMPRESSION_DEFAULT -1
+
+ /**
+ * AV_CODEC_FLAG_*.
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int flags;
+
+ /**
+ * AV_CODEC_FLAG2_*
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int flags2;
+
+ /**
+ * some codecs need / can use extradata like Huffman tables.
+ * MJPEG: Huffman tables
+ * rv10: additional flags
+ * MPEG-4: global headers (they can be in the bitstream or here)
+ * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger
+ * than extradata_size to avoid problems if it is read with the bitstream reader.
+ * The bytewise contents of extradata must not depend on the architecture or CPU endianness.
+ * - encoding: Set/allocated/freed by libavcodec.
+ * - decoding: Set/allocated/freed by user.
+ */
+ uint8_t *extradata;
+ int extradata_size;
+
+ /**
+ * This is the fundamental unit of time (in seconds) in terms
+ * of which frame timestamps are represented. For fixed-fps content,
+ * timebase should be 1/framerate and timestamp increments should be
+ * identically 1.
+ * This often, but not always is the inverse of the frame rate or field rate
+ * for video. 1/time_base is not the average frame rate if the frame rate is not
+ * constant.
+ *
+ * Like containers, elementary streams also can store timestamps, 1/time_base
+ * is the unit in which these timestamps are specified.
+ * As example of such codec time base see ISO/IEC 14496-2:2001(E)
+ * vop_time_increment_resolution and fixed_vop_rate
+ * (fixed_vop_rate == 0 implies that it is different from the framerate)
+ *
+ * - encoding: MUST be set by user.
+ * - decoding: the use of this field for decoding is deprecated.
+ * Use framerate instead.
+ */
+ AVRational time_base;
+
+ /**
+ * For some codecs, the time base is closer to the field rate than the frame rate.
+ * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration
+ * if no telecine is used ...
+ *
+ * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2.
+ */
+ int ticks_per_frame;
+
+ /**
+ * Codec delay.
+ *
+ * Encoding: Number of frames delay there will be from the encoder input to
+ * the decoder output. (we assume the decoder matches the spec)
+ * Decoding: Number of frames delay in addition to what a standard decoder
+ * as specified in the spec would produce.
+ *
+ * Video:
+ * Number of frames the decoded output will be delayed relative to the
+ * encoded input.
+ *
+ * Audio:
+ * For encoding, this field is unused (see initial_padding).
+ *
+ * For decoding, this is the number of samples the decoder needs to
+ * output before the decoder's output is valid. When seeking, you should
+ * start decoding this many samples prior to your desired seek point.
+ *
+ * - encoding: Set by libavcodec.
+ * - decoding: Set by libavcodec.
+ */
+ int delay;
+
+
+ /* video only */
+ /**
+ * picture width / height.
+ *
+ * @note Those fields may not match the values of the last
+ * AVFrame output by avcodec_decode_video2 due frame
+ * reordering.
+ *
+ * - encoding: MUST be set by user.
+ * - decoding: May be set by the user before opening the decoder if known e.g.
+ * from the container. Some decoders will require the dimensions
+ * to be set by the caller. During decoding, the decoder may
+ * overwrite those values as required while parsing the data.
+ */
+ int width, height;
+
+ /**
+ * Bitstream width / height, may be different from width/height e.g. when
+ * the decoded frame is cropped before being output or lowres is enabled.
+ *
+ * @note Those field may not match the value of the last
+ * AVFrame output by avcodec_receive_frame() due frame
+ * reordering.
+ *
+ * - encoding: unused
+ * - decoding: May be set by the user before opening the decoder if known
+ * e.g. from the container. During decoding, the decoder may
+ * overwrite those values as required while parsing the data.
+ */
+ int coded_width, coded_height;
+
+ /**
+ * the number of pictures in a group of pictures, or 0 for intra_only
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int gop_size;
+
+ /**
+ * Pixel format, see AV_PIX_FMT_xxx.
+ * May be set by the demuxer if known from headers.
+ * May be overridden by the decoder if it knows better.
+ *
+ * @note This field may not match the value of the last
+ * AVFrame output by avcodec_receive_frame() due frame
+ * reordering.
+ *
+ * - encoding: Set by user.
+ * - decoding: Set by user if known, overridden by libavcodec while
+ * parsing the data.
+ */
+ enum AVPixelFormat pix_fmt;
+
+ /**
+ * If non NULL, 'draw_horiz_band' is called by the libavcodec
+ * decoder to draw a horizontal band. It improves cache usage. Not
+ * all codecs can do that. You must check the codec capabilities
+ * beforehand.
+ * When multithreading is used, it may be called from multiple threads
+ * at the same time; threads might draw different parts of the same AVFrame,
+ * or multiple AVFrames, and there is no guarantee that slices will be drawn
+ * in order.
+ * The function is also used by hardware acceleration APIs.
+ * It is called at least once during frame decoding to pass
+ * the data needed for hardware render.
+ * In that mode instead of pixel data, AVFrame points to
+ * a structure specific to the acceleration API. The application
+ * reads the structure and can change some fields to indicate progress
+ * or mark state.
+ * - encoding: unused
+ * - decoding: Set by user.
+ * @param height the height of the slice
+ * @param y the y position of the slice
+ * @param type 1->top field, 2->bottom field, 3->frame
+ * @param offset offset into the AVFrame.data from which the slice should be read
+ */
+ void (*draw_horiz_band)(struct AVCodecContext *s,
+ const AVFrame *src, int offset[AV_NUM_DATA_POINTERS],
+ int y, int type, int height);
+
+ /**
+ * callback to negotiate the pixelFormat
+ * @param fmt is the list of formats which are supported by the codec,
+ * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality.
+ * The first is always the native one.
+ * @note The callback may be called again immediately if initialization for
+ * the selected (hardware-accelerated) pixel format failed.
+ * @warning Behavior is undefined if the callback returns a value not
+ * in the fmt list of formats.
+ * @return the chosen format
+ * - encoding: unused
+ * - decoding: Set by user, if not set the native format will be chosen.
+ */
+ enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt);
+
+ /**
+ * maximum number of B-frames between non-B-frames
+ * Note: The output will be delayed by max_b_frames+1 relative to the input.
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int max_b_frames;
+
+ /**
+ * qscale factor between IP and B-frames
+ * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset).
+ * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float b_quant_factor;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int b_frame_strategy;
+#endif
+
+ /**
+ * qscale offset between IP and B-frames
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float b_quant_offset;
+
+ /**
+ * Size of the frame reordering buffer in the decoder.
+ * For MPEG-2 it is 1 IPB or 0 low delay IP.
+ * - encoding: Set by libavcodec.
+ * - decoding: Set by libavcodec.
+ */
+ int has_b_frames;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int mpeg_quant;
+#endif
+
+ /**
+ * qscale factor between P- and I-frames
+ * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset).
+ * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float i_quant_factor;
+
+ /**
+ * qscale offset between P and I-frames
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float i_quant_offset;
+
+ /**
+ * luminance masking (0-> disabled)
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float lumi_masking;
+
+ /**
+ * temporary complexity masking (0-> disabled)
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float temporal_cplx_masking;
+
+ /**
+ * spatial complexity masking (0-> disabled)
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float spatial_cplx_masking;
+
+ /**
+ * p block masking (0-> disabled)
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float p_masking;
+
+ /**
+ * darkness masking (0-> disabled)
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ float dark_masking;
+
+ /**
+ * slice count
+ * - encoding: Set by libavcodec.
+ * - decoding: Set by user (or 0).
+ */
+ int slice_count;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int prediction_method;
+#define FF_PRED_LEFT 0
+#define FF_PRED_PLANE 1
+#define FF_PRED_MEDIAN 2
+#endif
+
+ /**
+ * slice offsets in the frame in bytes
+ * - encoding: Set/allocated by libavcodec.
+ * - decoding: Set/allocated by user (or NULL).
+ */
+ int *slice_offset;
+
+ /**
+ * sample aspect ratio (0 if unknown)
+ * That is the width of a pixel divided by the height of the pixel.
+ * Numerator and denominator must be relatively prime and smaller than 256 for some video standards.
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ AVRational sample_aspect_ratio;
+
+ /**
+ * motion estimation comparison function
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int me_cmp;
+ /**
+ * subpixel motion estimation comparison function
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int me_sub_cmp;
+ /**
+ * macroblock comparison function (not supported yet)
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int mb_cmp;
+ /**
+ * interlaced DCT comparison function
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int ildct_cmp;
+#define FF_CMP_SAD 0
+#define FF_CMP_SSE 1
+#define FF_CMP_SATD 2
+#define FF_CMP_DCT 3
+#define FF_CMP_PSNR 4
+#define FF_CMP_BIT 5
+#define FF_CMP_RD 6
+#define FF_CMP_ZERO 7
+#define FF_CMP_VSAD 8
+#define FF_CMP_VSSE 9
+#define FF_CMP_NSSE 10
+#define FF_CMP_W53 11
+#define FF_CMP_W97 12
+#define FF_CMP_DCTMAX 13
+#define FF_CMP_DCT264 14
+#define FF_CMP_MEDIAN_SAD 15
+#define FF_CMP_CHROMA 256
+
+ /**
+ * ME diamond size & shape
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int dia_size;
+
+ /**
+ * amount of previous MV predictors (2a+1 x 2a+1 square)
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int last_predictor_count;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int pre_me;
+#endif
+
+ /**
+ * motion estimation prepass comparison function
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int me_pre_cmp;
+
+ /**
+ * ME prepass diamond size & shape
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int pre_dia_size;
+
+ /**
+ * subpel ME quality
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int me_subpel_quality;
+
+ /**
+ * maximum motion estimation search range in subpel units
+ * If 0 then no limit.
+ *
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int me_range;
+
+ /**
+ * slice flags
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ int slice_flags;
+#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display
+#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics)
+#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1)
+
+ /**
+ * macroblock decision mode
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int mb_decision;
+#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp
+#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits
+#define FF_MB_DECISION_RD 2 ///< rate distortion
+
+ /**
+ * custom intra quantization matrix
+ * - encoding: Set by user, can be NULL.
+ * - decoding: Set by libavcodec.
+ */
+ uint16_t *intra_matrix;
+
+ /**
+ * custom inter quantization matrix
+ * - encoding: Set by user, can be NULL.
+ * - decoding: Set by libavcodec.
+ */
+ uint16_t *inter_matrix;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int scenechange_threshold;
+
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int noise_reduction;
+#endif
+
+ /**
+ * precision of the intra DC coefficient - 8
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec
+ */
+ int intra_dc_precision;
+
+ /**
+ * Number of macroblock rows at the top which are skipped.
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ int skip_top;
+
+ /**
+ * Number of macroblock rows at the bottom which are skipped.
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ int skip_bottom;
+
+ /**
+ * minimum MB Lagrange multiplier
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int mb_lmin;
+
+ /**
+ * maximum MB Lagrange multiplier
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int mb_lmax;
+
+#if FF_API_PRIVATE_OPT
+ /**
+ * @deprecated use encoder private options instead
+ */
+ attribute_deprecated
+ int me_penalty_compensation;
+#endif
+
+ /**
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int bidir_refine;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int brd_scale;
+#endif
+
+ /**
+ * minimum GOP size
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int keyint_min;
+
+ /**
+ * number of reference frames
+ * - encoding: Set by user.
+ * - decoding: Set by lavc.
+ */
+ int refs;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int chromaoffset;
+#endif
+
+ /**
+ * Note: Value depends upon the compare function used for fullpel ME.
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int mv0_threshold;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int b_sensitivity;
+#endif
+
+ /**
+ * Chromaticity coordinates of the source primaries.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVColorPrimaries color_primaries;
+
+ /**
+ * Color Transfer Characteristic.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVColorTransferCharacteristic color_trc;
+
+ /**
+ * YUV colorspace type.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVColorSpace colorspace;
+
+ /**
+ * MPEG vs JPEG YUV range.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVColorRange color_range;
+
+ /**
+ * This defines the location of chroma samples.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVChromaLocation chroma_sample_location;
+
+ /**
+ * Number of slices.
+ * Indicates number of picture subdivisions. Used for parallelized
+ * decoding.
+ * - encoding: Set by user
+ * - decoding: unused
+ */
+ int slices;
+
+ /** Field order
+ * - encoding: set by libavcodec
+ * - decoding: Set by user.
+ */
+ enum AVFieldOrder field_order;
+
+ /* audio only */
+ int sample_rate; ///< samples per second
+ int channels; ///< number of audio channels
+
+ /**
+ * audio sample format
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ enum AVSampleFormat sample_fmt; ///< sample format
+
+ /* The following data should not be initialized. */
+ /**
+ * Number of samples per channel in an audio frame.
+ *
+ * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame
+ * except the last must contain exactly frame_size samples per channel.
+ * May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the
+ * frame size is not restricted.
+ * - decoding: may be set by some decoders to indicate constant frame size
+ */
+ int frame_size;
+
+ /**
+ * Frame counter, set by libavcodec.
+ *
+ * - decoding: total number of frames returned from the decoder so far.
+ * - encoding: total number of frames passed to the encoder so far.
+ *
+ * @note the counter is not incremented if encoding/decoding resulted in
+ * an error.
+ */
+ int frame_number;
+
+ /**
+ * number of bytes per packet if constant and known or 0
+ * Used by some WAV based audio codecs.
+ */
+ int block_align;
+
+ /**
+ * Audio cutoff bandwidth (0 means "automatic")
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int cutoff;
+
+ /**
+ * Audio channel layout.
+ * - encoding: set by user.
+ * - decoding: set by user, may be overwritten by libavcodec.
+ */
+ uint64_t channel_layout;
+
+ /**
+ * Request decoder to use this channel layout if it can (0 for default)
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ uint64_t request_channel_layout;
+
+ /**
+ * Type of service that the audio stream conveys.
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ enum AVAudioServiceType audio_service_type;
+
+ /**
+ * desired sample format
+ * - encoding: Not used.
+ * - decoding: Set by user.
+ * Decoder will decode to this format if it can.
+ */
+ enum AVSampleFormat request_sample_fmt;
+
+ /**
+ * This callback is called at the beginning of each frame to get data
+ * buffer(s) for it. There may be one contiguous buffer for all the data or
+ * there may be a buffer per each data plane or anything in between. What
+ * this means is, you may set however many entries in buf[] you feel necessary.
+ * Each buffer must be reference-counted using the AVBuffer API (see description
+ * of buf[] below).
+ *
+ * The following fields will be set in the frame before this callback is
+ * called:
+ * - format
+ * - width, height (video only)
+ * - sample_rate, channel_layout, nb_samples (audio only)
+ * Their values may differ from the corresponding values in
+ * AVCodecContext. This callback must use the frame values, not the codec
+ * context values, to calculate the required buffer size.
+ *
+ * This callback must fill the following fields in the frame:
+ * - data[]
+ * - linesize[]
+ * - extended_data:
+ * * if the data is planar audio with more than 8 channels, then this
+ * callback must allocate and fill extended_data to contain all pointers
+ * to all data planes. data[] must hold as many pointers as it can.
+ * extended_data must be allocated with av_malloc() and will be freed in
+ * av_frame_unref().
+ * * otherwise extended_data must point to data
+ * - buf[] must contain one or more pointers to AVBufferRef structures. Each of
+ * the frame's data and extended_data pointers must be contained in these. That
+ * is, one AVBufferRef for each allocated chunk of memory, not necessarily one
+ * AVBufferRef per data[] entry. See: av_buffer_create(), av_buffer_alloc(),
+ * and av_buffer_ref().
+ * - extended_buf and nb_extended_buf must be allocated with av_malloc() by
+ * this callback and filled with the extra buffers if there are more
+ * buffers than buf[] can hold. extended_buf will be freed in
+ * av_frame_unref().
+ *
+ * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call
+ * avcodec_default_get_buffer2() instead of providing buffers allocated by
+ * some other means.
+ *
+ * Each data plane must be aligned to the maximum required by the target
+ * CPU.
+ *
+ * @see avcodec_default_get_buffer2()
+ *
+ * Video:
+ *
+ * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused
+ * (read and/or written to if it is writable) later by libavcodec.
+ *
+ * avcodec_align_dimensions2() should be used to find the required width and
+ * height, as they normally need to be rounded up to the next multiple of 16.
+ *
+ * Some decoders do not support linesizes changing between frames.
+ *
+ * If frame multithreading is used and thread_safe_callbacks is set,
+ * this callback may be called from a different thread, but not from more
+ * than one at once. Does not need to be reentrant.
+ *
+ * @see avcodec_align_dimensions2()
+ *
+ * Audio:
+ *
+ * Decoders request a buffer of a particular size by setting
+ * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may,
+ * however, utilize only part of the buffer by setting AVFrame.nb_samples
+ * to a smaller value in the output frame.
+ *
+ * As a convenience, av_samples_get_buffer_size() and
+ * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2()
+ * functions to find the required data size and to fill data pointers and
+ * linesize. In AVFrame.linesize, only linesize[0] may be set for audio
+ * since all planes must be the same size.
+ *
+ * @see av_samples_get_buffer_size(), av_samples_fill_arrays()
+ *
+ * - encoding: unused
+ * - decoding: Set by libavcodec, user can override.
+ */
+ int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags);
+
+ /**
+ * If non-zero, the decoded audio and video frames returned from
+ * avcodec_decode_video2() and avcodec_decode_audio4() are reference-counted
+ * and are valid indefinitely. The caller must free them with
+ * av_frame_unref() when they are not needed anymore.
+ * Otherwise, the decoded frames must not be freed by the caller and are
+ * only valid until the next decode call.
+ *
+ * This is always automatically enabled if avcodec_receive_frame() is used.
+ *
+ * - encoding: unused
+ * - decoding: set by the caller before avcodec_open2().
+ */
+ attribute_deprecated
+ int refcounted_frames;
+
+ /* - encoding parameters */
+ float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0)
+ float qblur; ///< amount of qscale smoothing over time (0.0-1.0)
+
+ /**
+ * minimum quantizer
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int qmin;
+
+ /**
+ * maximum quantizer
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int qmax;
+
+ /**
+ * maximum quantizer difference between frames
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int max_qdiff;
+
+ /**
+ * decoder bitstream buffer size
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int rc_buffer_size;
+
+ /**
+ * ratecontrol override, see RcOverride
+ * - encoding: Allocated/set/freed by user.
+ * - decoding: unused
+ */
+ int rc_override_count;
+ RcOverride *rc_override;
+
+ /**
+ * maximum bitrate
+ * - encoding: Set by user.
+ * - decoding: Set by user, may be overwritten by libavcodec.
+ */
+ int64_t rc_max_rate;
+
+ /**
+ * minimum bitrate
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int64_t rc_min_rate;
+
+ /**
+ * Ratecontrol attempt to use, at maximum, <value> of what can be used without an underflow.
+ * - encoding: Set by user.
+ * - decoding: unused.
+ */
+ float rc_max_available_vbv_use;
+
+ /**
+ * Ratecontrol attempt to use, at least, <value> times the amount needed to prevent a vbv overflow.
+ * - encoding: Set by user.
+ * - decoding: unused.
+ */
+ float rc_min_vbv_overflow_use;
+
+ /**
+ * Number of bits which should be loaded into the rc buffer before decoding starts.
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int rc_initial_buffer_occupancy;
+
+#if FF_API_CODER_TYPE
+#define FF_CODER_TYPE_VLC 0
+#define FF_CODER_TYPE_AC 1
+#define FF_CODER_TYPE_RAW 2
+#define FF_CODER_TYPE_RLE 3
+ /**
+ * @deprecated use encoder private options instead
+ */
+ attribute_deprecated
+ int coder_type;
+#endif /* FF_API_CODER_TYPE */
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int context_model;
+#endif
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int frame_skip_threshold;
+
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int frame_skip_factor;
+
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int frame_skip_exp;
+
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int frame_skip_cmp;
+#endif /* FF_API_PRIVATE_OPT */
+
+ /**
+ * trellis RD quantization
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int trellis;
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int min_prediction_order;
+
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int max_prediction_order;
+
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int64_t timecode_frame_start;
+#endif
+
+#if FF_API_RTP_CALLBACK
+ /**
+ * @deprecated unused
+ */
+ /* The RTP callback: This function is called */
+ /* every time the encoder has a packet to send. */
+ /* It depends on the encoder if the data starts */
+ /* with a Start Code (it should). H.263 does. */
+ /* mb_nb contains the number of macroblocks */
+ /* encoded in the RTP payload. */
+ attribute_deprecated
+ void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb);
+#endif
+
+#if FF_API_PRIVATE_OPT
+ /** @deprecated use encoder private options instead */
+ attribute_deprecated
+ int rtp_payload_size; /* The size of the RTP payload: the coder will */
+ /* do its best to deliver a chunk with size */
+ /* below rtp_payload_size, the chunk will start */
+ /* with a start code on some codecs like H.263. */
+ /* This doesn't take account of any particular */
+ /* headers inside the transmitted RTP payload. */
+#endif
+
+#if FF_API_STAT_BITS
+ /* statistics, used for 2-pass encoding */
+ attribute_deprecated
+ int mv_bits;
+ attribute_deprecated
+ int header_bits;
+ attribute_deprecated
+ int i_tex_bits;
+ attribute_deprecated
+ int p_tex_bits;
+ attribute_deprecated
+ int i_count;
+ attribute_deprecated
+ int p_count;
+ attribute_deprecated
+ int skip_count;
+ attribute_deprecated
+ int misc_bits;
+
+ /** @deprecated this field is unused */
+ attribute_deprecated
+ int frame_bits;
+#endif
+
+ /**
+ * pass1 encoding statistics output buffer
+ * - encoding: Set by libavcodec.
+ * - decoding: unused
+ */
+ char *stats_out;
+
+ /**
+ * pass2 encoding statistics input buffer
+ * Concatenated stuff from stats_out of pass1 should be placed here.
+ * - encoding: Allocated/set/freed by user.
+ * - decoding: unused
+ */
+ char *stats_in;
+
+ /**
+ * Work around bugs in encoders which sometimes cannot be detected automatically.
+ * - encoding: Set by user
+ * - decoding: Set by user
+ */
+ int workaround_bugs;
+#define FF_BUG_AUTODETECT 1 ///< autodetection
+#define FF_BUG_XVID_ILACE 4
+#define FF_BUG_UMP4 8
+#define FF_BUG_NO_PADDING 16
+#define FF_BUG_AMV 32
+#define FF_BUG_QPEL_CHROMA 64
+#define FF_BUG_STD_QPEL 128
+#define FF_BUG_QPEL_CHROMA2 256
+#define FF_BUG_DIRECT_BLOCKSIZE 512
+#define FF_BUG_EDGE 1024
+#define FF_BUG_HPEL_CHROMA 2048
+#define FF_BUG_DC_CLIP 4096
+#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders.
+#define FF_BUG_TRUNCATED 16384
+#define FF_BUG_IEDGE 32768
+
+ /**
+ * strictly follow the standard (MPEG-4, ...).
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ * Setting this to STRICT or higher means the encoder and decoder will
+ * generally do stupid things, whereas setting it to unofficial or lower
+ * will mean the encoder might produce output that is not supported by all
+ * spec-compliant decoders. Decoders don't differentiate between normal,
+ * unofficial and experimental (that is, they always try to decode things
+ * when they can) unless they are explicitly asked to behave stupidly
+ * (=strictly conform to the specs)
+ */
+ int strict_std_compliance;
+#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software.
+#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences.
+#define FF_COMPLIANCE_NORMAL 0
+#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions
+#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things.
+
+ /**
+ * error concealment flags
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ int error_concealment;
+#define FF_EC_GUESS_MVS 1
+#define FF_EC_DEBLOCK 2
+#define FF_EC_FAVOR_INTER 256
+
+ /**
+ * debug
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int debug;
+#define FF_DEBUG_PICT_INFO 1
+#define FF_DEBUG_RC 2
+#define FF_DEBUG_BITSTREAM 4
+#define FF_DEBUG_MB_TYPE 8
+#define FF_DEBUG_QP 16
+#if FF_API_DEBUG_MV
+/**
+ * @deprecated this option does nothing
+ */
+#define FF_DEBUG_MV 32
+#endif
+#define FF_DEBUG_DCT_COEFF 0x00000040
+#define FF_DEBUG_SKIP 0x00000080
+#define FF_DEBUG_STARTCODE 0x00000100
+#define FF_DEBUG_ER 0x00000400
+#define FF_DEBUG_MMCO 0x00000800
+#define FF_DEBUG_BUGS 0x00001000
+#if FF_API_DEBUG_MV
+#define FF_DEBUG_VIS_QP 0x00002000
+#define FF_DEBUG_VIS_MB_TYPE 0x00004000
+#endif
+#define FF_DEBUG_BUFFERS 0x00008000
+#define FF_DEBUG_THREADS 0x00010000
+#define FF_DEBUG_GREEN_MD 0x00800000
+#define FF_DEBUG_NOMC 0x01000000
+
+#if FF_API_DEBUG_MV
+ /**
+ * debug
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int debug_mv;
+#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 // visualize forward predicted MVs of P-frames
+#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 // visualize forward predicted MVs of B-frames
+#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 // visualize backward predicted MVs of B-frames
+#endif
+
+ /**
+ * Error recognition; may misdetect some more or less valid parts as errors.
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ int err_recognition;
+
+/**
+ * Verify checksums embedded in the bitstream (could be of either encoded or
+ * decoded data, depending on the codec) and print an error message on mismatch.
+ * If AV_EF_EXPLODE is also set, a mismatching checksum will result in the
+ * decoder returning an error.
+ */
+#define AV_EF_CRCCHECK (1<<0)
+#define AV_EF_BITSTREAM (1<<1) ///< detect bitstream specification deviations
+#define AV_EF_BUFFER (1<<2) ///< detect improper bitstream length
+#define AV_EF_EXPLODE (1<<3) ///< abort decoding on minor error detection
+
+#define AV_EF_IGNORE_ERR (1<<15) ///< ignore errors and continue
+#define AV_EF_CAREFUL (1<<16) ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors
+#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliances as errors
+#define AV_EF_AGGRESSIVE (1<<18) ///< consider things that a sane encoder should not do as an error
+
+
+ /**
+ * opaque 64-bit number (generally a PTS) that will be reordered and
+ * output in AVFrame.reordered_opaque
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ int64_t reordered_opaque;
+
+ /**
+ * Hardware accelerator in use
+ * - encoding: unused.
+ * - decoding: Set by libavcodec
+ */
+ const struct AVHWAccel *hwaccel;
+
+ /**
+ * Hardware accelerator context.
+ * For some hardware accelerators, a global context needs to be
+ * provided by the user. In that case, this holds display-dependent
+ * data FFmpeg cannot instantiate itself. Please refer to the
+ * FFmpeg HW accelerator documentation to know how to fill this
+ * is. e.g. for VA API, this is a struct vaapi_context.
+ * - encoding: unused
+ * - decoding: Set by user
+ */
+ void *hwaccel_context;
+
+ /**
+ * error
+ * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR.
+ * - decoding: unused
+ */
+ uint64_t error[AV_NUM_DATA_POINTERS];
+
+ /**
+ * DCT algorithm, see FF_DCT_* below
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int dct_algo;
+#define FF_DCT_AUTO 0
+#define FF_DCT_FASTINT 1
+#define FF_DCT_INT 2
+#define FF_DCT_MMX 3
+#define FF_DCT_ALTIVEC 5
+#define FF_DCT_FAAN 6
+
+ /**
+ * IDCT algorithm, see FF_IDCT_* below.
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int idct_algo;
+#define FF_IDCT_AUTO 0
+#define FF_IDCT_INT 1
+#define FF_IDCT_SIMPLE 2
+#define FF_IDCT_SIMPLEMMX 3
+#define FF_IDCT_ARM 7
+#define FF_IDCT_ALTIVEC 8
+#define FF_IDCT_SIMPLEARM 10
+#define FF_IDCT_XVID 14
+#define FF_IDCT_SIMPLEARMV5TE 16
+#define FF_IDCT_SIMPLEARMV6 17
+#define FF_IDCT_FAAN 20
+#define FF_IDCT_SIMPLENEON 22
+#define FF_IDCT_NONE 24 /* Used by XvMC to extract IDCT coefficients with FF_IDCT_PERM_NONE */
+#define FF_IDCT_SIMPLEAUTO 128
+
+ /**
+ * bits per sample/pixel from the demuxer (needed for huffyuv).
+ * - encoding: Set by libavcodec.
+ * - decoding: Set by user.
+ */
+ int bits_per_coded_sample;
+
+ /**
+ * Bits per sample/pixel of internal libavcodec pixel/sample format.
+ * - encoding: set by user.
+ * - decoding: set by libavcodec.
+ */
+ int bits_per_raw_sample;
+
+#if FF_API_LOWRES
+ /**
+ * low resolution decoding, 1-> 1/2 size, 2->1/4 size
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ int lowres;
+#endif
+
+#if FF_API_CODED_FRAME
+ /**
+ * the picture in the bitstream
+ * - encoding: Set by libavcodec.
+ * - decoding: unused
+ *
+ * @deprecated use the quality factor packet side data instead
+ */
+ attribute_deprecated AVFrame *coded_frame;
+#endif
+
+ /**
+ * thread count
+ * is used to decide how many independent tasks should be passed to execute()
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int thread_count;
+
+ /**
+ * Which multithreading methods to use.
+ * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread,
+ * so clients which cannot provide future frames should not use it.
+ *
+ * - encoding: Set by user, otherwise the default is used.
+ * - decoding: Set by user, otherwise the default is used.
+ */
+ int thread_type;
+#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once
+#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once
+
+ /**
+ * Which multithreading methods are in use by the codec.
+ * - encoding: Set by libavcodec.
+ * - decoding: Set by libavcodec.
+ */
+ int active_thread_type;
+
+ /**
+ * Set by the client if its custom get_buffer() callback can be called
+ * synchronously from another thread, which allows faster multithreaded decoding.
+ * draw_horiz_band() will be called from other threads regardless of this setting.
+ * Ignored if the default get_buffer() is used.
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int thread_safe_callbacks;
+
+ /**
+ * The codec may call this to execute several independent things.
+ * It will return only after finishing all tasks.
+ * The user may replace this with some multithreaded implementation,
+ * the default implementation will execute the parts serially.
+ * @param count the number of things to execute
+ * - encoding: Set by libavcodec, user can override.
+ * - decoding: Set by libavcodec, user can override.
+ */
+ int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size);
+
+ /**
+ * The codec may call this to execute several independent things.
+ * It will return only after finishing all tasks.
+ * The user may replace this with some multithreaded implementation,
+ * the default implementation will execute the parts serially.
+ * Also see avcodec_thread_init and e.g. the --enable-pthread configure option.
+ * @param c context passed also to func
+ * @param count the number of things to execute
+ * @param arg2 argument passed unchanged to func
+ * @param ret return values of executed functions, must have space for "count" values. May be NULL.
+ * @param func function that will be called count times, with jobnr from 0 to count-1.
+ * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no
+ * two instances of func executing at the same time will have the same threadnr.
+ * @return always 0 currently, but code should handle a future improvement where when any call to func
+ * returns < 0 no further calls to func may be done and < 0 is returned.
+ * - encoding: Set by libavcodec, user can override.
+ * - decoding: Set by libavcodec, user can override.
+ */
+ int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count);
+
+ /**
+ * noise vs. sse weight for the nsse comparison function
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int nsse_weight;
+
+ /**
+ * profile
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ int profile;
+#define FF_PROFILE_UNKNOWN -99
+#define FF_PROFILE_RESERVED -100
+
+#define FF_PROFILE_AAC_MAIN 0
+#define FF_PROFILE_AAC_LOW 1
+#define FF_PROFILE_AAC_SSR 2
+#define FF_PROFILE_AAC_LTP 3
+#define FF_PROFILE_AAC_HE 4
+#define FF_PROFILE_AAC_HE_V2 28
+#define FF_PROFILE_AAC_LD 22
+#define FF_PROFILE_AAC_ELD 38
+#define FF_PROFILE_MPEG2_AAC_LOW 128
+#define FF_PROFILE_MPEG2_AAC_HE 131
+
+#define FF_PROFILE_DNXHD 0
+#define FF_PROFILE_DNXHR_LB 1
+#define FF_PROFILE_DNXHR_SQ 2
+#define FF_PROFILE_DNXHR_HQ 3
+#define FF_PROFILE_DNXHR_HQX 4
+#define FF_PROFILE_DNXHR_444 5
+
+#define FF_PROFILE_DTS 20
+#define FF_PROFILE_DTS_ES 30
+#define FF_PROFILE_DTS_96_24 40
+#define FF_PROFILE_DTS_HD_HRA 50
+#define FF_PROFILE_DTS_HD_MA 60
+#define FF_PROFILE_DTS_EXPRESS 70
+
+#define FF_PROFILE_MPEG2_422 0
+#define FF_PROFILE_MPEG2_HIGH 1
+#define FF_PROFILE_MPEG2_SS 2
+#define FF_PROFILE_MPEG2_SNR_SCALABLE 3
+#define FF_PROFILE_MPEG2_MAIN 4
+#define FF_PROFILE_MPEG2_SIMPLE 5
+
+#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag
+#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag
+
+#define FF_PROFILE_H264_BASELINE 66
+#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED)
+#define FF_PROFILE_H264_MAIN 77
+#define FF_PROFILE_H264_EXTENDED 88
+#define FF_PROFILE_H264_HIGH 100
+#define FF_PROFILE_H264_HIGH_10 110
+#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA)
+#define FF_PROFILE_H264_MULTIVIEW_HIGH 118
+#define FF_PROFILE_H264_HIGH_422 122
+#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA)
+#define FF_PROFILE_H264_STEREO_HIGH 128
+#define FF_PROFILE_H264_HIGH_444 144
+#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244
+#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA)
+#define FF_PROFILE_H264_CAVLC_444 44
+
+#define FF_PROFILE_VC1_SIMPLE 0
+#define FF_PROFILE_VC1_MAIN 1
+#define FF_PROFILE_VC1_COMPLEX 2
+#define FF_PROFILE_VC1_ADVANCED 3
+
+#define FF_PROFILE_MPEG4_SIMPLE 0
+#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1
+#define FF_PROFILE_MPEG4_CORE 2
+#define FF_PROFILE_MPEG4_MAIN 3
+#define FF_PROFILE_MPEG4_N_BIT 4
+#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5
+#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6
+#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7
+#define FF_PROFILE_MPEG4_HYBRID 8
+#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9
+#define FF_PROFILE_MPEG4_CORE_SCALABLE 10
+#define FF_PROFILE_MPEG4_ADVANCED_CODING 11
+#define FF_PROFILE_MPEG4_ADVANCED_CORE 12
+#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13
+#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14
+#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15
+
+#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1
+#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2
+#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768
+#define FF_PROFILE_JPEG2000_DCINEMA_2K 3
+#define FF_PROFILE_JPEG2000_DCINEMA_4K 4
+
+#define FF_PROFILE_VP9_0 0
+#define FF_PROFILE_VP9_1 1
+#define FF_PROFILE_VP9_2 2
+#define FF_PROFILE_VP9_3 3
+
+#define FF_PROFILE_HEVC_MAIN 1
+#define FF_PROFILE_HEVC_MAIN_10 2
+#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3
+#define FF_PROFILE_HEVC_REXT 4
+
+#define FF_PROFILE_AV1_MAIN 0
+#define FF_PROFILE_AV1_HIGH 1
+#define FF_PROFILE_AV1_PROFESSIONAL 2
+
+#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0
+#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1
+#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2
+#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3
+#define FF_PROFILE_MJPEG_JPEG_LS 0xf7
+
+#define FF_PROFILE_SBC_MSBC 1
+
+ /**
+ * level
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ int level;
+#define FF_LEVEL_UNKNOWN -99
+
+ /**
+ * Skip loop filtering for selected frames.
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ enum AVDiscard skip_loop_filter;
+
+ /**
+ * Skip IDCT/dequantization for selected frames.
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ enum AVDiscard skip_idct;
+
+ /**
+ * Skip decoding for selected frames.
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ enum AVDiscard skip_frame;
+
+ /**
+ * Header containing style information for text subtitles.
+ * For SUBTITLE_ASS subtitle type, it should contain the whole ASS
+ * [Script Info] and [V4+ Styles] section, plus the [Events] line and
+ * the Format line following. It shouldn't include any Dialogue line.
+ * - encoding: Set/allocated/freed by user (before avcodec_open2())
+ * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2())
+ */
+ uint8_t *subtitle_header;
+ int subtitle_header_size;
+
+#if FF_API_VBV_DELAY
+ /**
+ * VBV delay coded in the last frame (in periods of a 27 MHz clock).
+ * Used for compliant TS muxing.
+ * - encoding: Set by libavcodec.
+ * - decoding: unused.
+ * @deprecated this value is now exported as a part of
+ * AV_PKT_DATA_CPB_PROPERTIES packet side data
+ */
+ attribute_deprecated
+ uint64_t vbv_delay;
+#endif
+
+#if FF_API_SIDEDATA_ONLY_PKT
+ /**
+ * Encoding only and set by default. Allow encoders to output packets
+ * that do not contain any encoded data, only side data.
+ *
+ * Some encoders need to output such packets, e.g. to update some stream
+ * parameters at the end of encoding.
+ *
+ * @deprecated this field disables the default behaviour and
+ * it is kept only for compatibility.
+ */
+ attribute_deprecated
+ int side_data_only_packets;
+#endif
+
+ /**
+ * Audio only. The number of "priming" samples (padding) inserted by the
+ * encoder at the beginning of the audio. I.e. this number of leading
+ * decoded samples must be discarded by the caller to get the original audio
+ * without leading padding.
+ *
+ * - decoding: unused
+ * - encoding: Set by libavcodec. The timestamps on the output packets are
+ * adjusted by the encoder so that they always refer to the
+ * first sample of the data actually contained in the packet,
+ * including any added padding. E.g. if the timebase is
+ * 1/samplerate and the timestamp of the first input sample is
+ * 0, the timestamp of the first output packet will be
+ * -initial_padding.
+ */
+ int initial_padding;
+
+ /**
+ * - decoding: For codecs that store a framerate value in the compressed
+ * bitstream, the decoder may export it here. { 0, 1} when
+ * unknown.
+ * - encoding: May be used to signal the framerate of CFR content to an
+ * encoder.
+ */
+ AVRational framerate;
+
+ /**
+ * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
+ * - encoding: unused.
+ * - decoding: Set by libavcodec before calling get_format()
+ */
+ enum AVPixelFormat sw_pix_fmt;
+
+ /**
+ * Timebase in which pkt_dts/pts and AVPacket.dts/pts are.
+ * - encoding unused.
+ * - decoding set by user.
+ */
+ AVRational pkt_timebase;
+
+ /**
+ * AVCodecDescriptor
+ * - encoding: unused.
+ * - decoding: set by libavcodec.
+ */
+ const AVCodecDescriptor *codec_descriptor;
+
+#if !FF_API_LOWRES
+ /**
+ * low resolution decoding, 1-> 1/2 size, 2->1/4 size
+ * - encoding: unused
+ * - decoding: Set by user.
+ */
+ int lowres;
+#endif
+
+ /**
+ * Current statistics for PTS correction.
+ * - decoding: maintained and used by libavcodec, not intended to be used by user apps
+ * - encoding: unused
+ */
+ int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far
+ int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far
+ int64_t pts_correction_last_pts; /// PTS of the last frame
+ int64_t pts_correction_last_dts; /// DTS of the last frame
+
+ /**
+ * Character encoding of the input subtitles file.
+ * - decoding: set by user
+ * - encoding: unused
+ */
+ char *sub_charenc;
+
+ /**
+ * Subtitles character encoding mode. Formats or codecs might be adjusting
+ * this setting (if they are doing the conversion themselves for instance).
+ * - decoding: set by libavcodec
+ * - encoding: unused
+ */
+ int sub_charenc_mode;
+#define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance)
+#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself
+#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv
+#define FF_SUB_CHARENC_MODE_IGNORE 2 ///< neither convert the subtitles, nor check them for valid UTF-8
+
+ /**
+ * Skip processing alpha if supported by codec.
+ * Note that if the format uses pre-multiplied alpha (common with VP6,
+ * and recommended due to better video quality/compression)
+ * the image will look as if alpha-blended onto a black background.
+ * However for formats that do not use pre-multiplied alpha
+ * there might be serious artefacts (though e.g. libswscale currently
+ * assumes pre-multiplied alpha anyway).
+ *
+ * - decoding: set by user
+ * - encoding: unused
+ */
+ int skip_alpha;
+
+ /**
+ * Number of samples to skip after a discontinuity
+ * - decoding: unused
+ * - encoding: set by libavcodec
+ */
+ int seek_preroll;
+
+#if !FF_API_DEBUG_MV
+ /**
+ * debug motion vectors
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int debug_mv;
+#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames
+#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames
+#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames
+#endif
+
+ /**
+ * custom intra quantization matrix
+ * - encoding: Set by user, can be NULL.
+ * - decoding: unused.
+ */
+ uint16_t *chroma_intra_matrix;
+
+ /**
+ * dump format separator.
+ * can be ", " or "\n " or anything else
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ uint8_t *dump_separator;
+
+ /**
+ * ',' separated list of allowed decoders.
+ * If NULL then all are allowed
+ * - encoding: unused
+ * - decoding: set by user
+ */
+ char *codec_whitelist;
+
+ /**
+ * Properties of the stream that gets decoded
+ * - encoding: unused
+ * - decoding: set by libavcodec
+ */
+ unsigned properties;
+#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001
+#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002
+
+ /**
+ * Additional data associated with the entire coded stream.
+ *
+ * - decoding: unused
+ * - encoding: may be set by libavcodec after avcodec_open2().
+ */
+ AVPacketSideData *coded_side_data;
+ int nb_coded_side_data;
+
+ /**
+ * A reference to the AVHWFramesContext describing the input (for encoding)
+ * or output (decoding) frames. The reference is set by the caller and
+ * afterwards owned (and freed) by libavcodec - it should never be read by
+ * the caller after being set.
+ *
+ * - decoding: This field should be set by the caller from the get_format()
+ * callback. The previous reference (if any) will always be
+ * unreffed by libavcodec before the get_format() call.
+ *
+ * If the default get_buffer2() is used with a hwaccel pixel
+ * format, then this AVHWFramesContext will be used for
+ * allocating the frame buffers.
+ *
+ * - encoding: For hardware encoders configured to use a hwaccel pixel
+ * format, this field should be set by the caller to a reference
+ * to the AVHWFramesContext describing input frames.
+ * AVHWFramesContext.format must be equal to
+ * AVCodecContext.pix_fmt.
+ *
+ * This field should be set before avcodec_open2() is called.
+ */
+ AVBufferRef *hw_frames_ctx;
+
+ /**
+ * Control the form of AVSubtitle.rects[N]->ass
+ * - decoding: set by user
+ * - encoding: unused
+ */
+ int sub_text_format;
+#define FF_SUB_TEXT_FMT_ASS 0
+#if FF_API_ASS_TIMING
+#define FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS 1
+#endif
+
+ /**
+ * Audio only. The amount of padding (in samples) appended by the encoder to
+ * the end of the audio. I.e. this number of decoded samples must be
+ * discarded by the caller from the end of the stream to get the original
+ * audio without any trailing padding.
+ *
+ * - decoding: unused
+ * - encoding: unused
+ */
+ int trailing_padding;
+
+ /**
+ * The number of pixels per image to maximally accept.
+ *
+ * - decoding: set by user
+ * - encoding: set by user
+ */
+ int64_t max_pixels;
+
+ /**
+ * A reference to the AVHWDeviceContext describing the device which will
+ * be used by a hardware encoder/decoder. The reference is set by the
+ * caller and afterwards owned (and freed) by libavcodec.
+ *
+ * This should be used if either the codec device does not require
+ * hardware frames or any that are used are to be allocated internally by
+ * libavcodec. If the user wishes to supply any of the frames used as
+ * encoder input or decoder output then hw_frames_ctx should be used
+ * instead. When hw_frames_ctx is set in get_format() for a decoder, this
+ * field will be ignored while decoding the associated stream segment, but
+ * may again be used on a following one after another get_format() call.
+ *
+ * For both encoders and decoders this field should be set before
+ * avcodec_open2() is called and must not be written to thereafter.
+ *
+ * Note that some decoders may require this field to be set initially in
+ * order to support hw_frames_ctx at all - in that case, all frames
+ * contexts used must be created on the same device.
+ */
+ AVBufferRef *hw_device_ctx;
+
+ /**
+ * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated
+ * decoding (if active).
+ * - encoding: unused
+ * - decoding: Set by user (either before avcodec_open2(), or in the
+ * AVCodecContext.get_format callback)
+ */
+ int hwaccel_flags;
+
+ /**
+ * Video decoding only. Certain video codecs support cropping, meaning that
+ * only a sub-rectangle of the decoded frame is intended for display. This
+ * option controls how cropping is handled by libavcodec.
+ *
+ * When set to 1 (the default), libavcodec will apply cropping internally.
+ * I.e. it will modify the output frame width/height fields and offset the
+ * data pointers (only by as much as possible while preserving alignment, or
+ * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that
+ * the frames output by the decoder refer only to the cropped area. The
+ * crop_* fields of the output frames will be zero.
+ *
+ * When set to 0, the width/height fields of the output frames will be set
+ * to the coded dimensions and the crop_* fields will describe the cropping
+ * rectangle. Applying the cropping is left to the caller.
+ *
+ * @warning When hardware acceleration with opaque output frames is used,
+ * libavcodec is unable to apply cropping from the top/left border.
+ *
+ * @note when this option is set to zero, the width/height fields of the
+ * AVCodecContext and output AVFrames have different meanings. The codec
+ * context fields store display dimensions (with the coded dimensions in
+ * coded_width/height), while the frame fields store the coded dimensions
+ * (with the display dimensions being determined by the crop_* fields).
+ */
+ int apply_cropping;
+
+ /*
+ * Video decoding only. Sets the number of extra hardware frames which
+ * the decoder will allocate for use by the caller. This must be set
+ * before avcodec_open2() is called.
+ *
+ * Some hardware decoders require all frames that they will use for
+ * output to be defined in advance before decoding starts. For such
+ * decoders, the hardware frame pool must therefore be of a fixed size.
+ * The extra frames set here are on top of any number that the decoder
+ * needs internally in order to operate normally (for example, frames
+ * used as reference pictures).
+ */
+ int extra_hw_frames;
+} AVCodecContext;
+
+#if FF_API_CODEC_GET_SET
+/**
+ * Accessors for some AVCodecContext fields. These used to be provided for ABI
+ * compatibility, and do not need to be used anymore.
+ */
+attribute_deprecated
+AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx);
+attribute_deprecated
+void av_codec_set_pkt_timebase (AVCodecContext *avctx, AVRational val);
+
+attribute_deprecated
+const AVCodecDescriptor *av_codec_get_codec_descriptor(const AVCodecContext *avctx);
+attribute_deprecated
+void av_codec_set_codec_descriptor(AVCodecContext *avctx, const AVCodecDescriptor *desc);
+
+attribute_deprecated
+unsigned av_codec_get_codec_properties(const AVCodecContext *avctx);
+
+#if FF_API_LOWRES
+attribute_deprecated
+int av_codec_get_lowres(const AVCodecContext *avctx);
+attribute_deprecated
+void av_codec_set_lowres(AVCodecContext *avctx, int val);
+#endif
+
+attribute_deprecated
+int av_codec_get_seek_preroll(const AVCodecContext *avctx);
+attribute_deprecated
+void av_codec_set_seek_preroll(AVCodecContext *avctx, int val);
+
+attribute_deprecated
+uint16_t *av_codec_get_chroma_intra_matrix(const AVCodecContext *avctx);
+attribute_deprecated
+void av_codec_set_chroma_intra_matrix(AVCodecContext *avctx, uint16_t *val);
+#endif
+
+/**
+ * AVProfile.
+ */
+typedef struct AVProfile {
+ int profile;
+ const char *name; ///< short name for the profile
+} AVProfile;
+
+enum {
+ /**
+ * The codec supports this format via the hw_device_ctx interface.
+ *
+ * When selecting this format, AVCodecContext.hw_device_ctx should
+ * have been set to a device of the specified type before calling
+ * avcodec_open2().
+ */
+ AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01,
+ /**
+ * The codec supports this format via the hw_frames_ctx interface.
+ *
+ * When selecting this format for a decoder,
+ * AVCodecContext.hw_frames_ctx should be set to a suitable frames
+ * context inside the get_format() callback. The frames context
+ * must have been created on a device of the specified type.
+ */
+ AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02,
+ /**
+ * The codec supports this format by some internal method.
+ *
+ * This format can be selected without any additional configuration -
+ * no device or frames context is required.
+ */
+ AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04,
+ /**
+ * The codec supports this format by some ad-hoc method.
+ *
+ * Additional settings and/or function calls are required. See the
+ * codec-specific documentation for details. (Methods requiring
+ * this sort of configuration are deprecated and others should be
+ * used in preference.)
+ */
+ AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08,
+};
+
+typedef struct AVCodecHWConfig {
+ /**
+ * A hardware pixel format which the codec can use.
+ */
+ enum AVPixelFormat pix_fmt;
+ /**
+ * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible
+ * setup methods which can be used with this configuration.
+ */
+ int methods;
+ /**
+ * The device type associated with the configuration.
+ *
+ * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and
+ * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused.
+ */
+ enum AVHWDeviceType device_type;
+} AVCodecHWConfig;
+
+typedef struct AVCodecDefault AVCodecDefault;
+
+struct AVSubtitle;
+
+/**
+ * AVCodec.
+ */
+typedef struct AVCodec {
+ /**
+ * Name of the codec implementation.
+ * The name is globally unique among encoders and among decoders (but an
+ * encoder and a decoder can share the same name).
+ * This is the primary way to find a codec from the user perspective.
+ */
+ const char *name;
+ /**
+ * Descriptive name for the codec, meant to be more human readable than name.
+ * You should use the NULL_IF_CONFIG_SMALL() macro to define it.
+ */
+ const char *long_name;
+ enum AVMediaType type;
+ enum AVCodecID id;
+ /**
+ * Codec capabilities.
+ * see AV_CODEC_CAP_*
+ */
+ int capabilities;
+ const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}
+ const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1
+ const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
+ const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
+ const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
+ uint8_t max_lowres; ///< maximum value for lowres supported by the decoder
+ const AVClass *priv_class; ///< AVClass for the private context
+ const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}
+
+ /**
+ * Group name of the codec implementation.
+ * This is a short symbolic name of the wrapper backing this codec. A
+ * wrapper uses some kind of external implementation for the codec, such
+ * as an external library, or a codec implementation provided by the OS or
+ * the hardware.
+ * If this field is NULL, this is a builtin, libavcodec native codec.
+ * If non-NULL, this will be the suffix in AVCodec.name in most cases
+ * (usually AVCodec.name will be of the form "<codec_name>_<wrapper_name>").
+ */
+ const char *wrapper_name;
+
+ /*****************************************************************
+ * No fields below this line are part of the public API. They
+ * may not be used outside of libavcodec and can be changed and
+ * removed at will.
+ * New public fields should be added right above.
+ *****************************************************************
+ */
+ int priv_data_size;
+ struct AVCodec *next;
+ /**
+ * @name Frame-level threading support functions
+ * @{
+ */
+ /**
+ * If defined, called on thread contexts when they are created.
+ * If the codec allocates writable tables in init(), re-allocate them here.
+ * priv_data will be set to a copy of the original.
+ */
+ int (*init_thread_copy)(AVCodecContext *);
+ /**
+ * Copy necessary context variables from a previous thread context to the current one.
+ * If not defined, the next thread will start automatically; otherwise, the codec
+ * must call ff_thread_finish_setup().
+ *
+ * dst and src will (rarely) point to the same context, in which case memcpy should be skipped.
+ */
+ int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src);
+ /** @} */
+
+ /**
+ * Private codec-specific defaults.
+ */
+ const AVCodecDefault *defaults;
+
+ /**
+ * Initialize codec static data, called from avcodec_register().
+ *
+ * This is not intended for time consuming operations as it is
+ * run for every codec regardless of that codec being used.
+ */
+ void (*init_static_data)(struct AVCodec *codec);
+
+ int (*init)(AVCodecContext *);
+ int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size,
+ const struct AVSubtitle *sub);
+ /**
+ * Encode data to an AVPacket.
+ *
+ * @param avctx codec context
+ * @param avpkt output AVPacket (may contain a user-provided buffer)
+ * @param[in] frame AVFrame containing the raw data to be encoded
+ * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a
+ * non-empty packet was returned in avpkt.
+ * @return 0 on success, negative error code on failure
+ */
+ int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame,
+ int *got_packet_ptr);
+ int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt);
+ int (*close)(AVCodecContext *);
+ /**
+ * Encode API with decoupled packet/frame dataflow. The API is the
+ * same as the avcodec_ prefixed APIs (avcodec_send_frame() etc.), except
+ * that:
+ * - never called if the codec is closed or the wrong type,
+ * - if AV_CODEC_CAP_DELAY is not set, drain frames are never sent,
+ * - only one drain frame is ever passed down,
+ */
+ int (*send_frame)(AVCodecContext *avctx, const AVFrame *frame);
+ int (*receive_packet)(AVCodecContext *avctx, AVPacket *avpkt);
+
+ /**
+ * Decode API with decoupled packet/frame dataflow. This function is called
+ * to get one output frame. It should call ff_decode_get_packet() to obtain
+ * input data.
+ */
+ int (*receive_frame)(AVCodecContext *avctx, AVFrame *frame);
+ /**
+ * Flush buffers.
+ * Will be called when seeking
+ */
+ void (*flush)(AVCodecContext *);
+ /**
+ * Internal codec capabilities.
+ * See FF_CODEC_CAP_* in internal.h
+ */
+ int caps_internal;
+
+ /**
+ * Decoding only, a comma-separated list of bitstream filters to apply to
+ * packets before decoding.
+ */
+ const char *bsfs;
+
+ /**
+ * Array of pointers to hardware configurations supported by the codec,
+ * or NULL if no hardware supported. The array is terminated by a NULL
+ * pointer.
+ *
+ * The user can only access this field via avcodec_get_hw_config().
+ */
+ const struct AVCodecHWConfigInternal **hw_configs;
+} AVCodec;
+
+#if FF_API_CODEC_GET_SET
+attribute_deprecated
+int av_codec_get_max_lowres(const AVCodec *codec);
+#endif
+
+struct MpegEncContext;
+
+/**
+ * Retrieve supported hardware configurations for a codec.
+ *
+ * Values of index from zero to some maximum return the indexed configuration
+ * descriptor; all other values return NULL. If the codec does not support
+ * any hardware configurations then it will always return NULL.
+ */
+const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index);
+
+/**
+ * @defgroup lavc_hwaccel AVHWAccel
+ *
+ * @note Nothing in this structure should be accessed by the user. At some
+ * point in future it will not be externally visible at all.
+ *
+ * @{
+ */
+typedef struct AVHWAccel {
+ /**
+ * Name of the hardware accelerated codec.
+ * The name is globally unique among encoders and among decoders (but an
+ * encoder and a decoder can share the same name).
+ */
+ const char *name;
+
+ /**
+ * Type of codec implemented by the hardware accelerator.
+ *
+ * See AVMEDIA_TYPE_xxx
+ */
+ enum AVMediaType type;
+
+ /**
+ * Codec implemented by the hardware accelerator.
+ *
+ * See AV_CODEC_ID_xxx
+ */
+ enum AVCodecID id;
+
+ /**
+ * Supported pixel format.
+ *
+ * Only hardware accelerated formats are supported here.
+ */
+ enum AVPixelFormat pix_fmt;
+
+ /**
+ * Hardware accelerated codec capabilities.
+ * see AV_HWACCEL_CODEC_CAP_*
+ */
+ int capabilities;
+
+ /*****************************************************************
+ * No fields below this line are part of the public API. They
+ * may not be used outside of libavcodec and can be changed and
+ * removed at will.
+ * New public fields should be added right above.
+ *****************************************************************
+ */
+
+ /**
+ * Allocate a custom buffer
+ */
+ int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame);
+
+ /**
+ * Called at the beginning of each frame or field picture.
+ *
+ * Meaningful frame information (codec specific) is guaranteed to
+ * be parsed at this point. This function is mandatory.
+ *
+ * Note that buf can be NULL along with buf_size set to 0.
+ * Otherwise, this means the whole frame is available at this point.
+ *
+ * @param avctx the codec context
+ * @param buf the frame data buffer base
+ * @param buf_size the size of the frame in bytes
+ * @return zero if successful, a negative value otherwise
+ */
+ int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size);
+
+ /**
+ * Callback for parameter data (SPS/PPS/VPS etc).
+ *
+ * Useful for hardware decoders which keep persistent state about the
+ * video parameters, and need to receive any changes to update that state.
+ *
+ * @param avctx the codec context
+ * @param type the nal unit type
+ * @param buf the nal unit data buffer
+ * @param buf_size the size of the nal unit in bytes
+ * @return zero if successful, a negative value otherwise
+ */
+ int (*decode_params)(AVCodecContext *avctx, int type, const uint8_t *buf, uint32_t buf_size);
+
+ /**
+ * Callback for each slice.
+ *
+ * Meaningful slice information (codec specific) is guaranteed to
+ * be parsed at this point. This function is mandatory.
+ * The only exception is XvMC, that works on MB level.
+ *
+ * @param avctx the codec context
+ * @param buf the slice data buffer base
+ * @param buf_size the size of the slice in bytes
+ * @return zero if successful, a negative value otherwise
+ */
+ int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size);
+
+ /**
+ * Called at the end of each frame or field picture.
+ *
+ * The whole picture is parsed at this point and can now be sent
+ * to the hardware accelerator. This function is mandatory.
+ *
+ * @param avctx the codec context
+ * @return zero if successful, a negative value otherwise
+ */
+ int (*end_frame)(AVCodecContext *avctx);
+
+ /**
+ * Size of per-frame hardware accelerator private data.
+ *
+ * Private data is allocated with av_mallocz() before
+ * AVCodecContext.get_buffer() and deallocated after
+ * AVCodecContext.release_buffer().
+ */
+ int frame_priv_data_size;
+
+ /**
+ * Called for every Macroblock in a slice.
+ *
+ * XvMC uses it to replace the ff_mpv_reconstruct_mb().
+ * Instead of decoding to raw picture, MB parameters are
+ * stored in an array provided by the video driver.
+ *
+ * @param s the mpeg context
+ */
+ void (*decode_mb)(struct MpegEncContext *s);
+
+ /**
+ * Initialize the hwaccel private data.
+ *
+ * This will be called from ff_get_format(), after hwaccel and
+ * hwaccel_context are set and the hwaccel private data in AVCodecInternal
+ * is allocated.
+ */
+ int (*init)(AVCodecContext *avctx);
+
+ /**
+ * Uninitialize the hwaccel private data.
+ *
+ * This will be called from get_format() or avcodec_close(), after hwaccel
+ * and hwaccel_context are already uninitialized.
+ */
+ int (*uninit)(AVCodecContext *avctx);
+
+ /**
+ * Size of the private data to allocate in
+ * AVCodecInternal.hwaccel_priv_data.
+ */
+ int priv_data_size;
+
+ /**
+ * Internal hwaccel capabilities.
+ */
+ int caps_internal;
+
+ /**
+ * Fill the given hw_frames context with current codec parameters. Called
+ * from get_format. Refer to avcodec_get_hw_frames_parameters() for
+ * details.
+ *
+ * This CAN be called before AVHWAccel.init is called, and you must assume
+ * that avctx->hwaccel_priv_data is invalid.
+ */
+ int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);
+} AVHWAccel;
+
+/**
+ * HWAccel is experimental and is thus avoided in favor of non experimental
+ * codecs
+ */
+#define AV_HWACCEL_CODEC_CAP_EXPERIMENTAL 0x0200
+
+/**
+ * Hardware acceleration should be used for decoding even if the codec level
+ * used is unknown or higher than the maximum supported level reported by the
+ * hardware driver.
+ *
+ * It's generally a good idea to pass this flag unless you have a specific
+ * reason not to, as hardware tends to under-report supported levels.
+ */
+#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0)
+
+/**
+ * Hardware acceleration can output YUV pixel formats with a different chroma
+ * sampling than 4:2:0 and/or other than 8 bits per component.
+ */
+#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1)
+
+/**
+ * Hardware acceleration should still be attempted for decoding when the
+ * codec profile does not match the reported capabilities of the hardware.
+ *
+ * For example, this can be used to try to decode baseline profile H.264
+ * streams in hardware - it will often succeed, because many streams marked
+ * as baseline profile actually conform to constrained baseline profile.
+ *
+ * @warning If the stream is actually not supported then the behaviour is
+ * undefined, and may include returning entirely incorrect output
+ * while indicating success.
+ */
+#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2)
+
+/**
+ * @}
+ */
+
+#if FF_API_AVPICTURE
+/**
+ * @defgroup lavc_picture AVPicture
+ *
+ * Functions for working with AVPicture
+ * @{
+ */
+
+/**
+ * Picture data structure.
+ *
+ * Up to four components can be stored into it, the last component is
+ * alpha.
+ * @deprecated use AVFrame or imgutils functions instead
+ */
+typedef struct AVPicture {
+ attribute_deprecated
+ uint8_t *data[AV_NUM_DATA_POINTERS]; ///< pointers to the image data planes
+ attribute_deprecated
+ int linesize[AV_NUM_DATA_POINTERS]; ///< number of bytes per line
+} AVPicture;
+
+/**
+ * @}
+ */
+#endif
+
+enum AVSubtitleType {
+ SUBTITLE_NONE,
+
+ SUBTITLE_BITMAP, ///< A bitmap, pict will be set
+
+ /**
+ * Plain text, the text field must be set by the decoder and is
+ * authoritative. ass and pict fields may contain approximations.
+ */
+ SUBTITLE_TEXT,
+
+ /**
+ * Formatted text, the ass field must be set by the decoder and is
+ * authoritative. pict and text fields may contain approximations.
+ */
+ SUBTITLE_ASS,
+};
+
+#define AV_SUBTITLE_FLAG_FORCED 0x00000001
+
+typedef struct AVSubtitleRect {
+ int x; ///< top left corner of pict, undefined when pict is not set
+ int y; ///< top left corner of pict, undefined when pict is not set
+ int w; ///< width of pict, undefined when pict is not set
+ int h; ///< height of pict, undefined when pict is not set
+ int nb_colors; ///< number of colors in pict, undefined when pict is not set
+
+#if FF_API_AVPICTURE
+ /**
+ * @deprecated unused
+ */
+ attribute_deprecated
+ AVPicture pict;
+#endif
+ /**
+ * data+linesize for the bitmap of this subtitle.
+ * Can be set for text/ass as well once they are rendered.
+ */
+ uint8_t *data[4];
+ int linesize[4];
+
+ enum AVSubtitleType type;
+
+ char *text; ///< 0 terminated plain UTF-8 text
+
+ /**
+ * 0 terminated ASS/SSA compatible event line.
+ * The presentation of this is unaffected by the other values in this
+ * struct.
+ */
+ char *ass;
+
+ int flags;
+} AVSubtitleRect;
+
+typedef struct AVSubtitle {
+ uint16_t format; /* 0 = graphics */
+ uint32_t start_display_time; /* relative to packet pts, in ms */
+ uint32_t end_display_time; /* relative to packet pts, in ms */
+ unsigned num_rects;
+ AVSubtitleRect **rects;
+ int64_t pts; ///< Same as packet pts, in AV_TIME_BASE
+} AVSubtitle;
+
+/**
+ * This struct describes the properties of an encoded stream.
+ *
+ * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must
+ * be allocated with avcodec_parameters_alloc() and freed with
+ * avcodec_parameters_free().
+ */
+typedef struct AVCodecParameters {
+ /**
+ * General type of the encoded data.
+ */
+ enum AVMediaType codec_type;
+ /**
+ * Specific type of the encoded data (the codec used).
+ */
+ enum AVCodecID codec_id;
+ /**
+ * Additional information about the codec (corresponds to the AVI FOURCC).
+ */
+ uint32_t codec_tag;
+
+ /**
+ * Extra binary data needed for initializing the decoder, codec-dependent.
+ *
+ * Must be allocated with av_malloc() and will be freed by
+ * avcodec_parameters_free(). The allocated size of extradata must be at
+ * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding
+ * bytes zeroed.
+ */
+ uint8_t *extradata;
+ /**
+ * Size of the extradata content in bytes.
+ */
+ int extradata_size;
+
+ /**
+ * - video: the pixel format, the value corresponds to enum AVPixelFormat.
+ * - audio: the sample format, the value corresponds to enum AVSampleFormat.
+ */
+ int format;
+
+ /**
+ * The average bitrate of the encoded data (in bits per second).
+ */
+ int64_t bit_rate;
+
+ /**
+ * The number of bits per sample in the codedwords.
+ *
+ * This is basically the bitrate per sample. It is mandatory for a bunch of
+ * formats to actually decode them. It's the number of bits for one sample in
+ * the actual coded bitstream.
+ *
+ * This could be for example 4 for ADPCM
+ * For PCM formats this matches bits_per_raw_sample
+ * Can be 0
+ */
+ int bits_per_coded_sample;
+
+ /**
+ * This is the number of valid bits in each output sample. If the
+ * sample format has more bits, the least significant bits are additional
+ * padding bits, which are always 0. Use right shifts to reduce the sample
+ * to its actual size. For example, audio formats with 24 bit samples will
+ * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32.
+ * To get the original sample use "(int32_t)sample >> 8"."
+ *
+ * For ADPCM this might be 12 or 16 or similar
+ * Can be 0
+ */
+ int bits_per_raw_sample;
+
+ /**
+ * Codec-specific bitstream restrictions that the stream conforms to.
+ */
+ int profile;
+ int level;
+
+ /**
+ * Video only. The dimensions of the video frame in pixels.
+ */
+ int width;
+ int height;
+
+ /**
+ * Video only. The aspect ratio (width / height) which a single pixel
+ * should have when displayed.
+ *
+ * When the aspect ratio is unknown / undefined, the numerator should be
+ * set to 0 (the denominator may have any value).
+ */
+ AVRational sample_aspect_ratio;
+
+ /**
+ * Video only. The order of the fields in interlaced video.
+ */
+ enum AVFieldOrder field_order;
+
+ /**
+ * Video only. Additional colorspace characteristics.
+ */
+ enum AVColorRange color_range;
+ enum AVColorPrimaries color_primaries;
+ enum AVColorTransferCharacteristic color_trc;
+ enum AVColorSpace color_space;
+ enum AVChromaLocation chroma_location;
+
+ /**
+ * Video only. Number of delayed frames.
+ */
+ int video_delay;
+
+ /**
+ * Audio only. The channel layout bitmask. May be 0 if the channel layout is
+ * unknown or unspecified, otherwise the number of bits set must be equal to
+ * the channels field.
+ */
+ uint64_t channel_layout;
+ /**
+ * Audio only. The number of audio channels.
+ */
+ int channels;
+ /**
+ * Audio only. The number of audio samples per second.
+ */
+ int sample_rate;
+ /**
+ * Audio only. The number of bytes per coded audio frame, required by some
+ * formats.
+ *
+ * Corresponds to nBlockAlign in WAVEFORMATEX.
+ */
+ int block_align;
+ /**
+ * Audio only. Audio frame size, if known. Required by some formats to be static.
+ */
+ int frame_size;
+
+ /**
+ * Audio only. The amount of padding (in samples) inserted by the encoder at
+ * the beginning of the audio. I.e. this number of leading decoded samples
+ * must be discarded by the caller to get the original audio without leading
+ * padding.
+ */
+ int initial_padding;
+ /**
+ * Audio only. The amount of padding (in samples) appended by the encoder to
+ * the end of the audio. I.e. this number of decoded samples must be
+ * discarded by the caller from the end of the stream to get the original
+ * audio without any trailing padding.
+ */
+ int trailing_padding;
+ /**
+ * Audio only. Number of samples to skip after a discontinuity.
+ */
+ int seek_preroll;
+} AVCodecParameters;
+
+/**
+ * Iterate over all registered codecs.
+ *
+ * @param opaque a pointer where libavcodec will store the iteration state. Must
+ * point to NULL to start the iteration.
+ *
+ * @return the next registered codec or NULL when the iteration is
+ * finished
+ */
+const AVCodec *av_codec_iterate(void **opaque);
+
+#if FF_API_NEXT
+/**
+ * If c is NULL, returns the first registered codec,
+ * if c is non-NULL, returns the next registered codec after c,
+ * or NULL if c is the last one.
+ */
+attribute_deprecated
+AVCodec *av_codec_next(const AVCodec *c);
+#endif
+
+/**
+ * Return the LIBAVCODEC_VERSION_INT constant.
+ */
+unsigned avcodec_version(void);
+
+/**
+ * Return the libavcodec build-time configuration.
+ */
+const char *avcodec_configuration(void);
+
+/**
+ * Return the libavcodec license.
+ */
+const char *avcodec_license(void);
+
+#if FF_API_NEXT
+/**
+ * Register the codec codec and initialize libavcodec.
+ *
+ * @warning either this function or avcodec_register_all() must be called
+ * before any other libavcodec functions.
+ *
+ * @see avcodec_register_all()
+ */
+attribute_deprecated
+void avcodec_register(AVCodec *codec);
+
+/**
+ * Register all the codecs, parsers and bitstream filters which were enabled at
+ * configuration time. If you do not call this function you can select exactly
+ * which formats you want to support, by using the individual registration
+ * functions.
+ *
+ * @see avcodec_register
+ * @see av_register_codec_parser
+ * @see av_register_bitstream_filter
+ */
+attribute_deprecated
+void avcodec_register_all(void);
+#endif
+
+/**
+ * Allocate an AVCodecContext and set its fields to default values. The
+ * resulting struct should be freed with avcodec_free_context().
+ *
+ * @param codec if non-NULL, allocate private data and initialize defaults
+ * for the given codec. It is illegal to then call avcodec_open2()
+ * with a different codec.
+ * If NULL, then the codec-specific defaults won't be initialized,
+ * which may result in suboptimal default settings (this is
+ * important mainly for encoders, e.g. libx264).
+ *
+ * @return An AVCodecContext filled with default values or NULL on failure.
+ */
+AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
+
+/**
+ * Free the codec context and everything associated with it and write NULL to
+ * the provided pointer.
+ */
+void avcodec_free_context(AVCodecContext **avctx);
+
+#if FF_API_GET_CONTEXT_DEFAULTS
+/**
+ * @deprecated This function should not be used, as closing and opening a codec
+ * context multiple time is not supported. A new codec context should be
+ * allocated for each new use.
+ */
+int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec);
+#endif
+
+/**
+ * Get the AVClass for AVCodecContext. It can be used in combination with
+ * AV_OPT_SEARCH_FAKE_OBJ for examining options.
+ *
+ * @see av_opt_find().
+ */
+const AVClass *avcodec_get_class(void);
+
+#if FF_API_COPY_CONTEXT
+/**
+ * Get the AVClass for AVFrame. It can be used in combination with
+ * AV_OPT_SEARCH_FAKE_OBJ for examining options.
+ *
+ * @see av_opt_find().
+ */
+const AVClass *avcodec_get_frame_class(void);
+
+/**
+ * Get the AVClass for AVSubtitleRect. It can be used in combination with
+ * AV_OPT_SEARCH_FAKE_OBJ for examining options.
+ *
+ * @see av_opt_find().
+ */
+const AVClass *avcodec_get_subtitle_rect_class(void);
+
+/**
+ * Copy the settings of the source AVCodecContext into the destination
+ * AVCodecContext. The resulting destination codec context will be
+ * unopened, i.e. you are required to call avcodec_open2() before you
+ * can use this AVCodecContext to decode/encode video/audio data.
+ *
+ * @param dest target codec context, should be initialized with
+ * avcodec_alloc_context3(NULL), but otherwise uninitialized
+ * @param src source codec context
+ * @return AVERROR() on error (e.g. memory allocation error), 0 on success
+ *
+ * @deprecated The semantics of this function are ill-defined and it should not
+ * be used. If you need to transfer the stream parameters from one codec context
+ * to another, use an intermediate AVCodecParameters instance and the
+ * avcodec_parameters_from_context() / avcodec_parameters_to_context()
+ * functions.
+ */
+attribute_deprecated
+int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src);
+#endif
+
+/**
+ * Allocate a new AVCodecParameters and set its fields to default values
+ * (unknown/invalid/0). The returned struct must be freed with
+ * avcodec_parameters_free().
+ */
+AVCodecParameters *avcodec_parameters_alloc(void);
+
+/**
+ * Free an AVCodecParameters instance and everything associated with it and
+ * write NULL to the supplied pointer.
+ */
+void avcodec_parameters_free(AVCodecParameters **par);
+
+/**
+ * Copy the contents of src to dst. Any allocated fields in dst are freed and
+ * replaced with newly allocated duplicates of the corresponding fields in src.
+ *
+ * @return >= 0 on success, a negative AVERROR code on failure.
+ */
+int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src);
+
+/**
+ * Fill the parameters struct based on the values from the supplied codec
+ * context. Any allocated fields in par are freed and replaced with duplicates
+ * of the corresponding fields in codec.
+ *
+ * @return >= 0 on success, a negative AVERROR code on failure
+ */
+int avcodec_parameters_from_context(AVCodecParameters *par,
+ const AVCodecContext *codec);
+
+/**
+ * Fill the codec context based on the values from the supplied codec
+ * parameters. Any allocated fields in codec that have a corresponding field in
+ * par are freed and replaced with duplicates of the corresponding field in par.
+ * Fields in codec that do not have a counterpart in par are not touched.
+ *
+ * @return >= 0 on success, a negative AVERROR code on failure.
+ */
+int avcodec_parameters_to_context(AVCodecContext *codec,
+ const AVCodecParameters *par);
+
+/**
+ * Initialize the AVCodecContext to use the given AVCodec. Prior to using this
+ * function the context has to be allocated with avcodec_alloc_context3().
+ *
+ * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
+ * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
+ * retrieving a codec.
+ *
+ * @warning This function is not thread safe!
+ *
+ * @note Always call this function before using decoding routines (such as
+ * @ref avcodec_receive_frame()).
+ *
+ * @code
+ * avcodec_register_all();
+ * av_dict_set(&opts, "b", "2.5M", 0);
+ * codec = avcodec_find_decoder(AV_CODEC_ID_H264);
+ * if (!codec)
+ * exit(1);
+ *
+ * context = avcodec_alloc_context3(codec);
+ *
+ * if (avcodec_open2(context, codec, opts) < 0)
+ * exit(1);
+ * @endcode
+ *
+ * @param avctx The context to initialize.
+ * @param codec The codec to open this context for. If a non-NULL codec has been
+ * previously passed to avcodec_alloc_context3() or
+ * for this context, then this parameter MUST be either NULL or
+ * equal to the previously passed codec.
+ * @param options A dictionary filled with AVCodecContext and codec-private options.
+ * On return this object will be filled with options that were not found.
+ *
+ * @return zero on success, a negative value on error
+ * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),
+ * av_dict_set(), av_opt_find().
+ */
+int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
+
+/**
+ * Close a given AVCodecContext and free all the data associated with it
+ * (but not the AVCodecContext itself).
+ *
+ * Calling this function on an AVCodecContext that hasn't been opened will free
+ * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL
+ * codec. Subsequent calls will do nothing.
+ *
+ * @note Do not use this function. Use avcodec_free_context() to destroy a
+ * codec context (either open or closed). Opening and closing a codec context
+ * multiple times is not supported anymore -- use multiple codec contexts
+ * instead.
+ */
+int avcodec_close(AVCodecContext *avctx);
+
+/**
+ * Free all allocated data in the given subtitle struct.
+ *
+ * @param sub AVSubtitle to free.
+ */
+void avsubtitle_free(AVSubtitle *sub);
+
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup lavc_packet
+ * @{
+ */
+
+/**
+ * Allocate an AVPacket and set its fields to default values. The resulting
+ * struct must be freed using av_packet_free().
+ *
+ * @return An AVPacket filled with default values or NULL on failure.
+ *
+ * @note this only allocates the AVPacket itself, not the data buffers. Those
+ * must be allocated through other means such as av_new_packet.
+ *
+ * @see av_new_packet
+ */
+AVPacket *av_packet_alloc(void);
+
+/**
+ * Create a new packet that references the same data as src.
+ *
+ * This is a shortcut for av_packet_alloc()+av_packet_ref().
+ *
+ * @return newly created AVPacket on success, NULL on error.
+ *
+ * @see av_packet_alloc
+ * @see av_packet_ref
+ */
+AVPacket *av_packet_clone(const AVPacket *src);
+
+/**
+ * Free the packet, if the packet is reference counted, it will be
+ * unreferenced first.
+ *
+ * @param pkt packet to be freed. The pointer will be set to NULL.
+ * @note passing NULL is a no-op.
+ */
+void av_packet_free(AVPacket **pkt);
+
+/**
+ * Initialize optional fields of a packet with default values.
+ *
+ * Note, this does not touch the data and size members, which have to be
+ * initialized separately.
+ *
+ * @param pkt packet
+ */
+void av_init_packet(AVPacket *pkt);
+
+/**
+ * Allocate the payload of a packet and initialize its fields with
+ * default values.
+ *
+ * @param pkt packet
+ * @param size wanted payload size
+ * @return 0 if OK, AVERROR_xxx otherwise
+ */
+int av_new_packet(AVPacket *pkt, int size);
+
+/**
+ * Reduce packet size, correctly zeroing padding
+ *
+ * @param pkt packet
+ * @param size new size
+ */
+void av_shrink_packet(AVPacket *pkt, int size);
+
+/**
+ * Increase packet size, correctly zeroing padding
+ *
+ * @param pkt packet
+ * @param grow_by number of bytes by which to increase the size of the packet
+ */
+int av_grow_packet(AVPacket *pkt, int grow_by);
+
+/**
+ * Initialize a reference-counted packet from av_malloc()ed data.
+ *
+ * @param pkt packet to be initialized. This function will set the data, size,
+ * buf and destruct fields, all others are left untouched.
+ * @param data Data allocated by av_malloc() to be used as packet data. If this
+ * function returns successfully, the data is owned by the underlying AVBuffer.
+ * The caller may not access the data through other means.
+ * @param size size of data in bytes, without the padding. I.e. the full buffer
+ * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE.
+ *
+ * @return 0 on success, a negative AVERROR on error
+ */
+int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size);
+
+#if FF_API_AVPACKET_OLD_API
+/**
+ * @warning This is a hack - the packet memory allocation stuff is broken. The
+ * packet is allocated if it was not really allocated.
+ *
+ * @deprecated Use av_packet_ref or av_packet_make_refcounted
+ */
+attribute_deprecated
+int av_dup_packet(AVPacket *pkt);
+/**
+ * Copy packet, including contents
+ *
+ * @return 0 on success, negative AVERROR on fail
+ *
+ * @deprecated Use av_packet_ref
+ */
+attribute_deprecated
+int av_copy_packet(AVPacket *dst, const AVPacket *src);
+
+/**
+ * Copy packet side data
+ *
+ * @return 0 on success, negative AVERROR on fail
+ *
+ * @deprecated Use av_packet_copy_props
+ */
+attribute_deprecated
+int av_copy_packet_side_data(AVPacket *dst, const AVPacket *src);
+
+/**
+ * Free a packet.
+ *
+ * @deprecated Use av_packet_unref
+ *
+ * @param pkt packet to free
+ */
+attribute_deprecated
+void av_free_packet(AVPacket *pkt);
+#endif
+/**
+ * Allocate new information of a packet.
+ *
+ * @param pkt packet
+ * @param type side information type
+ * @param size side information size
+ * @return pointer to fresh allocated data or NULL otherwise
+ */
+uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
+ int size);
+
+/**
+ * Wrap an existing array as a packet side data.
+ *
+ * @param pkt packet
+ * @param type side information type
+ * @param data the side data array. It must be allocated with the av_malloc()
+ * family of functions. The ownership of the data is transferred to
+ * pkt.
+ * @param size side information size
+ * @return a non-negative number on success, a negative AVERROR code on
+ * failure. On failure, the packet is unchanged and the data remains
+ * owned by the caller.
+ */
+int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
+ uint8_t *data, size_t size);
+
+/**
+ * Shrink the already allocated side data buffer
+ *
+ * @param pkt packet
+ * @param type side information type
+ * @param size new side information size
+ * @return 0 on success, < 0 on failure
+ */
+int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
+ int size);
+
+/**
+ * Get side information from packet.
+ *
+ * @param pkt packet
+ * @param type desired side information type
+ * @param size pointer for side information size to store (optional)
+ * @return pointer to data if present or NULL otherwise
+ */
+uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type,
+ int *size);
+
+#if FF_API_MERGE_SD_API
+attribute_deprecated
+int av_packet_merge_side_data(AVPacket *pkt);
+
+attribute_deprecated
+int av_packet_split_side_data(AVPacket *pkt);
+#endif
+
+const char *av_packet_side_data_name(enum AVPacketSideDataType type);
+
+/**
+ * Pack a dictionary for use in side_data.
+ *
+ * @param dict The dictionary to pack.
+ * @param size pointer to store the size of the returned data
+ * @return pointer to data if successful, NULL otherwise
+ */
+uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size);
+/**
+ * Unpack a dictionary from side_data.
+ *
+ * @param data data from side_data
+ * @param size size of the data
+ * @param dict the metadata storage dictionary
+ * @return 0 on success, < 0 on failure
+ */
+int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict);
+
+
+/**
+ * Convenience function to free all the side data stored.
+ * All the other fields stay untouched.
+ *
+ * @param pkt packet
+ */
+void av_packet_free_side_data(AVPacket *pkt);
+
+/**
+ * Setup a new reference to the data described by a given packet
+ *
+ * If src is reference-counted, setup dst as a new reference to the
+ * buffer in src. Otherwise allocate a new buffer in dst and copy the
+ * data from src into it.
+ *
+ * All the other fields are copied from src.
+ *
+ * @see av_packet_unref
+ *
+ * @param dst Destination packet
+ * @param src Source packet
+ *
+ * @return 0 on success, a negative AVERROR on error.
+ */
+int av_packet_ref(AVPacket *dst, const AVPacket *src);
+
+/**
+ * Wipe the packet.
+ *
+ * Unreference the buffer referenced by the packet and reset the
+ * remaining packet fields to their default values.
+ *
+ * @param pkt The packet to be unreferenced.
+ */
+void av_packet_unref(AVPacket *pkt);
+
+/**
+ * Move every field in src to dst and reset src.
+ *
+ * @see av_packet_unref
+ *
+ * @param src Source packet, will be reset
+ * @param dst Destination packet
+ */
+void av_packet_move_ref(AVPacket *dst, AVPacket *src);
+
+/**
+ * Copy only "properties" fields from src to dst.
+ *
+ * Properties for the purpose of this function are all the fields
+ * beside those related to the packet data (buf, data, size)
+ *
+ * @param dst Destination packet
+ * @param src Source packet
+ *
+ * @return 0 on success AVERROR on failure.
+ */
+int av_packet_copy_props(AVPacket *dst, const AVPacket *src);
+
+/**
+ * Ensure the data described by a given packet is reference counted.
+ *
+ * @note This function does not ensure that the reference will be writable.
+ * Use av_packet_make_writable instead for that purpose.
+ *
+ * @see av_packet_ref
+ * @see av_packet_make_writable
+ *
+ * @param pkt packet whose data should be made reference counted.
+ *
+ * @return 0 on success, a negative AVERROR on error. On failure, the
+ * packet is unchanged.
+ */
+int av_packet_make_refcounted(AVPacket *pkt);
+
+/**
+ * Create a writable reference for the data described by a given packet,
+ * avoiding data copy if possible.
+ *
+ * @param pkt Packet whose data should be made writable.
+ *
+ * @return 0 on success, a negative AVERROR on failure. On failure, the
+ * packet is unchanged.
+ */
+int av_packet_make_writable(AVPacket *pkt);
+
+/**
+ * Convert valid timing fields (timestamps / durations) in a packet from one
+ * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
+ * ignored.
+ *
+ * @param pkt packet on which the conversion will be performed
+ * @param tb_src source timebase, in which the timing fields in pkt are
+ * expressed
+ * @param tb_dst destination timebase, to which the timing fields will be
+ * converted
+ */
+void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);
+
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup lavc_decoding
+ * @{
+ */
+
+/**
+ * Find a registered decoder with a matching codec ID.
+ *
+ * @param id AVCodecID of the requested decoder
+ * @return A decoder if one was found, NULL otherwise.
+ */
+AVCodec *avcodec_find_decoder(enum AVCodecID id);
+
+/**
+ * Find a registered decoder with the specified name.
+ *
+ * @param name name of the requested decoder
+ * @return A decoder if one was found, NULL otherwise.
+ */
+AVCodec *avcodec_find_decoder_by_name(const char *name);
+
+/**
+ * The default callback for AVCodecContext.get_buffer2(). It is made public so
+ * it can be called by custom get_buffer2() implementations for decoders without
+ * AV_CODEC_CAP_DR1 set.
+ */
+int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags);
+
+/**
+ * Modify width and height values so that they will result in a memory
+ * buffer that is acceptable for the codec if you do not use any horizontal
+ * padding.
+ *
+ * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened.
+ */
+void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height);
+
+/**
+ * Modify width and height values so that they will result in a memory
+ * buffer that is acceptable for the codec if you also ensure that all
+ * line sizes are a multiple of the respective linesize_align[i].
+ *
+ * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened.
+ */
+void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
+ int linesize_align[AV_NUM_DATA_POINTERS]);
+
+/**
+ * Converts AVChromaLocation to swscale x/y chroma position.
+ *
+ * The positions represent the chroma (0,0) position in a coordinates system
+ * with luma (0,0) representing the origin and luma(1,1) representing 256,256
+ *
+ * @param xpos horizontal chroma sample position
+ * @param ypos vertical chroma sample position
+ */
+int avcodec_enum_to_chroma_pos(int *xpos, int *ypos, enum AVChromaLocation pos);
+
+/**
+ * Converts swscale x/y chroma position to AVChromaLocation.
+ *
+ * The positions represent the chroma (0,0) position in a coordinates system
+ * with luma (0,0) representing the origin and luma(1,1) representing 256,256
+ *
+ * @param xpos horizontal chroma sample position
+ * @param ypos vertical chroma sample position
+ */
+enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos);
+
+/**
+ * Decode the audio frame of size avpkt->size from avpkt->data into frame.
+ *
+ * Some decoders may support multiple frames in a single AVPacket. Such
+ * decoders would then just decode the first frame and the return value would be
+ * less than the packet size. In this case, avcodec_decode_audio4 has to be
+ * called again with an AVPacket containing the remaining data in order to
+ * decode the second frame, etc... Even if no frames are returned, the packet
+ * needs to be fed to the decoder with remaining data until it is completely
+ * consumed or an error occurs.
+ *
+ * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input
+ * and output. This means that for some packets they will not immediately
+ * produce decoded output and need to be flushed at the end of decoding to get
+ * all the decoded data. Flushing is done by calling this function with packets
+ * with avpkt->data set to NULL and avpkt->size set to 0 until it stops
+ * returning samples. It is safe to flush even those decoders that are not
+ * marked with AV_CODEC_CAP_DELAY, then no samples will be returned.
+ *
+ * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE
+ * larger than the actual read bytes because some optimized bitstream
+ * readers read 32 or 64 bits at once and could read over the end.
+ *
+ * @note The AVCodecContext MUST have been opened with @ref avcodec_open2()
+ * before packets may be fed to the decoder.
+ *
+ * @param avctx the codec context
+ * @param[out] frame The AVFrame in which to store decoded audio samples.
+ * The decoder will allocate a buffer for the decoded frame by
+ * calling the AVCodecContext.get_buffer2() callback.
+ * When AVCodecContext.refcounted_frames is set to 1, the frame is
+ * reference counted and the returned reference belongs to the
+ * caller. The caller must release the frame using av_frame_unref()
+ * when the frame is no longer needed. The caller may safely write
+ * to the frame if av_frame_is_writable() returns 1.
+ * When AVCodecContext.refcounted_frames is set to 0, the returned
+ * reference belongs to the decoder and is valid only until the
+ * next call to this function or until closing or flushing the
+ * decoder. The caller may not write to it.
+ * @param[out] got_frame_ptr Zero if no frame could be decoded, otherwise it is
+ * non-zero. Note that this field being set to zero
+ * does not mean that an error has occurred. For
+ * decoders with AV_CODEC_CAP_DELAY set, no given decode
+ * call is guaranteed to produce a frame.
+ * @param[in] avpkt The input AVPacket containing the input buffer.
+ * At least avpkt->data and avpkt->size should be set. Some
+ * decoders might also require additional fields to be set.
+ * @return A negative error code is returned if an error occurred during
+ * decoding, otherwise the number of bytes consumed from the input
+ * AVPacket is returned.
+ *
+* @deprecated Use avcodec_send_packet() and avcodec_receive_frame().
+ */
+attribute_deprecated
+int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, const AVPacket *avpkt);
+
+/**
+ * Decode the video frame of size avpkt->size from avpkt->data into picture.
+ * Some decoders may support multiple frames in a single AVPacket, such
+ * decoders would then just decode the first frame.
+ *
+ * @warning The input buffer must be AV_INPUT_BUFFER_PADDING_SIZE larger than
+ * the actual read bytes because some optimized bitstream readers read 32 or 64
+ * bits at once and could read over the end.
+ *
+ * @warning The end of the input buffer buf should be set to 0 to ensure that
+ * no overreading happens for damaged MPEG streams.
+ *
+ * @note Codecs which have the AV_CODEC_CAP_DELAY capability set have a delay
+ * between input and output, these need to be fed with avpkt->data=NULL,
+ * avpkt->size=0 at the end to return the remaining frames.
+ *
+ * @note The AVCodecContext MUST have been opened with @ref avcodec_open2()
+ * before packets may be fed to the decoder.
+ *
+ * @param avctx the codec context
+ * @param[out] picture The AVFrame in which the decoded video frame will be stored.
+ * Use av_frame_alloc() to get an AVFrame. The codec will
+ * allocate memory for the actual bitmap by calling the
+ * AVCodecContext.get_buffer2() callback.
+ * When AVCodecContext.refcounted_frames is set to 1, the frame is
+ * reference counted and the returned reference belongs to the
+ * caller. The caller must release the frame using av_frame_unref()
+ * when the frame is no longer needed. The caller may safely write
+ * to the frame if av_frame_is_writable() returns 1.
+ * When AVCodecContext.refcounted_frames is set to 0, the returned
+ * reference belongs to the decoder and is valid only until the
+ * next call to this function or until closing or flushing the
+ * decoder. The caller may not write to it.
+ *
+ * @param[in] avpkt The input AVPacket containing the input buffer.
+ * You can create such packet with av_init_packet() and by then setting
+ * data and size, some decoders might in addition need other fields like
+ * flags&AV_PKT_FLAG_KEY. All decoders are designed to use the least
+ * fields possible.
+ * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero.
+ * @return On error a negative value is returned, otherwise the number of bytes
+ * used or zero if no frame could be decompressed.
+ *
+ * @deprecated Use avcodec_send_packet() and avcodec_receive_frame().
+ */
+attribute_deprecated
+int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
+ int *got_picture_ptr,
+ const AVPacket *avpkt);
+
+/**
+ * Decode a subtitle message.
+ * Return a negative value on error, otherwise return the number of bytes used.
+ * If no subtitle could be decompressed, got_sub_ptr is zero.
+ * Otherwise, the subtitle is stored in *sub.
+ * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for
+ * simplicity, because the performance difference is expect to be negligible
+ * and reusing a get_buffer written for video codecs would probably perform badly
+ * due to a potentially very different allocation pattern.
+ *
+ * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input
+ * and output. This means that for some packets they will not immediately
+ * produce decoded output and need to be flushed at the end of decoding to get
+ * all the decoded data. Flushing is done by calling this function with packets
+ * with avpkt->data set to NULL and avpkt->size set to 0 until it stops
+ * returning subtitles. It is safe to flush even those decoders that are not
+ * marked with AV_CODEC_CAP_DELAY, then no subtitles will be returned.
+ *
+ * @note The AVCodecContext MUST have been opened with @ref avcodec_open2()
+ * before packets may be fed to the decoder.
+ *
+ * @param avctx the codec context
+ * @param[out] sub The Preallocated AVSubtitle in which the decoded subtitle will be stored,
+ * must be freed with avsubtitle_free if *got_sub_ptr is set.
+ * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero.
+ * @param[in] avpkt The input AVPacket containing the input buffer.
+ */
+int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
+ int *got_sub_ptr,
+ AVPacket *avpkt);
+
+/**
+ * Supply raw packet data as input to a decoder.
+ *
+ * Internally, this call will copy relevant AVCodecContext fields, which can
+ * influence decoding per-packet, and apply them when the packet is actually
+ * decoded. (For example AVCodecContext.skip_frame, which might direct the
+ * decoder to drop the frame contained by the packet sent with this function.)
+ *
+ * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE
+ * larger than the actual read bytes because some optimized bitstream
+ * readers read 32 or 64 bits at once and could read over the end.
+ *
+ * @warning Do not mix this API with the legacy API (like avcodec_decode_video2())
+ * on the same AVCodecContext. It will return unexpected results now
+ * or in future libavcodec versions.
+ *
+ * @note The AVCodecContext MUST have been opened with @ref avcodec_open2()
+ * before packets may be fed to the decoder.
+ *
+ * @param avctx codec context
+ * @param[in] avpkt The input AVPacket. Usually, this will be a single video
+ * frame, or several complete audio frames.
+ * Ownership of the packet remains with the caller, and the
+ * decoder will not write to the packet. The decoder may create
+ * a reference to the packet data (or copy it if the packet is
+ * not reference-counted).
+ * Unlike with older APIs, the packet is always fully consumed,
+ * and if it contains multiple frames (e.g. some audio codecs),
+ * will require you to call avcodec_receive_frame() multiple
+ * times afterwards before you can send a new packet.
+ * It can be NULL (or an AVPacket with data set to NULL and
+ * size set to 0); in this case, it is considered a flush
+ * packet, which signals the end of the stream. Sending the
+ * first flush packet will return success. Subsequent ones are
+ * unnecessary and will return AVERROR_EOF. If the decoder
+ * still has frames buffered, it will return them after sending
+ * a flush packet.
+ *
+ * @return 0 on success, otherwise negative error code:
+ * AVERROR(EAGAIN): input is not accepted in the current state - user
+ * must read output with avcodec_receive_frame() (once
+ * all output is read, the packet should be resent, and
+ * the call will not fail with EAGAIN).
+ * AVERROR_EOF: the decoder has been flushed, and no new packets can
+ * be sent to it (also returned if more than 1 flush
+ * packet is sent)
+ * AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush
+ * AVERROR(ENOMEM): failed to add packet to internal queue, or similar
+ * other errors: legitimate decoding errors
+ */
+int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
+
+/**
+ * Return decoded output data from a decoder.
+ *
+ * @param avctx codec context
+ * @param frame This will be set to a reference-counted video or audio
+ * frame (depending on the decoder type) allocated by the
+ * decoder. Note that the function will always call
+ * av_frame_unref(frame) before doing anything else.
+ *
+ * @return
+ * 0: success, a frame was returned
+ * AVERROR(EAGAIN): output is not available in this state - user must try
+ * to send new input
+ * AVERROR_EOF: the decoder has been fully flushed, and there will be
+ * no more output frames
+ * AVERROR(EINVAL): codec not opened, or it is an encoder
+ * other negative values: legitimate decoding errors
+ */
+int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
+
+/**
+ * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet()
+ * to retrieve buffered output packets.
+ *
+ * @param avctx codec context
+ * @param[in] frame AVFrame containing the raw audio or video frame to be encoded.
+ * Ownership of the frame remains with the caller, and the
+ * encoder will not write to the frame. The encoder may create
+ * a reference to the frame data (or copy it if the frame is
+ * not reference-counted).
+ * It can be NULL, in which case it is considered a flush
+ * packet. This signals the end of the stream. If the encoder
+ * still has packets buffered, it will return them after this
+ * call. Once flushing mode has been entered, additional flush
+ * packets are ignored, and sending frames will return
+ * AVERROR_EOF.
+ *
+ * For audio:
+ * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame
+ * can have any number of samples.
+ * If it is not set, frame->nb_samples must be equal to
+ * avctx->frame_size for all frames except the last.
+ * The final frame may be smaller than avctx->frame_size.
+ * @return 0 on success, otherwise negative error code:
+ * AVERROR(EAGAIN): input is not accepted in the current state - user
+ * must read output with avcodec_receive_packet() (once
+ * all output is read, the packet should be resent, and
+ * the call will not fail with EAGAIN).
+ * AVERROR_EOF: the encoder has been flushed, and no new frames can
+ * be sent to it
+ * AVERROR(EINVAL): codec not opened, refcounted_frames not set, it is a
+ * decoder, or requires flush
+ * AVERROR(ENOMEM): failed to add packet to internal queue, or similar
+ * other errors: legitimate decoding errors
+ */
+int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
+
+/**
+ * Read encoded data from the encoder.
+ *
+ * @param avctx codec context
+ * @param avpkt This will be set to a reference-counted packet allocated by the
+ * encoder. Note that the function will always call
+ * av_frame_unref(frame) before doing anything else.
+ * @return 0 on success, otherwise negative error code:
+ * AVERROR(EAGAIN): output is not available in the current state - user
+ * must try to send input
+ * AVERROR_EOF: the encoder has been fully flushed, and there will be
+ * no more output packets
+ * AVERROR(EINVAL): codec not opened, or it is an encoder
+ * other errors: legitimate decoding errors
+ */
+int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
+
+/**
+ * Create and return a AVHWFramesContext with values adequate for hardware
+ * decoding. This is meant to get called from the get_format callback, and is
+ * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx.
+ * This API is for decoding with certain hardware acceleration modes/APIs only.
+ *
+ * The returned AVHWFramesContext is not initialized. The caller must do this
+ * with av_hwframe_ctx_init().
+ *
+ * Calling this function is not a requirement, but makes it simpler to avoid
+ * codec or hardware API specific details when manually allocating frames.
+ *
+ * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx,
+ * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes
+ * it unnecessary to call this function or having to care about
+ * AVHWFramesContext initialization at all.
+ *
+ * There are a number of requirements for calling this function:
+ *
+ * - It must be called from get_format with the same avctx parameter that was
+ * passed to get_format. Calling it outside of get_format is not allowed, and
+ * can trigger undefined behavior.
+ * - The function is not always supported (see description of return values).
+ * Even if this function returns successfully, hwaccel initialization could
+ * fail later. (The degree to which implementations check whether the stream
+ * is actually supported varies. Some do this check only after the user's
+ * get_format callback returns.)
+ * - The hw_pix_fmt must be one of the choices suggested by get_format. If the
+ * user decides to use a AVHWFramesContext prepared with this API function,
+ * the user must return the same hw_pix_fmt from get_format.
+ * - The device_ref passed to this function must support the given hw_pix_fmt.
+ * - After calling this API function, it is the user's responsibility to
+ * initialize the AVHWFramesContext (returned by the out_frames_ref parameter),
+ * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done
+ * before returning from get_format (this is implied by the normal
+ * AVCodecContext.hw_frames_ctx API rules).
+ * - The AVHWFramesContext parameters may change every time time get_format is
+ * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So
+ * you are inherently required to go through this process again on every
+ * get_format call.
+ * - It is perfectly possible to call this function without actually using
+ * the resulting AVHWFramesContext. One use-case might be trying to reuse a
+ * previously initialized AVHWFramesContext, and calling this API function
+ * only to test whether the required frame parameters have changed.
+ * - Fields that use dynamically allocated values of any kind must not be set
+ * by the user unless setting them is explicitly allowed by the documentation.
+ * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque,
+ * the new free callback must call the potentially set previous free callback.
+ * This API call may set any dynamically allocated fields, including the free
+ * callback.
+ *
+ * The function will set at least the following fields on AVHWFramesContext
+ * (potentially more, depending on hwaccel API):
+ *
+ * - All fields set by av_hwframe_ctx_alloc().
+ * - Set the format field to hw_pix_fmt.
+ * - Set the sw_format field to the most suited and most versatile format. (An
+ * implication is that this will prefer generic formats over opaque formats
+ * with arbitrary restrictions, if possible.)
+ * - Set the width/height fields to the coded frame size, rounded up to the
+ * API-specific minimum alignment.
+ * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size
+ * field to the number of maximum reference surfaces possible with the codec,
+ * plus 1 surface for the user to work (meaning the user can safely reference
+ * at most 1 decoded surface at a time), plus additional buffering introduced
+ * by frame threading. If the hwaccel does not require pre-allocation, the
+ * field is left to 0, and the decoder will allocate new surfaces on demand
+ * during decoding.
+ * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying
+ * hardware API.
+ *
+ * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but
+ * with basic frame parameters set.
+ *
+ * The function is stateless, and does not change the AVCodecContext or the
+ * device_ref AVHWDeviceContext.
+ *
+ * @param avctx The context which is currently calling get_format, and which
+ * implicitly contains all state needed for filling the returned
+ * AVHWFramesContext properly.
+ * @param device_ref A reference to the AVHWDeviceContext describing the device
+ * which will be used by the hardware decoder.
+ * @param hw_pix_fmt The hwaccel format you are going to return from get_format.
+ * @param out_frames_ref On success, set to a reference to an _uninitialized_
+ * AVHWFramesContext, created from the given device_ref.
+ * Fields will be set to values required for decoding.
+ * Not changed if an error is returned.
+ * @return zero on success, a negative value on error. The following error codes
+ * have special semantics:
+ * AVERROR(ENOENT): the decoder does not support this functionality. Setup
+ * is always manual, or it is a decoder which does not
+ * support setting AVCodecContext.hw_frames_ctx at all,
+ * or it is a software format.
+ * AVERROR(EINVAL): it is known that hardware decoding is not supported for
+ * this configuration, or the device_ref is not supported
+ * for the hwaccel referenced by hw_pix_fmt.
+ */
+int avcodec_get_hw_frames_parameters(AVCodecContext *avctx,
+ AVBufferRef *device_ref,
+ enum AVPixelFormat hw_pix_fmt,
+ AVBufferRef **out_frames_ref);
+
+
+
+/**
+ * @defgroup lavc_parsing Frame parsing
+ * @{
+ */
+
+enum AVPictureStructure {
+ AV_PICTURE_STRUCTURE_UNKNOWN, //< unknown
+ AV_PICTURE_STRUCTURE_TOP_FIELD, //< coded as top field
+ AV_PICTURE_STRUCTURE_BOTTOM_FIELD, //< coded as bottom field
+ AV_PICTURE_STRUCTURE_FRAME, //< coded as frame
+};
+
+typedef struct AVCodecParserContext {
+ void *priv_data;
+ struct AVCodecParser *parser;
+ int64_t frame_offset; /* offset of the current frame */
+ int64_t cur_offset; /* current offset
+ (incremented by each av_parser_parse()) */
+ int64_t next_frame_offset; /* offset of the next frame */
+ /* video info */
+ int pict_type; /* XXX: Put it back in AVCodecContext. */
+ /**
+ * This field is used for proper frame duration computation in lavf.
+ * It signals, how much longer the frame duration of the current frame
+ * is compared to normal frame duration.
+ *
+ * frame_duration = (1 + repeat_pict) * time_base
+ *
+ * It is used by codecs like H.264 to display telecined material.
+ */
+ int repeat_pict; /* XXX: Put it back in AVCodecContext. */
+ int64_t pts; /* pts of the current frame */
+ int64_t dts; /* dts of the current frame */
+
+ /* private data */
+ int64_t last_pts;
+ int64_t last_dts;
+ int fetch_timestamp;
+
+#define AV_PARSER_PTS_NB 4
+ int cur_frame_start_index;
+ int64_t cur_frame_offset[AV_PARSER_PTS_NB];
+ int64_t cur_frame_pts[AV_PARSER_PTS_NB];
+ int64_t cur_frame_dts[AV_PARSER_PTS_NB];
+
+ int flags;
+#define PARSER_FLAG_COMPLETE_FRAMES 0x0001
+#define PARSER_FLAG_ONCE 0x0002
+/// Set if the parser has a valid file offset
+#define PARSER_FLAG_FETCHED_OFFSET 0x0004
+#define PARSER_FLAG_USE_CODEC_TS 0x1000
+
+ int64_t offset; ///< byte offset from starting packet start
+ int64_t cur_frame_end[AV_PARSER_PTS_NB];
+
+ /**
+ * Set by parser to 1 for key frames and 0 for non-key frames.
+ * It is initialized to -1, so if the parser doesn't set this flag,
+ * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames
+ * will be used.
+ */
+ int key_frame;
+
+#if FF_API_CONVERGENCE_DURATION
+ /**
+ * @deprecated unused
+ */
+ attribute_deprecated
+ int64_t convergence_duration;
+#endif
+
+ // Timestamp generation support:
+ /**
+ * Synchronization point for start of timestamp generation.
+ *
+ * Set to >0 for sync point, 0 for no sync point and <0 for undefined
+ * (default).
+ *
+ * For example, this corresponds to presence of H.264 buffering period
+ * SEI message.
+ */
+ int dts_sync_point;
+
+ /**
+ * Offset of the current timestamp against last timestamp sync point in
+ * units of AVCodecContext.time_base.
+ *
+ * Set to INT_MIN when dts_sync_point unused. Otherwise, it must
+ * contain a valid timestamp offset.
+ *
+ * Note that the timestamp of sync point has usually a nonzero
+ * dts_ref_dts_delta, which refers to the previous sync point. Offset of
+ * the next frame after timestamp sync point will be usually 1.
+ *
+ * For example, this corresponds to H.264 cpb_removal_delay.
+ */
+ int dts_ref_dts_delta;
+
+ /**
+ * Presentation delay of current frame in units of AVCodecContext.time_base.
+ *
+ * Set to INT_MIN when dts_sync_point unused. Otherwise, it must
+ * contain valid non-negative timestamp delta (presentation time of a frame
+ * must not lie in the past).
+ *
+ * This delay represents the difference between decoding and presentation
+ * time of the frame.
+ *
+ * For example, this corresponds to H.264 dpb_output_delay.
+ */
+ int pts_dts_delta;
+
+ /**
+ * Position of the packet in file.
+ *
+ * Analogous to cur_frame_pts/dts
+ */
+ int64_t cur_frame_pos[AV_PARSER_PTS_NB];
+
+ /**
+ * Byte position of currently parsed frame in stream.
+ */
+ int64_t pos;
+
+ /**
+ * Previous frame byte position.
+ */
+ int64_t last_pos;
+
+ /**
+ * Duration of the current frame.
+ * For audio, this is in units of 1 / AVCodecContext.sample_rate.
+ * For all other types, this is in units of AVCodecContext.time_base.
+ */
+ int duration;
+
+ enum AVFieldOrder field_order;
+
+ /**
+ * Indicate whether a picture is coded as a frame, top field or bottom field.
+ *
+ * For example, H.264 field_pic_flag equal to 0 corresponds to
+ * AV_PICTURE_STRUCTURE_FRAME. An H.264 picture with field_pic_flag
+ * equal to 1 and bottom_field_flag equal to 0 corresponds to
+ * AV_PICTURE_STRUCTURE_TOP_FIELD.
+ */
+ enum AVPictureStructure picture_structure;
+
+ /**
+ * Picture number incremented in presentation or output order.
+ * This field may be reinitialized at the first picture of a new sequence.
+ *
+ * For example, this corresponds to H.264 PicOrderCnt.
+ */
+ int output_picture_number;
+
+ /**
+ * Dimensions of the decoded video intended for presentation.
+ */
+ int width;
+ int height;
+
+ /**
+ * Dimensions of the coded video.
+ */
+ int coded_width;
+ int coded_height;
+
+ /**
+ * The format of the coded data, corresponds to enum AVPixelFormat for video
+ * and for enum AVSampleFormat for audio.
+ *
+ * Note that a decoder can have considerable freedom in how exactly it
+ * decodes the data, so the format reported here might be different from the
+ * one returned by a decoder.
+ */
+ int format;
+} AVCodecParserContext;
+
+typedef struct AVCodecParser {
+ int codec_ids[5]; /* several codec IDs are permitted */
+ int priv_data_size;
+ int (*parser_init)(AVCodecParserContext *s);
+ /* This callback never returns an error, a negative value means that
+ * the frame start was in a previous packet. */
+ int (*parser_parse)(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ const uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size);
+ void (*parser_close)(AVCodecParserContext *s);
+ int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size);
+ struct AVCodecParser *next;
+} AVCodecParser;
+
+/**
+ * Iterate over all registered codec parsers.
+ *
+ * @param opaque a pointer where libavcodec will store the iteration state. Must
+ * point to NULL to start the iteration.
+ *
+ * @return the next registered codec parser or NULL when the iteration is
+ * finished
+ */
+const AVCodecParser *av_parser_iterate(void **opaque);
+
+attribute_deprecated
+AVCodecParser *av_parser_next(const AVCodecParser *c);
+
+attribute_deprecated
+void av_register_codec_parser(AVCodecParser *parser);
+AVCodecParserContext *av_parser_init(int codec_id);
+
+/**
+ * Parse a packet.
+ *
+ * @param s parser context.
+ * @param avctx codec context.
+ * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished.
+ * @param poutbuf_size set to size of parsed buffer or zero if not yet finished.
+ * @param buf input buffer.
+ * @param buf_size buffer size in bytes without the padding. I.e. the full buffer
+ size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE.
+ To signal EOF, this should be 0 (so that the last frame
+ can be output).
+ * @param pts input presentation timestamp.
+ * @param dts input decoding timestamp.
+ * @param pos input byte position in stream.
+ * @return the number of bytes of the input bitstream used.
+ *
+ * Example:
+ * @code
+ * while(in_len){
+ * len = av_parser_parse2(myparser, AVCodecContext, &data, &size,
+ * in_data, in_len,
+ * pts, dts, pos);
+ * in_data += len;
+ * in_len -= len;
+ *
+ * if(size)
+ * decode_frame(data, size);
+ * }
+ * @endcode
+ */
+int av_parser_parse2(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size,
+ int64_t pts, int64_t dts,
+ int64_t pos);
+
+/**
+ * @return 0 if the output buffer is a subset of the input, 1 if it is allocated and must be freed
+ * @deprecated use AVBitStreamFilter
+ */
+int av_parser_change(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size, int keyframe);
+void av_parser_close(AVCodecParserContext *s);
+
+/**
+ * @}
+ * @}
+ */
+
+/**
+ * @addtogroup lavc_encoding
+ * @{
+ */
+
+/**
+ * Find a registered encoder with a matching codec ID.
+ *
+ * @param id AVCodecID of the requested encoder
+ * @return An encoder if one was found, NULL otherwise.
+ */
+AVCodec *avcodec_find_encoder(enum AVCodecID id);
+
+/**
+ * Find a registered encoder with the specified name.
+ *
+ * @param name name of the requested encoder
+ * @return An encoder if one was found, NULL otherwise.
+ */
+AVCodec *avcodec_find_encoder_by_name(const char *name);
+
+/**
+ * Encode a frame of audio.
+ *
+ * Takes input samples from frame and writes the next output packet, if
+ * available, to avpkt. The output packet does not necessarily contain data for
+ * the most recent frame, as encoders can delay, split, and combine input frames
+ * internally as needed.
+ *
+ * @param avctx codec context
+ * @param avpkt output AVPacket.
+ * The user can supply an output buffer by setting
+ * avpkt->data and avpkt->size prior to calling the
+ * function, but if the size of the user-provided data is not
+ * large enough, encoding will fail. If avpkt->data and
+ * avpkt->size are set, avpkt->destruct must also be set. All
+ * other AVPacket fields will be reset by the encoder using
+ * av_init_packet(). If avpkt->data is NULL, the encoder will
+ * allocate it. The encoder will set avpkt->size to the size
+ * of the output packet.
+ *
+ * If this function fails or produces no output, avpkt will be
+ * freed using av_packet_unref().
+ * @param[in] frame AVFrame containing the raw audio data to be encoded.
+ * May be NULL when flushing an encoder that has the
+ * AV_CODEC_CAP_DELAY capability set.
+ * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame
+ * can have any number of samples.
+ * If it is not set, frame->nb_samples must be equal to
+ * avctx->frame_size for all frames except the last.
+ * The final frame may be smaller than avctx->frame_size.
+ * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the
+ * output packet is non-empty, and to 0 if it is
+ * empty. If the function returns an error, the
+ * packet can be assumed to be invalid, and the
+ * value of got_packet_ptr is undefined and should
+ * not be used.
+ * @return 0 on success, negative error code on failure
+ *
+ * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead
+ */
+attribute_deprecated
+int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr);
+
+/**
+ * Encode a frame of video.
+ *
+ * Takes input raw video data from frame and writes the next output packet, if
+ * available, to avpkt. The output packet does not necessarily contain data for
+ * the most recent frame, as encoders can delay and reorder input frames
+ * internally as needed.
+ *
+ * @param avctx codec context
+ * @param avpkt output AVPacket.
+ * The user can supply an output buffer by setting
+ * avpkt->data and avpkt->size prior to calling the
+ * function, but if the size of the user-provided data is not
+ * large enough, encoding will fail. All other AVPacket fields
+ * will be reset by the encoder using av_init_packet(). If
+ * avpkt->data is NULL, the encoder will allocate it.
+ * The encoder will set avpkt->size to the size of the
+ * output packet. The returned data (if any) belongs to the
+ * caller, he is responsible for freeing it.
+ *
+ * If this function fails or produces no output, avpkt will be
+ * freed using av_packet_unref().
+ * @param[in] frame AVFrame containing the raw video data to be encoded.
+ * May be NULL when flushing an encoder that has the
+ * AV_CODEC_CAP_DELAY capability set.
+ * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the
+ * output packet is non-empty, and to 0 if it is
+ * empty. If the function returns an error, the
+ * packet can be assumed to be invalid, and the
+ * value of got_packet_ptr is undefined and should
+ * not be used.
+ * @return 0 on success, negative error code on failure
+ *
+ * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead
+ */
+attribute_deprecated
+int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr);
+
+int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+ const AVSubtitle *sub);
+
+
+/**
+ * @}
+ */
+
+#if FF_API_AVPICTURE
+/**
+ * @addtogroup lavc_picture
+ * @{
+ */
+
+/**
+ * @deprecated unused
+ */
+attribute_deprecated
+int avpicture_alloc(AVPicture *picture, enum AVPixelFormat pix_fmt, int width, int height);
+
+/**
+ * @deprecated unused
+ */
+attribute_deprecated
+void avpicture_free(AVPicture *picture);
+
+/**
+ * @deprecated use av_image_fill_arrays() instead.
+ */
+attribute_deprecated
+int avpicture_fill(AVPicture *picture, const uint8_t *ptr,
+ enum AVPixelFormat pix_fmt, int width, int height);
+
+/**
+ * @deprecated use av_image_copy_to_buffer() instead.
+ */
+attribute_deprecated
+int avpicture_layout(const AVPicture *src, enum AVPixelFormat pix_fmt,
+ int width, int height,
+ unsigned char *dest, int dest_size);
+
+/**
+ * @deprecated use av_image_get_buffer_size() instead.
+ */
+attribute_deprecated
+int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height);
+
+/**
+ * @deprecated av_image_copy() instead.
+ */
+attribute_deprecated
+void av_picture_copy(AVPicture *dst, const AVPicture *src,
+ enum AVPixelFormat pix_fmt, int width, int height);
+
+/**
+ * @deprecated unused
+ */
+attribute_deprecated
+int av_picture_crop(AVPicture *dst, const AVPicture *src,
+ enum AVPixelFormat pix_fmt, int top_band, int left_band);
+
+/**
+ * @deprecated unused
+ */
+attribute_deprecated
+int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, enum AVPixelFormat pix_fmt,
+ int padtop, int padbottom, int padleft, int padright, int *color);
+
+/**
+ * @}
+ */
+#endif
+
+/**
+ * @defgroup lavc_misc Utility functions
+ * @ingroup libavc
+ *
+ * Miscellaneous utility functions related to both encoding and decoding
+ * (or neither).
+ * @{
+ */
+
+/**
+ * @defgroup lavc_misc_pixfmt Pixel formats
+ *
+ * Functions for working with pixel formats.
+ * @{
+ */
+
+#if FF_API_GETCHROMA
+/**
+ * @deprecated Use av_pix_fmt_get_chroma_sub_sample
+ */
+
+attribute_deprecated
+void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift);
+#endif
+
+/**
+ * Return a value representing the fourCC code associated to the
+ * pixel format pix_fmt, or 0 if no associated fourCC code can be
+ * found.
+ */
+unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt);
+
+/**
+ * @deprecated see av_get_pix_fmt_loss()
+ */
+int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt,
+ int has_alpha);
+
+/**
+ * Find the best pixel format to convert to given a certain source pixel
+ * format. When converting from one pixel format to another, information loss
+ * may occur. For example, when converting from RGB24 to GRAY, the color
+ * information will be lost. Similarly, other losses occur when converting from
+ * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of
+ * the given pixel formats should be used to suffer the least amount of loss.
+ * The pixel formats from which it chooses one, are determined by the
+ * pix_fmt_list parameter.
+ *
+ *
+ * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from
+ * @param[in] src_pix_fmt source pixel format
+ * @param[in] has_alpha Whether the source pixel format alpha channel is used.
+ * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur.
+ * @return The best pixel format to convert to or -1 if none was found.
+ */
+enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list,
+ enum AVPixelFormat src_pix_fmt,
+ int has_alpha, int *loss_ptr);
+
+/**
+ * @deprecated see av_find_best_pix_fmt_of_2()
+ */
+enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
+ enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr);
+
+attribute_deprecated
+enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
+ enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr);
+
+enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt);
+
+/**
+ * @}
+ */
+
+#if FF_API_TAG_STRING
+/**
+ * Put a string representing the codec tag codec_tag in buf.
+ *
+ * @param buf buffer to place codec tag in
+ * @param buf_size size in bytes of buf
+ * @param codec_tag codec tag to assign
+ * @return the length of the string that would have been generated if
+ * enough space had been available, excluding the trailing null
+ *
+ * @deprecated see av_fourcc_make_string() and av_fourcc2str().
+ */
+attribute_deprecated
+size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag);
+#endif
+
+void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode);
+
+/**
+ * Return a name for the specified profile, if available.
+ *
+ * @param codec the codec that is searched for the given profile
+ * @param profile the profile value for which a name is requested
+ * @return A name for the profile if found, NULL otherwise.
+ */
+const char *av_get_profile_name(const AVCodec *codec, int profile);
+
+/**
+ * Return a name for the specified profile, if available.
+ *
+ * @param codec_id the ID of the codec to which the requested profile belongs
+ * @param profile the profile value for which a name is requested
+ * @return A name for the profile if found, NULL otherwise.
+ *
+ * @note unlike av_get_profile_name(), which searches a list of profiles
+ * supported by a specific decoder or encoder implementation, this
+ * function searches the list of profiles from the AVCodecDescriptor
+ */
+const char *avcodec_profile_name(enum AVCodecID codec_id, int profile);
+
+int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size);
+int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count);
+//FIXME func typedef
+
+/**
+ * Fill AVFrame audio data and linesize pointers.
+ *
+ * The buffer buf must be a preallocated buffer with a size big enough
+ * to contain the specified samples amount. The filled AVFrame data
+ * pointers will point to this buffer.
+ *
+ * AVFrame extended_data channel pointers are allocated if necessary for
+ * planar audio.
+ *
+ * @param frame the AVFrame
+ * frame->nb_samples must be set prior to calling the
+ * function. This function fills in frame->data,
+ * frame->extended_data, frame->linesize[0].
+ * @param nb_channels channel count
+ * @param sample_fmt sample format
+ * @param buf buffer to use for frame data
+ * @param buf_size size of buffer
+ * @param align plane size sample alignment (0 = default)
+ * @return >=0 on success, negative error code on failure
+ * @todo return the size in bytes required to store the samples in
+ * case of success, at the next libavutil bump
+ */
+int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
+ enum AVSampleFormat sample_fmt, const uint8_t *buf,
+ int buf_size, int align);
+
+/**
+ * Reset the internal decoder state / flush internal buffers. Should be called
+ * e.g. when seeking or when switching to a different stream.
+ *
+ * @note when refcounted frames are not used (i.e. avctx->refcounted_frames is 0),
+ * this invalidates the frames previously returned from the decoder. When
+ * refcounted frames are used, the decoder just releases any references it might
+ * keep internally, but the caller's reference remains valid.
+ */
+void avcodec_flush_buffers(AVCodecContext *avctx);
+
+/**
+ * Return codec bits per sample.
+ *
+ * @param[in] codec_id the codec
+ * @return Number of bits per sample or zero if unknown for the given codec.
+ */
+int av_get_bits_per_sample(enum AVCodecID codec_id);
+
+/**
+ * Return the PCM codec associated with a sample format.
+ * @param be endianness, 0 for little, 1 for big,
+ * -1 (or anything else) for native
+ * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE
+ */
+enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be);
+
+/**
+ * Return codec bits per sample.
+ * Only return non-zero if the bits per sample is exactly correct, not an
+ * approximation.
+ *
+ * @param[in] codec_id the codec
+ * @return Number of bits per sample or zero if unknown for the given codec.
+ */
+int av_get_exact_bits_per_sample(enum AVCodecID codec_id);
+
+/**
+ * Return audio frame duration.
+ *
+ * @param avctx codec context
+ * @param frame_bytes size of the frame, or 0 if unknown
+ * @return frame duration, in samples, if known. 0 if not able to
+ * determine.
+ */
+int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes);
+
+/**
+ * This function is the same as av_get_audio_frame_duration(), except it works
+ * with AVCodecParameters instead of an AVCodecContext.
+ */
+int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes);
+
+#if FF_API_OLD_BSF
+typedef struct AVBitStreamFilterContext {
+ void *priv_data;
+ const struct AVBitStreamFilter *filter;
+ AVCodecParserContext *parser;
+ struct AVBitStreamFilterContext *next;
+ /**
+ * Internal default arguments, used if NULL is passed to av_bitstream_filter_filter().
+ * Not for access by library users.
+ */
+ char *args;
+} AVBitStreamFilterContext;
+#endif
+
+typedef struct AVBSFInternal AVBSFInternal;
+
+/**
+ * The bitstream filter state.
+ *
+ * This struct must be allocated with av_bsf_alloc() and freed with
+ * av_bsf_free().
+ *
+ * The fields in the struct will only be changed (by the caller or by the
+ * filter) as described in their documentation, and are to be considered
+ * immutable otherwise.
+ */
+typedef struct AVBSFContext {
+ /**
+ * A class for logging and AVOptions
+ */
+ const AVClass *av_class;
+
+ /**
+ * The bitstream filter this context is an instance of.
+ */
+ const struct AVBitStreamFilter *filter;
+
+ /**
+ * Opaque libavcodec internal data. Must not be touched by the caller in any
+ * way.
+ */
+ AVBSFInternal *internal;
+
+ /**
+ * Opaque filter-specific private data. If filter->priv_class is non-NULL,
+ * this is an AVOptions-enabled struct.
+ */
+ void *priv_data;
+
+ /**
+ * Parameters of the input stream. This field is allocated in
+ * av_bsf_alloc(), it needs to be filled by the caller before
+ * av_bsf_init().
+ */
+ AVCodecParameters *par_in;
+
+ /**
+ * Parameters of the output stream. This field is allocated in
+ * av_bsf_alloc(), it is set by the filter in av_bsf_init().
+ */
+ AVCodecParameters *par_out;
+
+ /**
+ * The timebase used for the timestamps of the input packets. Set by the
+ * caller before av_bsf_init().
+ */
+ AVRational time_base_in;
+
+ /**
+ * The timebase used for the timestamps of the output packets. Set by the
+ * filter in av_bsf_init().
+ */
+ AVRational time_base_out;
+} AVBSFContext;
+
+typedef struct AVBitStreamFilter {
+ const char *name;
+
+ /**
+ * A list of codec ids supported by the filter, terminated by
+ * AV_CODEC_ID_NONE.
+ * May be NULL, in that case the bitstream filter works with any codec id.
+ */
+ const enum AVCodecID *codec_ids;
+
+ /**
+ * A class for the private data, used to declare bitstream filter private
+ * AVOptions. This field is NULL for bitstream filters that do not declare
+ * any options.
+ *
+ * If this field is non-NULL, the first member of the filter private data
+ * must be a pointer to AVClass, which will be set by libavcodec generic
+ * code to this class.
+ */
+ const AVClass *priv_class;
+
+ /*****************************************************************
+ * No fields below this line are part of the public API. They
+ * may not be used outside of libavcodec and can be changed and
+ * removed at will.
+ * New public fields should be added right above.
+ *****************************************************************
+ */
+
+ int priv_data_size;
+ int (*init)(AVBSFContext *ctx);
+ int (*filter)(AVBSFContext *ctx, AVPacket *pkt);
+ void (*close)(AVBSFContext *ctx);
+} AVBitStreamFilter;
+
+#if FF_API_OLD_BSF
+/**
+ * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext)
+ * is deprecated. Use the new bitstream filtering API (using AVBSFContext).
+ */
+attribute_deprecated
+void av_register_bitstream_filter(AVBitStreamFilter *bsf);
+/**
+ * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext)
+ * is deprecated. Use av_bsf_get_by_name(), av_bsf_alloc(), and av_bsf_init()
+ * from the new bitstream filtering API (using AVBSFContext).
+ */
+attribute_deprecated
+AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
+/**
+ * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext)
+ * is deprecated. Use av_bsf_send_packet() and av_bsf_receive_packet() from the
+ * new bitstream filtering API (using AVBSFContext).
+ */
+attribute_deprecated
+int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
+ AVCodecContext *avctx, const char *args,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size, int keyframe);
+/**
+ * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext)
+ * is deprecated. Use av_bsf_free() from the new bitstream filtering API (using
+ * AVBSFContext).
+ */
+attribute_deprecated
+void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
+/**
+ * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext)
+ * is deprecated. Use av_bsf_iterate() from the new bitstream filtering API (using
+ * AVBSFContext).
+ */
+attribute_deprecated
+const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f);
+#endif
+
+/**
+ * @return a bitstream filter with the specified name or NULL if no such
+ * bitstream filter exists.
+ */
+const AVBitStreamFilter *av_bsf_get_by_name(const char *name);
+
+/**
+ * Iterate over all registered bitstream filters.
+ *
+ * @param opaque a pointer where libavcodec will store the iteration state. Must
+ * point to NULL to start the iteration.
+ *
+ * @return the next registered bitstream filter or NULL when the iteration is
+ * finished
+ */
+const AVBitStreamFilter *av_bsf_iterate(void **opaque);
+#if FF_API_NEXT
+attribute_deprecated
+const AVBitStreamFilter *av_bsf_next(void **opaque);
+#endif
+
+/**
+ * Allocate a context for a given bitstream filter. The caller must fill in the
+ * context parameters as described in the documentation and then call
+ * av_bsf_init() before sending any data to the filter.
+ *
+ * @param filter the filter for which to allocate an instance.
+ * @param ctx a pointer into which the pointer to the newly-allocated context
+ * will be written. It must be freed with av_bsf_free() after the
+ * filtering is done.
+ *
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx);
+
+/**
+ * Prepare the filter for use, after all the parameters and options have been
+ * set.
+ */
+int av_bsf_init(AVBSFContext *ctx);
+
+/**
+ * Submit a packet for filtering.
+ *
+ * After sending each packet, the filter must be completely drained by calling
+ * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or
+ * AVERROR_EOF.
+ *
+ * @param pkt the packet to filter. The bitstream filter will take ownership of
+ * the packet and reset the contents of pkt. pkt is not touched if an error occurs.
+ * This parameter may be NULL, which signals the end of the stream (i.e. no more
+ * packets will be sent). That will cause the filter to output any packets it
+ * may have buffered internally.
+ *
+ * @return 0 on success, a negative AVERROR on error.
+ */
+int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt);
+
+/**
+ * Retrieve a filtered packet.
+ *
+ * @param[out] pkt this struct will be filled with the contents of the filtered
+ * packet. It is owned by the caller and must be freed using
+ * av_packet_unref() when it is no longer needed.
+ * This parameter should be "clean" (i.e. freshly allocated
+ * with av_packet_alloc() or unreffed with av_packet_unref())
+ * when this function is called. If this function returns
+ * successfully, the contents of pkt will be completely
+ * overwritten by the returned data. On failure, pkt is not
+ * touched.
+ *
+ * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the
+ * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there
+ * will be no further output from the filter. Another negative AVERROR value if
+ * an error occurs.
+ *
+ * @note one input packet may result in several output packets, so after sending
+ * a packet with av_bsf_send_packet(), this function needs to be called
+ * repeatedly until it stops returning 0. It is also possible for a filter to
+ * output fewer packets than were sent to it, so this function may return
+ * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call.
+ */
+int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt);
+
+/**
+ * Free a bitstream filter context and everything associated with it; write NULL
+ * into the supplied pointer.
+ */
+void av_bsf_free(AVBSFContext **ctx);
+
+/**
+ * Get the AVClass for AVBSFContext. It can be used in combination with
+ * AV_OPT_SEARCH_FAKE_OBJ for examining options.
+ *
+ * @see av_opt_find().
+ */
+const AVClass *av_bsf_get_class(void);
+
+/**
+ * Structure for chain/list of bitstream filters.
+ * Empty list can be allocated by av_bsf_list_alloc().
+ */
+typedef struct AVBSFList AVBSFList;
+
+/**
+ * Allocate empty list of bitstream filters.
+ * The list must be later freed by av_bsf_list_free()
+ * or finalized by av_bsf_list_finalize().
+ *
+ * @return Pointer to @ref AVBSFList on success, NULL in case of failure
+ */
+AVBSFList *av_bsf_list_alloc(void);
+
+/**
+ * Free list of bitstream filters.
+ *
+ * @param lst Pointer to pointer returned by av_bsf_list_alloc()
+ */
+void av_bsf_list_free(AVBSFList **lst);
+
+/**
+ * Append bitstream filter to the list of bitstream filters.
+ *
+ * @param lst List to append to
+ * @param bsf Filter context to be appended
+ *
+ * @return >=0 on success, negative AVERROR in case of failure
+ */
+int av_bsf_list_append(AVBSFList *lst, AVBSFContext *bsf);
+
+/**
+ * Construct new bitstream filter context given it's name and options
+ * and append it to the list of bitstream filters.
+ *
+ * @param lst List to append to
+ * @param bsf_name Name of the bitstream filter
+ * @param options Options for the bitstream filter, can be set to NULL
+ *
+ * @return >=0 on success, negative AVERROR in case of failure
+ */
+int av_bsf_list_append2(AVBSFList *lst, const char * bsf_name, AVDictionary **options);
+/**
+ * Finalize list of bitstream filters.
+ *
+ * This function will transform @ref AVBSFList to single @ref AVBSFContext,
+ * so the whole chain of bitstream filters can be treated as single filter
+ * freshly allocated by av_bsf_alloc().
+ * If the call is successful, @ref AVBSFList structure is freed and lst
+ * will be set to NULL. In case of failure, caller is responsible for
+ * freeing the structure by av_bsf_list_free()
+ *
+ * @param lst Filter list structure to be transformed
+ * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure
+ * representing the chain of bitstream filters
+ *
+ * @return >=0 on success, negative AVERROR in case of failure
+ */
+int av_bsf_list_finalize(AVBSFList **lst, AVBSFContext **bsf);
+
+/**
+ * Parse string describing list of bitstream filters and create single
+ * @ref AVBSFContext describing the whole chain of bitstream filters.
+ * Resulting @ref AVBSFContext can be treated as any other @ref AVBSFContext freshly
+ * allocated by av_bsf_alloc().
+ *
+ * @param str String describing chain of bitstream filters in format
+ * `bsf1[=opt1=val1:opt2=val2][,bsf2]`
+ * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure
+ * representing the chain of bitstream filters
+ *
+ * @return >=0 on success, negative AVERROR in case of failure
+ */
+int av_bsf_list_parse_str(const char *str, AVBSFContext **bsf);
+
+/**
+ * Get null/pass-through bitstream filter.
+ *
+ * @param[out] bsf Pointer to be set to new instance of pass-through bitstream filter
+ *
+ * @return
+ */
+int av_bsf_get_null_filter(AVBSFContext **bsf);
+
+/* memory */
+
+/**
+ * Same behaviour av_fast_malloc but the buffer has additional
+ * AV_INPUT_BUFFER_PADDING_SIZE at the end which will always be 0.
+ *
+ * In addition the whole buffer will initially and after resizes
+ * be 0-initialized so that no uninitialized data will ever appear.
+ */
+void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size);
+
+/**
+ * Same behaviour av_fast_padded_malloc except that buffer will always
+ * be 0-initialized after call.
+ */
+void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size);
+
+/**
+ * Encode extradata length to a buffer. Used by xiph codecs.
+ *
+ * @param s buffer to write to; must be at least (v/255+1) bytes long
+ * @param v size of extradata in bytes
+ * @return number of bytes written to the buffer.
+ */
+unsigned int av_xiphlacing(unsigned char *s, unsigned int v);
+
+#if FF_API_USER_VISIBLE_AVHWACCEL
+/**
+ * Register the hardware accelerator hwaccel.
+ *
+ * @deprecated This function doesn't do anything.
+ */
+attribute_deprecated
+void av_register_hwaccel(AVHWAccel *hwaccel);
+
+/**
+ * If hwaccel is NULL, returns the first registered hardware accelerator,
+ * if hwaccel is non-NULL, returns the next registered hardware accelerator
+ * after hwaccel, or NULL if hwaccel is the last one.
+ *
+ * @deprecated AVHWaccel structures contain no user-serviceable parts, so
+ * this function should not be used.
+ */
+attribute_deprecated
+AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel);
+#endif
+
+#if FF_API_LOCKMGR
+/**
+ * Lock operation used by lockmgr
+ *
+ * @deprecated Deprecated together with av_lockmgr_register().
+ */
+enum AVLockOp {
+ AV_LOCK_CREATE, ///< Create a mutex
+ AV_LOCK_OBTAIN, ///< Lock the mutex
+ AV_LOCK_RELEASE, ///< Unlock the mutex
+ AV_LOCK_DESTROY, ///< Free mutex resources
+};
+
+/**
+ * Register a user provided lock manager supporting the operations
+ * specified by AVLockOp. The "mutex" argument to the function points
+ * to a (void *) where the lockmgr should store/get a pointer to a user
+ * allocated mutex. It is NULL upon AV_LOCK_CREATE and equal to the
+ * value left by the last call for all other ops. If the lock manager is
+ * unable to perform the op then it should leave the mutex in the same
+ * state as when it was called and return a non-zero value. However,
+ * when called with AV_LOCK_DESTROY the mutex will always be assumed to
+ * have been successfully destroyed. If av_lockmgr_register succeeds
+ * it will return a non-negative value, if it fails it will return a
+ * negative value and destroy all mutex and unregister all callbacks.
+ * av_lockmgr_register is not thread-safe, it must be called from a
+ * single thread before any calls which make use of locking are used.
+ *
+ * @param cb User defined callback. av_lockmgr_register invokes calls
+ * to this callback and the previously registered callback.
+ * The callback will be used to create more than one mutex
+ * each of which must be backed by its own underlying locking
+ * mechanism (i.e. do not use a single static object to
+ * implement your lock manager). If cb is set to NULL the
+ * lockmgr will be unregistered.
+ *
+ * @deprecated This function does nothing, and always returns 0. Be sure to
+ * build with thread support to get basic thread safety.
+ */
+attribute_deprecated
+int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op));
+#endif
+
+/**
+ * Get the type of the given codec.
+ */
+enum AVMediaType avcodec_get_type(enum AVCodecID codec_id);
+
+/**
+ * Get the name of a codec.
+ * @return a static string identifying the codec; never NULL
+ */
+const char *avcodec_get_name(enum AVCodecID id);
+
+/**
+ * @return a positive value if s is open (i.e. avcodec_open2() was called on it
+ * with no corresponding avcodec_close()), 0 otherwise.
+ */
+int avcodec_is_open(AVCodecContext *s);
+
+/**
+ * @return a non-zero number if codec is an encoder, zero otherwise
+ */
+int av_codec_is_encoder(const AVCodec *codec);
+
+/**
+ * @return a non-zero number if codec is a decoder, zero otherwise
+ */
+int av_codec_is_decoder(const AVCodec *codec);
+
+/**
+ * @return descriptor for given codec ID or NULL if no descriptor exists.
+ */
+const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id);
+
+/**
+ * Iterate over all codec descriptors known to libavcodec.
+ *
+ * @param prev previous descriptor. NULL to get the first descriptor.
+ *
+ * @return next descriptor or NULL after the last descriptor
+ */
+const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev);
+
+/**
+ * @return codec descriptor with the given name or NULL if no such descriptor
+ * exists.
+ */
+const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name);
+
+/**
+ * Allocate a CPB properties structure and initialize its fields to default
+ * values.
+ *
+ * @param size if non-NULL, the size of the allocated struct will be written
+ * here. This is useful for embedding it in side data.
+ *
+ * @return the newly allocated struct or NULL on failure
+ */
+AVCPBProperties *av_cpb_properties_alloc(size_t *size);
+
+/**
+ * @}
+ */
+
+#endif /* AVCODEC_AVCODEC_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/avfft.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/avfft.h
new file mode 100644
index 000000000..0c0f9b8d8
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/avfft.h
@@ -0,0 +1,118 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_AVFFT_H
+#define AVCODEC_AVFFT_H
+
+/**
+ * @file
+ * @ingroup lavc_fft
+ * FFT functions
+ */
+
+/**
+ * @defgroup lavc_fft FFT functions
+ * @ingroup lavc_misc
+ *
+ * @{
+ */
+
+typedef float FFTSample;
+
+typedef struct FFTComplex {
+ FFTSample re, im;
+} FFTComplex;
+
+typedef struct FFTContext FFTContext;
+
+/**
+ * Set up a complex FFT.
+ * @param nbits log2 of the length of the input array
+ * @param inverse if 0 perform the forward transform, if 1 perform the inverse
+ */
+FFTContext *av_fft_init(int nbits, int inverse);
+
+/**
+ * Do the permutation needed BEFORE calling ff_fft_calc().
+ */
+void av_fft_permute(FFTContext *s, FFTComplex *z);
+
+/**
+ * Do a complex FFT with the parameters defined in av_fft_init(). The
+ * input data must be permuted before. No 1.0/sqrt(n) normalization is done.
+ */
+void av_fft_calc(FFTContext *s, FFTComplex *z);
+
+void av_fft_end(FFTContext *s);
+
+FFTContext *av_mdct_init(int nbits, int inverse, double scale);
+void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);
+void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input);
+void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);
+void av_mdct_end(FFTContext *s);
+
+/* Real Discrete Fourier Transform */
+
+enum RDFTransformType {
+ DFT_R2C,
+ IDFT_C2R,
+ IDFT_R2C,
+ DFT_C2R,
+};
+
+typedef struct RDFTContext RDFTContext;
+
+/**
+ * Set up a real FFT.
+ * @param nbits log2 of the length of the input array
+ * @param trans the type of transform
+ */
+RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans);
+void av_rdft_calc(RDFTContext *s, FFTSample *data);
+void av_rdft_end(RDFTContext *s);
+
+/* Discrete Cosine Transform */
+
+typedef struct DCTContext DCTContext;
+
+enum DCTTransformType {
+ DCT_II = 0,
+ DCT_III,
+ DCT_I,
+ DST_I,
+};
+
+/**
+ * Set up DCT.
+ *
+ * @param nbits size of the input array:
+ * (1 << nbits) for DCT-II, DCT-III and DST-I
+ * (1 << nbits) + 1 for DCT-I
+ * @param type the type of transform
+ *
+ * @note the first element of the input of DST-I is ignored
+ */
+DCTContext *av_dct_init(int nbits, enum DCTTransformType type);
+void av_dct_calc(DCTContext *s, FFTSample *data);
+void av_dct_end (DCTContext *s);
+
+/**
+ * @}
+ */
+
+#endif /* AVCODEC_AVFFT_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/vaapi.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/vaapi.h
new file mode 100644
index 000000000..2cf7da588
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/vaapi.h
@@ -0,0 +1,86 @@
+/*
+ * Video Acceleration API (shared data between FFmpeg and the video player)
+ * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1
+ *
+ * Copyright (C) 2008-2009 Splitted-Desktop Systems
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VAAPI_H
+#define AVCODEC_VAAPI_H
+
+/**
+ * @file
+ * @ingroup lavc_codec_hwaccel_vaapi
+ * Public libavcodec VA API header.
+ */
+
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "version.h"
+
+#if FF_API_STRUCT_VAAPI_CONTEXT
+
+/**
+ * @defgroup lavc_codec_hwaccel_vaapi VA API Decoding
+ * @ingroup lavc_codec_hwaccel
+ * @{
+ */
+
+/**
+ * This structure is used to share data between the FFmpeg library and
+ * the client video application.
+ * This shall be zero-allocated and available as
+ * AVCodecContext.hwaccel_context. All user members can be set once
+ * during initialization or through each AVCodecContext.get_buffer()
+ * function call. In any case, they must be valid prior to calling
+ * decoding functions.
+ *
+ * Deprecated: use AVCodecContext.hw_frames_ctx instead.
+ */
+struct attribute_deprecated vaapi_context {
+ /**
+ * Window system dependent data
+ *
+ * - encoding: unused
+ * - decoding: Set by user
+ */
+ void *display;
+
+ /**
+ * Configuration ID
+ *
+ * - encoding: unused
+ * - decoding: Set by user
+ */
+ uint32_t config_id;
+
+ /**
+ * Context ID (video decode pipeline)
+ *
+ * - encoding: unused
+ * - decoding: Set by user
+ */
+ uint32_t context_id;
+};
+
+/* @} */
+
+#endif /* FF_API_STRUCT_VAAPI_CONTEXT */
+
+#endif /* AVCODEC_VAAPI_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/vdpau.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/vdpau.h
new file mode 100644
index 000000000..4d9994336
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/vdpau.h
@@ -0,0 +1,176 @@
+/*
+ * The Video Decode and Presentation API for UNIX (VDPAU) is used for
+ * hardware-accelerated decoding of MPEG-1/2, H.264 and VC-1.
+ *
+ * Copyright (C) 2008 NVIDIA
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VDPAU_H
+#define AVCODEC_VDPAU_H
+
+/**
+ * @file
+ * @ingroup lavc_codec_hwaccel_vdpau
+ * Public libavcodec VDPAU header.
+ */
+
+
+/**
+ * @defgroup lavc_codec_hwaccel_vdpau VDPAU Decoder and Renderer
+ * @ingroup lavc_codec_hwaccel
+ *
+ * VDPAU hardware acceleration has two modules
+ * - VDPAU decoding
+ * - VDPAU presentation
+ *
+ * The VDPAU decoding module parses all headers using FFmpeg
+ * parsing mechanisms and uses VDPAU for the actual decoding.
+ *
+ * As per the current implementation, the actual decoding
+ * and rendering (API calls) are done as part of the VDPAU
+ * presentation (vo_vdpau.c) module.
+ *
+ * @{
+ */
+
+#include <vdpau/vdpau.h>
+
+#include "libavutil/avconfig.h"
+#include "libavutil/attributes.h"
+
+#include "avcodec.h"
+#include "version.h"
+
+struct AVCodecContext;
+struct AVFrame;
+
+typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
+ const VdpPictureInfo *, uint32_t,
+ const VdpBitstreamBuffer *);
+
+/**
+ * This structure is used to share data between the libavcodec library and
+ * the client video application.
+ * The user shall allocate the structure via the av_alloc_vdpau_hwaccel
+ * function and make it available as
+ * AVCodecContext.hwaccel_context. Members can be set by the user once
+ * during initialization or through each AVCodecContext.get_buffer()
+ * function call. In any case, they must be valid prior to calling
+ * decoding functions.
+ *
+ * The size of this structure is not a part of the public ABI and must not
+ * be used outside of libavcodec. Use av_vdpau_alloc_context() to allocate an
+ * AVVDPAUContext.
+ */
+typedef struct AVVDPAUContext {
+ /**
+ * VDPAU decoder handle
+ *
+ * Set by user.
+ */
+ VdpDecoder decoder;
+
+ /**
+ * VDPAU decoder render callback
+ *
+ * Set by the user.
+ */
+ VdpDecoderRender *render;
+
+ AVVDPAU_Render2 render2;
+} AVVDPAUContext;
+
+/**
+ * @brief allocation function for AVVDPAUContext
+ *
+ * Allows extending the struct without breaking API/ABI
+ */
+AVVDPAUContext *av_alloc_vdpaucontext(void);
+
+AVVDPAU_Render2 av_vdpau_hwaccel_get_render2(const AVVDPAUContext *);
+void av_vdpau_hwaccel_set_render2(AVVDPAUContext *, AVVDPAU_Render2);
+
+/**
+ * Associate a VDPAU device with a codec context for hardware acceleration.
+ * This function is meant to be called from the get_format() codec callback,
+ * or earlier. It can also be called after avcodec_flush_buffers() to change
+ * the underlying VDPAU device mid-stream (e.g. to recover from non-transparent
+ * display preemption).
+ *
+ * @note get_format() must return AV_PIX_FMT_VDPAU if this function completes
+ * successfully.
+ *
+ * @param avctx decoding context whose get_format() callback is invoked
+ * @param device VDPAU device handle to use for hardware acceleration
+ * @param get_proc_address VDPAU device driver
+ * @param flags zero of more OR'd AV_HWACCEL_FLAG_* flags
+ *
+ * @return 0 on success, an AVERROR code on failure.
+ */
+int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,
+ VdpGetProcAddress *get_proc_address, unsigned flags);
+
+/**
+ * Gets the parameters to create an adequate VDPAU video surface for the codec
+ * context using VDPAU hardware decoding acceleration.
+ *
+ * @note Behavior is undefined if the context was not successfully bound to a
+ * VDPAU device using av_vdpau_bind_context().
+ *
+ * @param avctx the codec context being used for decoding the stream
+ * @param type storage space for the VDPAU video surface chroma type
+ * (or NULL to ignore)
+ * @param width storage space for the VDPAU video surface pixel width
+ * (or NULL to ignore)
+ * @param height storage space for the VDPAU video surface pixel height
+ * (or NULL to ignore)
+ *
+ * @return 0 on success, a negative AVERROR code on failure.
+ */
+int av_vdpau_get_surface_parameters(AVCodecContext *avctx, VdpChromaType *type,
+ uint32_t *width, uint32_t *height);
+
+/**
+ * Allocate an AVVDPAUContext.
+ *
+ * @return Newly-allocated AVVDPAUContext or NULL on failure.
+ */
+AVVDPAUContext *av_vdpau_alloc_context(void);
+
+#if FF_API_VDPAU_PROFILE
+/**
+ * Get a decoder profile that should be used for initializing a VDPAU decoder.
+ * Should be called from the AVCodecContext.get_format() callback.
+ *
+ * @deprecated Use av_vdpau_bind_context() instead.
+ *
+ * @param avctx the codec context being used for decoding the stream
+ * @param profile a pointer into which the result will be written on success.
+ * The contents of profile are undefined if this function returns
+ * an error.
+ *
+ * @return 0 on success (non-negative), a negative AVERROR on failure.
+ */
+attribute_deprecated
+int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile);
+#endif
+
+/* @}*/
+
+#endif /* AVCODEC_VDPAU_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/version.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/version.h
new file mode 100644
index 000000000..6895f1a46
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavcodec/version.h
@@ -0,0 +1,137 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VERSION_H
+#define AVCODEC_VERSION_H
+
+/**
+ * @file
+ * @ingroup libavc
+ * Libavcodec version macros.
+ */
+
+#include "libavutil/version.h"
+
+#define LIBAVCODEC_VERSION_MAJOR 58
+#define LIBAVCODEC_VERSION_MINOR 18
+#define LIBAVCODEC_VERSION_MICRO 100
+
+#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
+ LIBAVCODEC_VERSION_MINOR, \
+ LIBAVCODEC_VERSION_MICRO)
+#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \
+ LIBAVCODEC_VERSION_MINOR, \
+ LIBAVCODEC_VERSION_MICRO)
+#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT
+
+#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
+
+/**
+ * FF_API_* defines may be placed below to indicate public API that will be
+ * dropped at a future version bump. The defines themselves are not part of
+ * the public API and may change, break or disappear at any time.
+ *
+ * @note, when bumping the major version it is recommended to manually
+ * disable each FF_API_* in its own commit instead of disabling them all
+ * at once through the bump. This improves the git bisect-ability of the change.
+ */
+
+#ifndef FF_API_LOWRES
+#define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_DEBUG_MV
+#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58)
+#endif
+#ifndef FF_API_AVCTX_TIMEBASE
+#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_CODED_FRAME
+#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_SIDEDATA_ONLY_PKT
+#define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_VDPAU_PROFILE
+#define FF_API_VDPAU_PROFILE (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_CONVERGENCE_DURATION
+#define FF_API_CONVERGENCE_DURATION (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_AVPICTURE
+#define FF_API_AVPICTURE (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_AVPACKET_OLD_API
+#define FF_API_AVPACKET_OLD_API (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_RTP_CALLBACK
+#define FF_API_RTP_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_VBV_DELAY
+#define FF_API_VBV_DELAY (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_CODER_TYPE
+#define FF_API_CODER_TYPE (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_STAT_BITS
+#define FF_API_STAT_BITS (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_PRIVATE_OPT
+#define FF_API_PRIVATE_OPT (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_ASS_TIMING
+#define FF_API_ASS_TIMING (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_OLD_BSF
+#define FF_API_OLD_BSF (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_COPY_CONTEXT
+#define FF_API_COPY_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_GET_CONTEXT_DEFAULTS
+#define FF_API_GET_CONTEXT_DEFAULTS (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_NVENC_OLD_NAME
+#define FF_API_NVENC_OLD_NAME (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_STRUCT_VAAPI_CONTEXT
+#define FF_API_STRUCT_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_MERGE_SD_API
+#define FF_API_MERGE_SD_API (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_TAG_STRING
+#define FF_API_TAG_STRING (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_GETCHROMA
+#define FF_API_GETCHROMA (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_CODEC_GET_SET
+#define FF_API_CODEC_GET_SET (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_USER_VISIBLE_AVHWACCEL
+#define FF_API_USER_VISIBLE_AVHWACCEL (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_LOCKMGR
+#define FF_API_LOCKMGR (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_NEXT
+#define FF_API_NEXT (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+
+
+#endif /* AVCODEC_VERSION_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/attributes.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/attributes.h
new file mode 100644
index 000000000..ced108aa2
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/attributes.h
@@ -0,0 +1,167 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Macro definitions for various function/variable attributes
+ */
+
+#ifndef AVUTIL_ATTRIBUTES_H
+#define AVUTIL_ATTRIBUTES_H
+
+#ifdef __GNUC__
+# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
+# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y))
+#else
+# define AV_GCC_VERSION_AT_LEAST(x,y) 0
+# define AV_GCC_VERSION_AT_MOST(x,y) 0
+#endif
+
+#ifndef av_always_inline
+#if AV_GCC_VERSION_AT_LEAST(3,1)
+# define av_always_inline __attribute__((always_inline)) inline
+#elif defined(_MSC_VER)
+# define av_always_inline __forceinline
+#else
+# define av_always_inline inline
+#endif
+#endif
+
+#ifndef av_extern_inline
+#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__)
+# define av_extern_inline extern inline
+#else
+# define av_extern_inline inline
+#endif
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(3,4)
+# define av_warn_unused_result __attribute__((warn_unused_result))
+#else
+# define av_warn_unused_result
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(3,1)
+# define av_noinline __attribute__((noinline))
+#elif defined(_MSC_VER)
+# define av_noinline __declspec(noinline)
+#else
+# define av_noinline
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__)
+# define av_pure __attribute__((pure))
+#else
+# define av_pure
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__)
+# define av_const __attribute__((const))
+#else
+# define av_const
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__)
+# define av_cold __attribute__((cold))
+#else
+# define av_cold
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__)
+# define av_flatten __attribute__((flatten))
+#else
+# define av_flatten
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(3,1)
+# define attribute_deprecated __attribute__((deprecated))
+#elif defined(_MSC_VER)
+# define attribute_deprecated __declspec(deprecated)
+#else
+# define attribute_deprecated
+#endif
+
+/**
+ * Disable warnings about deprecated features
+ * This is useful for sections of code kept for backward compatibility and
+ * scheduled for removal.
+ */
+#ifndef AV_NOWARN_DEPRECATED
+#if AV_GCC_VERSION_AT_LEAST(4,6)
+# define AV_NOWARN_DEPRECATED(code) \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \
+ code \
+ _Pragma("GCC diagnostic pop")
+#elif defined(_MSC_VER)
+# define AV_NOWARN_DEPRECATED(code) \
+ __pragma(warning(push)) \
+ __pragma(warning(disable : 4996)) \
+ code; \
+ __pragma(warning(pop))
+#else
+# define AV_NOWARN_DEPRECATED(code) code
+#endif
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# define av_unused __attribute__((unused))
+#else
+# define av_unused
+#endif
+
+/**
+ * Mark a variable as used and prevent the compiler from optimizing it
+ * away. This is useful for variables accessed only from inline
+ * assembler without the compiler being aware.
+ */
+#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__)
+# define av_used __attribute__((used))
+#else
+# define av_used
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__)
+# define av_alias __attribute__((may_alias))
+#else
+# define av_alias
+#endif
+
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER)
+# define av_uninit(x) x=x
+#else
+# define av_uninit(x) x
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# define av_builtin_constant_p __builtin_constant_p
+# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos)))
+#else
+# define av_builtin_constant_p(x) 0
+# define av_printf_format(fmtpos, attrpos)
+#endif
+
+#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__)
+# define av_noreturn __attribute__((noreturn))
+#else
+# define av_noreturn
+#endif
+
+#endif /* AVUTIL_ATTRIBUTES_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/avconfig.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/avconfig.h
new file mode 100644
index 000000000..c289fbb55
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/avconfig.h
@@ -0,0 +1,6 @@
+/* Generated by ffmpeg configure */
+#ifndef AVUTIL_AVCONFIG_H
+#define AVUTIL_AVCONFIG_H
+#define AV_HAVE_BIGENDIAN 0
+#define AV_HAVE_FAST_UNALIGNED 1
+#endif /* AVUTIL_AVCONFIG_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/avutil.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/avutil.h
new file mode 100644
index 000000000..4d633156d
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/avutil.h
@@ -0,0 +1,365 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_AVUTIL_H
+#define AVUTIL_AVUTIL_H
+
+/**
+ * @file
+ * @ingroup lavu
+ * Convenience header that includes @ref lavu "libavutil"'s core.
+ */
+
+/**
+ * @mainpage
+ *
+ * @section ffmpeg_intro Introduction
+ *
+ * This document describes the usage of the different libraries
+ * provided by FFmpeg.
+ *
+ * @li @ref libavc "libavcodec" encoding/decoding library
+ * @li @ref lavfi "libavfilter" graph-based frame editing library
+ * @li @ref libavf "libavformat" I/O and muxing/demuxing library
+ * @li @ref lavd "libavdevice" special devices muxing/demuxing library
+ * @li @ref lavu "libavutil" common utility library
+ * @li @ref lswr "libswresample" audio resampling, format conversion and mixing
+ * @li @ref lpp "libpostproc" post processing library
+ * @li @ref libsws "libswscale" color conversion and scaling library
+ *
+ * @section ffmpeg_versioning Versioning and compatibility
+ *
+ * Each of the FFmpeg libraries contains a version.h header, which defines a
+ * major, minor and micro version number with the
+ * <em>LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO}</em> macros. The major version
+ * number is incremented with backward incompatible changes - e.g. removing
+ * parts of the public API, reordering public struct members, etc. The minor
+ * version number is incremented for backward compatible API changes or major
+ * new features - e.g. adding a new public function or a new decoder. The micro
+ * version number is incremented for smaller changes that a calling program
+ * might still want to check for - e.g. changing behavior in a previously
+ * unspecified situation.
+ *
+ * FFmpeg guarantees backward API and ABI compatibility for each library as long
+ * as its major version number is unchanged. This means that no public symbols
+ * will be removed or renamed. Types and names of the public struct members and
+ * values of public macros and enums will remain the same (unless they were
+ * explicitly declared as not part of the public API). Documented behavior will
+ * not change.
+ *
+ * In other words, any correct program that works with a given FFmpeg snapshot
+ * should work just as well without any changes with any later snapshot with the
+ * same major versions. This applies to both rebuilding the program against new
+ * FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program
+ * links against.
+ *
+ * However, new public symbols may be added and new members may be appended to
+ * public structs whose size is not part of public ABI (most public structs in
+ * FFmpeg). New macros and enum values may be added. Behavior in undocumented
+ * situations may change slightly (and be documented). All those are accompanied
+ * by an entry in doc/APIchanges and incrementing either the minor or micro
+ * version number.
+ */
+
+/**
+ * @defgroup lavu libavutil
+ * Common code shared across all FFmpeg libraries.
+ *
+ * @note
+ * libavutil is designed to be modular. In most cases, in order to use the
+ * functions provided by one component of libavutil you must explicitly include
+ * the specific header containing that feature. If you are only using
+ * media-related components, you could simply include libavutil/avutil.h, which
+ * brings in most of the "core" components.
+ *
+ * @{
+ *
+ * @defgroup lavu_crypto Crypto and Hashing
+ *
+ * @{
+ * @}
+ *
+ * @defgroup lavu_math Mathematics
+ * @{
+ *
+ * @}
+ *
+ * @defgroup lavu_string String Manipulation
+ *
+ * @{
+ *
+ * @}
+ *
+ * @defgroup lavu_mem Memory Management
+ *
+ * @{
+ *
+ * @}
+ *
+ * @defgroup lavu_data Data Structures
+ * @{
+ *
+ * @}
+ *
+ * @defgroup lavu_video Video related
+ *
+ * @{
+ *
+ * @}
+ *
+ * @defgroup lavu_audio Audio related
+ *
+ * @{
+ *
+ * @}
+ *
+ * @defgroup lavu_error Error Codes
+ *
+ * @{
+ *
+ * @}
+ *
+ * @defgroup lavu_log Logging Facility
+ *
+ * @{
+ *
+ * @}
+ *
+ * @defgroup lavu_misc Other
+ *
+ * @{
+ *
+ * @defgroup preproc_misc Preprocessor String Macros
+ *
+ * @{
+ *
+ * @}
+ *
+ * @defgroup version_utils Library Version Macros
+ *
+ * @{
+ *
+ * @}
+ */
+
+
+/**
+ * @addtogroup lavu_ver
+ * @{
+ */
+
+/**
+ * Return the LIBAVUTIL_VERSION_INT constant.
+ */
+unsigned avutil_version(void);
+
+/**
+ * Return an informative version string. This usually is the actual release
+ * version number or a git commit description. This string has no fixed format
+ * and can change any time. It should never be parsed by code.
+ */
+const char *av_version_info(void);
+
+/**
+ * Return the libavutil build-time configuration.
+ */
+const char *avutil_configuration(void);
+
+/**
+ * Return the libavutil license.
+ */
+const char *avutil_license(void);
+
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup lavu_media Media Type
+ * @brief Media Type
+ */
+
+enum AVMediaType {
+ AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA
+ AVMEDIA_TYPE_VIDEO,
+ AVMEDIA_TYPE_AUDIO,
+ AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous
+ AVMEDIA_TYPE_SUBTITLE,
+ AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse
+ AVMEDIA_TYPE_NB
+};
+
+/**
+ * Return a string describing the media_type enum, NULL if media_type
+ * is unknown.
+ */
+const char *av_get_media_type_string(enum AVMediaType media_type);
+
+/**
+ * @defgroup lavu_const Constants
+ * @{
+ *
+ * @defgroup lavu_enc Encoding specific
+ *
+ * @note those definition should move to avcodec
+ * @{
+ */
+
+#define FF_LAMBDA_SHIFT 7
+#define FF_LAMBDA_SCALE (1<<FF_LAMBDA_SHIFT)
+#define FF_QP2LAMBDA 118 ///< factor to convert from H.263 QP to lambda
+#define FF_LAMBDA_MAX (256*128-1)
+
+#define FF_QUALITY_SCALE FF_LAMBDA_SCALE //FIXME maybe remove
+
+/**
+ * @}
+ * @defgroup lavu_time Timestamp specific
+ *
+ * FFmpeg internal timebase and timestamp definitions
+ *
+ * @{
+ */
+
+/**
+ * @brief Undefined timestamp value
+ *
+ * Usually reported by demuxer that work on containers that do not provide
+ * either pts or dts.
+ */
+
+#define AV_NOPTS_VALUE ((int64_t)UINT64_C(0x8000000000000000))
+
+/**
+ * Internal time base represented as integer
+ */
+
+#define AV_TIME_BASE 1000000
+
+/**
+ * Internal time base represented as fractional value
+ */
+
+#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
+
+/**
+ * @}
+ * @}
+ * @defgroup lavu_picture Image related
+ *
+ * AVPicture types, pixel formats and basic image planes manipulation.
+ *
+ * @{
+ */
+
+enum AVPictureType {
+ AV_PICTURE_TYPE_NONE = 0, ///< Undefined
+ AV_PICTURE_TYPE_I, ///< Intra
+ AV_PICTURE_TYPE_P, ///< Predicted
+ AV_PICTURE_TYPE_B, ///< Bi-dir predicted
+ AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4
+ AV_PICTURE_TYPE_SI, ///< Switching Intra
+ AV_PICTURE_TYPE_SP, ///< Switching Predicted
+ AV_PICTURE_TYPE_BI, ///< BI type
+};
+
+/**
+ * Return a single letter to describe the given picture type
+ * pict_type.
+ *
+ * @param[in] pict_type the picture type @return a single character
+ * representing the picture type, '?' if pict_type is unknown
+ */
+char av_get_picture_type_char(enum AVPictureType pict_type);
+
+/**
+ * @}
+ */
+
+#include "common.h"
+#include "error.h"
+#include "rational.h"
+#include "version.h"
+#include "macros.h"
+#include "mathematics.h"
+#include "log.h"
+#include "pixfmt.h"
+
+/**
+ * Return x default pointer in case p is NULL.
+ */
+static inline void *av_x_if_null(const void *p, const void *x)
+{
+ return (void *)(intptr_t)(p ? p : x);
+}
+
+/**
+ * Compute the length of an integer list.
+ *
+ * @param elsize size in bytes of each list element (only 1, 2, 4 or 8)
+ * @param term list terminator (usually 0 or -1)
+ * @param list pointer to the list
+ * @return length of the list, in elements, not counting the terminator
+ */
+unsigned av_int_list_length_for_size(unsigned elsize,
+ const void *list, uint64_t term) av_pure;
+
+/**
+ * Compute the length of an integer list.
+ *
+ * @param term list terminator (usually 0 or -1)
+ * @param list pointer to the list
+ * @return length of the list, in elements, not counting the terminator
+ */
+#define av_int_list_length(list, term) \
+ av_int_list_length_for_size(sizeof(*(list)), list, term)
+
+/**
+ * Open a file using a UTF-8 filename.
+ * The API of this function matches POSIX fopen(), errors are returned through
+ * errno.
+ */
+FILE *av_fopen_utf8(const char *path, const char *mode);
+
+/**
+ * Return the fractional representation of the internal time base.
+ */
+AVRational av_get_time_base_q(void);
+
+#define AV_FOURCC_MAX_STRING_SIZE 32
+
+#define av_fourcc2str(fourcc) av_fourcc_make_string((char[AV_FOURCC_MAX_STRING_SIZE]){0}, fourcc)
+
+/**
+ * Fill the provided buffer with a string containing a FourCC (four-character
+ * code) representation.
+ *
+ * @param buf a buffer with size in bytes of at least AV_FOURCC_MAX_STRING_SIZE
+ * @param fourcc the fourcc to represent
+ * @return the buffer in input
+ */
+char *av_fourcc_make_string(char *buf, uint32_t fourcc);
+
+/**
+ * @}
+ * @}
+ */
+
+#endif /* AVUTIL_AVUTIL_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/buffer.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/buffer.h
new file mode 100644
index 000000000..73b6bd0b1
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/buffer.h
@@ -0,0 +1,291 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @ingroup lavu_buffer
+ * refcounted data buffer API
+ */
+
+#ifndef AVUTIL_BUFFER_H
+#define AVUTIL_BUFFER_H
+
+#include <stdint.h>
+
+/**
+ * @defgroup lavu_buffer AVBuffer
+ * @ingroup lavu_data
+ *
+ * @{
+ * AVBuffer is an API for reference-counted data buffers.
+ *
+ * There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer
+ * represents the data buffer itself; it is opaque and not meant to be accessed
+ * by the caller directly, but only through AVBufferRef. However, the caller may
+ * e.g. compare two AVBuffer pointers to check whether two different references
+ * are describing the same data buffer. AVBufferRef represents a single
+ * reference to an AVBuffer and it is the object that may be manipulated by the
+ * caller directly.
+ *
+ * There are two functions provided for creating a new AVBuffer with a single
+ * reference -- av_buffer_alloc() to just allocate a new buffer, and
+ * av_buffer_create() to wrap an existing array in an AVBuffer. From an existing
+ * reference, additional references may be created with av_buffer_ref().
+ * Use av_buffer_unref() to free a reference (this will automatically free the
+ * data once all the references are freed).
+ *
+ * The convention throughout this API and the rest of FFmpeg is such that the
+ * buffer is considered writable if there exists only one reference to it (and
+ * it has not been marked as read-only). The av_buffer_is_writable() function is
+ * provided to check whether this is true and av_buffer_make_writable() will
+ * automatically create a new writable buffer when necessary.
+ * Of course nothing prevents the calling code from violating this convention,
+ * however that is safe only when all the existing references are under its
+ * control.
+ *
+ * @note Referencing and unreferencing the buffers is thread-safe and thus
+ * may be done from multiple threads simultaneously without any need for
+ * additional locking.
+ *
+ * @note Two different references to the same buffer can point to different
+ * parts of the buffer (i.e. their AVBufferRef.data will not be equal).
+ */
+
+/**
+ * A reference counted buffer type. It is opaque and is meant to be used through
+ * references (AVBufferRef).
+ */
+typedef struct AVBuffer AVBuffer;
+
+/**
+ * A reference to a data buffer.
+ *
+ * The size of this struct is not a part of the public ABI and it is not meant
+ * to be allocated directly.
+ */
+typedef struct AVBufferRef {
+ AVBuffer *buffer;
+
+ /**
+ * The data buffer. It is considered writable if and only if
+ * this is the only reference to the buffer, in which case
+ * av_buffer_is_writable() returns 1.
+ */
+ uint8_t *data;
+ /**
+ * Size of data in bytes.
+ */
+ int size;
+} AVBufferRef;
+
+/**
+ * Allocate an AVBuffer of the given size using av_malloc().
+ *
+ * @return an AVBufferRef of given size or NULL when out of memory
+ */
+AVBufferRef *av_buffer_alloc(int size);
+
+/**
+ * Same as av_buffer_alloc(), except the returned buffer will be initialized
+ * to zero.
+ */
+AVBufferRef *av_buffer_allocz(int size);
+
+/**
+ * Always treat the buffer as read-only, even when it has only one
+ * reference.
+ */
+#define AV_BUFFER_FLAG_READONLY (1 << 0)
+
+/**
+ * Create an AVBuffer from an existing array.
+ *
+ * If this function is successful, data is owned by the AVBuffer. The caller may
+ * only access data through the returned AVBufferRef and references derived from
+ * it.
+ * If this function fails, data is left untouched.
+ * @param data data array
+ * @param size size of data in bytes
+ * @param free a callback for freeing this buffer's data
+ * @param opaque parameter to be got for processing or passed to free
+ * @param flags a combination of AV_BUFFER_FLAG_*
+ *
+ * @return an AVBufferRef referring to data on success, NULL on failure.
+ */
+AVBufferRef *av_buffer_create(uint8_t *data, int size,
+ void (*free)(void *opaque, uint8_t *data),
+ void *opaque, int flags);
+
+/**
+ * Default free callback, which calls av_free() on the buffer data.
+ * This function is meant to be passed to av_buffer_create(), not called
+ * directly.
+ */
+void av_buffer_default_free(void *opaque, uint8_t *data);
+
+/**
+ * Create a new reference to an AVBuffer.
+ *
+ * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on
+ * failure.
+ */
+AVBufferRef *av_buffer_ref(AVBufferRef *buf);
+
+/**
+ * Free a given reference and automatically free the buffer if there are no more
+ * references to it.
+ *
+ * @param buf the reference to be freed. The pointer is set to NULL on return.
+ */
+void av_buffer_unref(AVBufferRef **buf);
+
+/**
+ * @return 1 if the caller may write to the data referred to by buf (which is
+ * true if and only if buf is the only reference to the underlying AVBuffer).
+ * Return 0 otherwise.
+ * A positive answer is valid until av_buffer_ref() is called on buf.
+ */
+int av_buffer_is_writable(const AVBufferRef *buf);
+
+/**
+ * @return the opaque parameter set by av_buffer_create.
+ */
+void *av_buffer_get_opaque(const AVBufferRef *buf);
+
+int av_buffer_get_ref_count(const AVBufferRef *buf);
+
+/**
+ * Create a writable reference from a given buffer reference, avoiding data copy
+ * if possible.
+ *
+ * @param buf buffer reference to make writable. On success, buf is either left
+ * untouched, or it is unreferenced and a new writable AVBufferRef is
+ * written in its place. On failure, buf is left untouched.
+ * @return 0 on success, a negative AVERROR on failure.
+ */
+int av_buffer_make_writable(AVBufferRef **buf);
+
+/**
+ * Reallocate a given buffer.
+ *
+ * @param buf a buffer reference to reallocate. On success, buf will be
+ * unreferenced and a new reference with the required size will be
+ * written in its place. On failure buf will be left untouched. *buf
+ * may be NULL, then a new buffer is allocated.
+ * @param size required new buffer size.
+ * @return 0 on success, a negative AVERROR on failure.
+ *
+ * @note the buffer is actually reallocated with av_realloc() only if it was
+ * initially allocated through av_buffer_realloc(NULL) and there is only one
+ * reference to it (i.e. the one passed to this function). In all other cases
+ * a new buffer is allocated and the data is copied.
+ */
+int av_buffer_realloc(AVBufferRef **buf, int size);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup lavu_bufferpool AVBufferPool
+ * @ingroup lavu_data
+ *
+ * @{
+ * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers.
+ *
+ * Frequently allocating and freeing large buffers may be slow. AVBufferPool is
+ * meant to solve this in cases when the caller needs a set of buffers of the
+ * same size (the most obvious use case being buffers for raw video or audio
+ * frames).
+ *
+ * At the beginning, the user must call av_buffer_pool_init() to create the
+ * buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to
+ * get a reference to a new buffer, similar to av_buffer_alloc(). This new
+ * reference works in all aspects the same way as the one created by
+ * av_buffer_alloc(). However, when the last reference to this buffer is
+ * unreferenced, it is returned to the pool instead of being freed and will be
+ * reused for subsequent av_buffer_pool_get() calls.
+ *
+ * When the caller is done with the pool and no longer needs to allocate any new
+ * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable.
+ * Once all the buffers are released, it will automatically be freed.
+ *
+ * Allocating and releasing buffers with this API is thread-safe as long as
+ * either the default alloc callback is used, or the user-supplied one is
+ * thread-safe.
+ */
+
+/**
+ * The buffer pool. This structure is opaque and not meant to be accessed
+ * directly. It is allocated with av_buffer_pool_init() and freed with
+ * av_buffer_pool_uninit().
+ */
+typedef struct AVBufferPool AVBufferPool;
+
+/**
+ * Allocate and initialize a buffer pool.
+ *
+ * @param size size of each buffer in this pool
+ * @param alloc a function that will be used to allocate new buffers when the
+ * pool is empty. May be NULL, then the default allocator will be used
+ * (av_buffer_alloc()).
+ * @return newly created buffer pool on success, NULL on error.
+ */
+AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size));
+
+/**
+ * Allocate and initialize a buffer pool with a more complex allocator.
+ *
+ * @param size size of each buffer in this pool
+ * @param opaque arbitrary user data used by the allocator
+ * @param alloc a function that will be used to allocate new buffers when the
+ * pool is empty.
+ * @param pool_free a function that will be called immediately before the pool
+ * is freed. I.e. after av_buffer_pool_uninit() is called
+ * by the caller and all the frames are returned to the pool
+ * and freed. It is intended to uninitialize the user opaque
+ * data.
+ * @return newly created buffer pool on success, NULL on error.
+ */
+AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
+ AVBufferRef* (*alloc)(void *opaque, int size),
+ void (*pool_free)(void *opaque));
+
+/**
+ * Mark the pool as being available for freeing. It will actually be freed only
+ * once all the allocated buffers associated with the pool are released. Thus it
+ * is safe to call this function while some of the allocated buffers are still
+ * in use.
+ *
+ * @param pool pointer to the pool to be freed. It will be set to NULL.
+ */
+void av_buffer_pool_uninit(AVBufferPool **pool);
+
+/**
+ * Allocate a new AVBuffer, reusing an old buffer from the pool when available.
+ * This function may be called simultaneously from multiple threads.
+ *
+ * @return a reference to the new buffer on success, NULL on error.
+ */
+AVBufferRef *av_buffer_pool_get(AVBufferPool *pool);
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_BUFFER_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/channel_layout.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/channel_layout.h
new file mode 100644
index 000000000..50bb8f03c
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/channel_layout.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ * Copyright (c) 2008 Peter Ross
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_CHANNEL_LAYOUT_H
+#define AVUTIL_CHANNEL_LAYOUT_H
+
+#include <stdint.h>
+
+/**
+ * @file
+ * audio channel layout utility functions
+ */
+
+/**
+ * @addtogroup lavu_audio
+ * @{
+ */
+
+/**
+ * @defgroup channel_masks Audio channel masks
+ *
+ * A channel layout is a 64-bits integer with a bit set for every channel.
+ * The number of bits set must be equal to the number of channels.
+ * The value 0 means that the channel layout is not known.
+ * @note this data structure is not powerful enough to handle channels
+ * combinations that have the same channel multiple times, such as
+ * dual-mono.
+ *
+ * @{
+ */
+#define AV_CH_FRONT_LEFT 0x00000001
+#define AV_CH_FRONT_RIGHT 0x00000002
+#define AV_CH_FRONT_CENTER 0x00000004
+#define AV_CH_LOW_FREQUENCY 0x00000008
+#define AV_CH_BACK_LEFT 0x00000010
+#define AV_CH_BACK_RIGHT 0x00000020
+#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040
+#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080
+#define AV_CH_BACK_CENTER 0x00000100
+#define AV_CH_SIDE_LEFT 0x00000200
+#define AV_CH_SIDE_RIGHT 0x00000400
+#define AV_CH_TOP_CENTER 0x00000800
+#define AV_CH_TOP_FRONT_LEFT 0x00001000
+#define AV_CH_TOP_FRONT_CENTER 0x00002000
+#define AV_CH_TOP_FRONT_RIGHT 0x00004000
+#define AV_CH_TOP_BACK_LEFT 0x00008000
+#define AV_CH_TOP_BACK_CENTER 0x00010000
+#define AV_CH_TOP_BACK_RIGHT 0x00020000
+#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix.
+#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT.
+#define AV_CH_WIDE_LEFT 0x0000000080000000ULL
+#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL
+#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL
+#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL
+#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL
+
+/** Channel mask value used for AVCodecContext.request_channel_layout
+ to indicate that the user requests the channel order of the decoder output
+ to be the native codec channel order. */
+#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL
+
+/**
+ * @}
+ * @defgroup channel_mask_c Audio channel layouts
+ * @{
+ * */
+#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER)
+#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
+#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY)
+#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)
+#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)
+#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY)
+#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER)
+#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY)
+#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)
+#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)
+#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY)
+#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY)
+#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER)
+#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
+#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER)
+#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER)
+#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER)
+#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY)
+#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
+#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
+#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
+#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT)
+#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT)
+
+enum AVMatrixEncoding {
+ AV_MATRIX_ENCODING_NONE,
+ AV_MATRIX_ENCODING_DOLBY,
+ AV_MATRIX_ENCODING_DPLII,
+ AV_MATRIX_ENCODING_DPLIIX,
+ AV_MATRIX_ENCODING_DPLIIZ,
+ AV_MATRIX_ENCODING_DOLBYEX,
+ AV_MATRIX_ENCODING_DOLBYHEADPHONE,
+ AV_MATRIX_ENCODING_NB
+};
+
+/**
+ * Return a channel layout id that matches name, or 0 if no match is found.
+ *
+ * name can be one or several of the following notations,
+ * separated by '+' or '|':
+ * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0,
+ * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix);
+ * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC,
+ * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR);
+ * - a number of channels, in decimal, followed by 'c', yielding
+ * the default channel layout for that number of channels (@see
+ * av_get_default_channel_layout);
+ * - a channel layout mask, in hexadecimal starting with "0x" (see the
+ * AV_CH_* macros).
+ *
+ * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7"
+ */
+uint64_t av_get_channel_layout(const char *name);
+
+/**
+ * Return a channel layout and the number of channels based on the specified name.
+ *
+ * This function is similar to (@see av_get_channel_layout), but can also parse
+ * unknown channel layout specifications.
+ *
+ * @param[in] name channel layout specification string
+ * @param[out] channel_layout parsed channel layout (0 if unknown)
+ * @param[out] nb_channels number of channels
+ *
+ * @return 0 on success, AVERROR(EINVAL) if the parsing fails.
+ */
+int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels);
+
+/**
+ * Return a description of a channel layout.
+ * If nb_channels is <= 0, it is guessed from the channel_layout.
+ *
+ * @param buf put here the string containing the channel layout
+ * @param buf_size size in bytes of the buffer
+ */
+void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout);
+
+struct AVBPrint;
+/**
+ * Append a description of a channel layout to a bprint buffer.
+ */
+void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout);
+
+/**
+ * Return the number of channels in the channel layout.
+ */
+int av_get_channel_layout_nb_channels(uint64_t channel_layout);
+
+/**
+ * Return default channel layout for a given number of channels.
+ */
+int64_t av_get_default_channel_layout(int nb_channels);
+
+/**
+ * Get the index of a channel in channel_layout.
+ *
+ * @param channel a channel layout describing exactly one channel which must be
+ * present in channel_layout.
+ *
+ * @return index of channel in channel_layout on success, a negative AVERROR
+ * on error.
+ */
+int av_get_channel_layout_channel_index(uint64_t channel_layout,
+ uint64_t channel);
+
+/**
+ * Get the channel with the given index in channel_layout.
+ */
+uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index);
+
+/**
+ * Get the name of a given channel.
+ *
+ * @return channel name on success, NULL on error.
+ */
+const char *av_get_channel_name(uint64_t channel);
+
+/**
+ * Get the description of a given channel.
+ *
+ * @param channel a channel layout with a single channel
+ * @return channel description on success, NULL on error
+ */
+const char *av_get_channel_description(uint64_t channel);
+
+/**
+ * Get the value and name of a standard channel layout.
+ *
+ * @param[in] index index in an internal list, starting at 0
+ * @param[out] layout channel layout mask
+ * @param[out] name name of the layout
+ * @return 0 if the layout exists,
+ * <0 if index is beyond the limits
+ */
+int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
+ const char **name);
+
+/**
+ * @}
+ * @}
+ */
+
+#endif /* AVUTIL_CHANNEL_LAYOUT_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/common.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/common.h
new file mode 100644
index 000000000..0fffa6771
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/common.h
@@ -0,0 +1,560 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * common internal and external API header
+ */
+
+#ifndef AVUTIL_COMMON_H
+#define AVUTIL_COMMON_H
+
+#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C)
+#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS
+#endif
+
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "attributes.h"
+#include "macros.h"
+#include "version.h"
+#include "libavutil/avconfig.h"
+
+#if AV_HAVE_BIGENDIAN
+# define AV_NE(be, le) (be)
+#else
+# define AV_NE(be, le) (le)
+#endif
+
+//rounded division & shift
+#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
+/* assume b>0 */
+#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
+/* Fast a/(1<<b) rounded toward +inf. Assume a>=0 and b>=0 */
+#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \
+ : ((a) + (1<<(b)) - 1) >> (b))
+/* Backwards compat. */
+#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT
+
+#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b))
+#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b))
+
+/**
+ * Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they
+ * are not representable as absolute values of their type. This is the same
+ * as with *abs()
+ * @see FFNABS()
+ */
+#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
+#define FFSIGN(a) ((a) > 0 ? 1 : -1)
+
+/**
+ * Negative Absolute value.
+ * this works for all integers of all types.
+ * As with many macros, this evaluates its argument twice, it thus must not have
+ * a sideeffect, that is FFNABS(x++) has undefined behavior.
+ */
+#define FFNABS(a) ((a) <= 0 ? (a) : (-(a)))
+
+/**
+ * Comparator.
+ * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0
+ * if x == y. This is useful for instance in a qsort comparator callback.
+ * Furthermore, compilers are able to optimize this to branchless code, and
+ * there is no risk of overflow with signed types.
+ * As with many macros, this evaluates its argument multiple times, it thus
+ * must not have a side-effect.
+ */
+#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y)))
+
+#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
+#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
+#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
+#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)
+
+#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
+#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
+
+/* misc math functions */
+
+#ifdef HAVE_AV_CONFIG_H
+# include "config.h"
+# include "intmath.h"
+#endif
+
+/* Pull in unguarded fallback defines at the end of this file. */
+#include "common.h"
+
+#ifndef av_log2
+av_const int av_log2(unsigned v);
+#endif
+
+#ifndef av_log2_16bit
+av_const int av_log2_16bit(unsigned v);
+#endif
+
+/**
+ * Clip a signed integer value into the amin-amax range.
+ * @param a value to clip
+ * @param amin minimum value of the clip range
+ * @param amax maximum value of the clip range
+ * @return clipped value
+ */
+static av_always_inline av_const int av_clip_c(int a, int amin, int amax)
+{
+#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
+ if (amin > amax) abort();
+#endif
+ if (a < amin) return amin;
+ else if (a > amax) return amax;
+ else return a;
+}
+
+/**
+ * Clip a signed 64bit integer value into the amin-amax range.
+ * @param a value to clip
+ * @param amin minimum value of the clip range
+ * @param amax maximum value of the clip range
+ * @return clipped value
+ */
+static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax)
+{
+#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
+ if (amin > amax) abort();
+#endif
+ if (a < amin) return amin;
+ else if (a > amax) return amax;
+ else return a;
+}
+
+/**
+ * Clip a signed integer value into the 0-255 range.
+ * @param a value to clip
+ * @return clipped value
+ */
+static av_always_inline av_const uint8_t av_clip_uint8_c(int a)
+{
+ if (a&(~0xFF)) return (~a)>>31;
+ else return a;
+}
+
+/**
+ * Clip a signed integer value into the -128,127 range.
+ * @param a value to clip
+ * @return clipped value
+ */
+static av_always_inline av_const int8_t av_clip_int8_c(int a)
+{
+ if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F;
+ else return a;
+}
+
+/**
+ * Clip a signed integer value into the 0-65535 range.
+ * @param a value to clip
+ * @return clipped value
+ */
+static av_always_inline av_const uint16_t av_clip_uint16_c(int a)
+{
+ if (a&(~0xFFFF)) return (~a)>>31;
+ else return a;
+}
+
+/**
+ * Clip a signed integer value into the -32768,32767 range.
+ * @param a value to clip
+ * @return clipped value
+ */
+static av_always_inline av_const int16_t av_clip_int16_c(int a)
+{
+ if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF;
+ else return a;
+}
+
+/**
+ * Clip a signed 64-bit integer value into the -2147483648,2147483647 range.
+ * @param a value to clip
+ * @return clipped value
+ */
+static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a)
+{
+ if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF);
+ else return (int32_t)a;
+}
+
+/**
+ * Clip a signed integer into the -(2^p),(2^p-1) range.
+ * @param a value to clip
+ * @param p bit position to clip at
+ * @return clipped value
+ */
+static av_always_inline av_const int av_clip_intp2_c(int a, int p)
+{
+ if (((unsigned)a + (1 << p)) & ~((2 << p) - 1))
+ return (a >> 31) ^ ((1 << p) - 1);
+ else
+ return a;
+}
+
+/**
+ * Clip a signed integer to an unsigned power of two range.
+ * @param a value to clip
+ * @param p bit position to clip at
+ * @return clipped value
+ */
+static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p)
+{
+ if (a & ~((1<<p) - 1)) return -a >> 31 & ((1<<p) - 1);
+ else return a;
+}
+
+/**
+ * Clear high bits from an unsigned integer starting with specific bit position
+ * @param a value to clip
+ * @param p bit position to clip at
+ * @return clipped value
+ */
+static av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p)
+{
+ return a & ((1 << p) - 1);
+}
+
+/**
+ * Add two signed 32-bit values with saturation.
+ *
+ * @param a one value
+ * @param b another value
+ * @return sum with signed saturation
+ */
+static av_always_inline int av_sat_add32_c(int a, int b)
+{
+ return av_clipl_int32((int64_t)a + b);
+}
+
+/**
+ * Add a doubled value to another value with saturation at both stages.
+ *
+ * @param a first value
+ * @param b value doubled and added to a
+ * @return sum sat(a + sat(2*b)) with signed saturation
+ */
+static av_always_inline int av_sat_dadd32_c(int a, int b)
+{
+ return av_sat_add32(a, av_sat_add32(b, b));
+}
+
+/**
+ * Subtract two signed 32-bit values with saturation.
+ *
+ * @param a one value
+ * @param b another value
+ * @return difference with signed saturation
+ */
+static av_always_inline int av_sat_sub32_c(int a, int b)
+{
+ return av_clipl_int32((int64_t)a - b);
+}
+
+/**
+ * Subtract a doubled value from another value with saturation at both stages.
+ *
+ * @param a first value
+ * @param b value doubled and subtracted from a
+ * @return difference sat(a - sat(2*b)) with signed saturation
+ */
+static av_always_inline int av_sat_dsub32_c(int a, int b)
+{
+ return av_sat_sub32(a, av_sat_add32(b, b));
+}
+
+/**
+ * Clip a float value into the amin-amax range.
+ * @param a value to clip
+ * @param amin minimum value of the clip range
+ * @param amax maximum value of the clip range
+ * @return clipped value
+ */
+static av_always_inline av_const float av_clipf_c(float a, float amin, float amax)
+{
+#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
+ if (amin > amax) abort();
+#endif
+ if (a < amin) return amin;
+ else if (a > amax) return amax;
+ else return a;
+}
+
+/**
+ * Clip a double value into the amin-amax range.
+ * @param a value to clip
+ * @param amin minimum value of the clip range
+ * @param amax maximum value of the clip range
+ * @return clipped value
+ */
+static av_always_inline av_const double av_clipd_c(double a, double amin, double amax)
+{
+#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
+ if (amin > amax) abort();
+#endif
+ if (a < amin) return amin;
+ else if (a > amax) return amax;
+ else return a;
+}
+
+/** Compute ceil(log2(x)).
+ * @param x value used to compute ceil(log2(x))
+ * @return computed ceiling of log2(x)
+ */
+static av_always_inline av_const int av_ceil_log2_c(int x)
+{
+ return av_log2((x - 1) << 1);
+}
+
+/**
+ * Count number of bits set to one in x
+ * @param x value to count bits of
+ * @return the number of bits set to one in x
+ */
+static av_always_inline av_const int av_popcount_c(uint32_t x)
+{
+ x -= (x >> 1) & 0x55555555;
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ x = (x + (x >> 4)) & 0x0F0F0F0F;
+ x += x >> 8;
+ return (x + (x >> 16)) & 0x3F;
+}
+
+/**
+ * Count number of bits set to one in x
+ * @param x value to count bits of
+ * @return the number of bits set to one in x
+ */
+static av_always_inline av_const int av_popcount64_c(uint64_t x)
+{
+ return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32));
+}
+
+static av_always_inline av_const int av_parity_c(uint32_t v)
+{
+ return av_popcount(v) & 1;
+}
+
+#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
+#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24))
+
+/**
+ * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form.
+ *
+ * @param val Output value, must be an lvalue of type uint32_t.
+ * @param GET_BYTE Expression reading one byte from the input.
+ * Evaluated up to 7 times (4 for the currently
+ * assigned Unicode range). With a memory buffer
+ * input, this could be *ptr++.
+ * @param ERROR Expression to be evaluated on invalid input,
+ * typically a goto statement.
+ *
+ * @warning ERROR should not contain a loop control statement which
+ * could interact with the internal while loop, and should force an
+ * exit from the macro code (e.g. through a goto or a return) in order
+ * to prevent undefined results.
+ */
+#define GET_UTF8(val, GET_BYTE, ERROR)\
+ val= (GET_BYTE);\
+ {\
+ uint32_t top = (val & 128) >> 1;\
+ if ((val & 0xc0) == 0x80 || val >= 0xFE)\
+ ERROR\
+ while (val & top) {\
+ int tmp= (GET_BYTE) - 128;\
+ if(tmp>>6)\
+ ERROR\
+ val= (val<<6) + tmp;\
+ top <<= 5;\
+ }\
+ val &= (top << 1) - 1;\
+ }
+
+/**
+ * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form.
+ *
+ * @param val Output value, must be an lvalue of type uint32_t.
+ * @param GET_16BIT Expression returning two bytes of UTF-16 data converted
+ * to native byte order. Evaluated one or two times.
+ * @param ERROR Expression to be evaluated on invalid input,
+ * typically a goto statement.
+ */
+#define GET_UTF16(val, GET_16BIT, ERROR)\
+ val = GET_16BIT;\
+ {\
+ unsigned int hi = val - 0xD800;\
+ if (hi < 0x800) {\
+ val = GET_16BIT - 0xDC00;\
+ if (val > 0x3FFU || hi > 0x3FFU)\
+ ERROR\
+ val += (hi<<10) + 0x10000;\
+ }\
+ }\
+
+/**
+ * @def PUT_UTF8(val, tmp, PUT_BYTE)
+ * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long).
+ * @param val is an input-only argument and should be of type uint32_t. It holds
+ * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If
+ * val is given as a function it is executed only once.
+ * @param tmp is a temporary variable and should be of type uint8_t. It
+ * represents an intermediate value during conversion that is to be
+ * output by PUT_BYTE.
+ * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination.
+ * It could be a function or a statement, and uses tmp as the input byte.
+ * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be
+ * executed up to 4 times for values in the valid UTF-8 range and up to
+ * 7 times in the general case, depending on the length of the converted
+ * Unicode character.
+ */
+#define PUT_UTF8(val, tmp, PUT_BYTE)\
+ {\
+ int bytes, shift;\
+ uint32_t in = val;\
+ if (in < 0x80) {\
+ tmp = in;\
+ PUT_BYTE\
+ } else {\
+ bytes = (av_log2(in) + 4) / 5;\
+ shift = (bytes - 1) * 6;\
+ tmp = (256 - (256 >> bytes)) | (in >> shift);\
+ PUT_BYTE\
+ while (shift >= 6) {\
+ shift -= 6;\
+ tmp = 0x80 | ((in >> shift) & 0x3f);\
+ PUT_BYTE\
+ }\
+ }\
+ }
+
+/**
+ * @def PUT_UTF16(val, tmp, PUT_16BIT)
+ * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes).
+ * @param val is an input-only argument and should be of type uint32_t. It holds
+ * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If
+ * val is given as a function it is executed only once.
+ * @param tmp is a temporary variable and should be of type uint16_t. It
+ * represents an intermediate value during conversion that is to be
+ * output by PUT_16BIT.
+ * @param PUT_16BIT writes the converted UTF-16 data to any proper destination
+ * in desired endianness. It could be a function or a statement, and uses tmp
+ * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;"
+ * PUT_BYTE will be executed 1 or 2 times depending on input character.
+ */
+#define PUT_UTF16(val, tmp, PUT_16BIT)\
+ {\
+ uint32_t in = val;\
+ if (in < 0x10000) {\
+ tmp = in;\
+ PUT_16BIT\
+ } else {\
+ tmp = 0xD800 | ((in - 0x10000) >> 10);\
+ PUT_16BIT\
+ tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\
+ PUT_16BIT\
+ }\
+ }\
+
+
+
+#include "mem.h"
+
+#ifdef HAVE_AV_CONFIG_H
+# include "internal.h"
+#endif /* HAVE_AV_CONFIG_H */
+
+#endif /* AVUTIL_COMMON_H */
+
+/*
+ * The following definitions are outside the multiple inclusion guard
+ * to ensure they are immediately available in intmath.h.
+ */
+
+#ifndef av_ceil_log2
+# define av_ceil_log2 av_ceil_log2_c
+#endif
+#ifndef av_clip
+# define av_clip av_clip_c
+#endif
+#ifndef av_clip64
+# define av_clip64 av_clip64_c
+#endif
+#ifndef av_clip_uint8
+# define av_clip_uint8 av_clip_uint8_c
+#endif
+#ifndef av_clip_int8
+# define av_clip_int8 av_clip_int8_c
+#endif
+#ifndef av_clip_uint16
+# define av_clip_uint16 av_clip_uint16_c
+#endif
+#ifndef av_clip_int16
+# define av_clip_int16 av_clip_int16_c
+#endif
+#ifndef av_clipl_int32
+# define av_clipl_int32 av_clipl_int32_c
+#endif
+#ifndef av_clip_intp2
+# define av_clip_intp2 av_clip_intp2_c
+#endif
+#ifndef av_clip_uintp2
+# define av_clip_uintp2 av_clip_uintp2_c
+#endif
+#ifndef av_mod_uintp2
+# define av_mod_uintp2 av_mod_uintp2_c
+#endif
+#ifndef av_sat_add32
+# define av_sat_add32 av_sat_add32_c
+#endif
+#ifndef av_sat_dadd32
+# define av_sat_dadd32 av_sat_dadd32_c
+#endif
+#ifndef av_sat_sub32
+# define av_sat_sub32 av_sat_sub32_c
+#endif
+#ifndef av_sat_dsub32
+# define av_sat_dsub32 av_sat_dsub32_c
+#endif
+#ifndef av_clipf
+# define av_clipf av_clipf_c
+#endif
+#ifndef av_clipd
+# define av_clipd av_clipd_c
+#endif
+#ifndef av_popcount
+# define av_popcount av_popcount_c
+#endif
+#ifndef av_popcount64
+# define av_popcount64 av_popcount64_c
+#endif
+#ifndef av_parity
+# define av_parity av_parity_c
+#endif
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/cpu.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/cpu.h
new file mode 100644
index 000000000..8bb9eb606
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/cpu.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_CPU_H
+#define AVUTIL_CPU_H
+
+#include <stddef.h>
+
+#include "attributes.h"
+
+#define AV_CPU_FLAG_FORCE 0x80000000 /* force usage of selected flags (OR) */
+
+ /* lower 16 bits - CPU features */
+#define AV_CPU_FLAG_MMX 0x0001 ///< standard MMX
+#define AV_CPU_FLAG_MMXEXT 0x0002 ///< SSE integer functions or AMD MMX ext
+#define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext
+#define AV_CPU_FLAG_3DNOW 0x0004 ///< AMD 3DNOW
+#define AV_CPU_FLAG_SSE 0x0008 ///< SSE functions
+#define AV_CPU_FLAG_SSE2 0x0010 ///< PIV SSE2 functions
+#define AV_CPU_FLAG_SSE2SLOW 0x40000000 ///< SSE2 supported, but usually not faster
+ ///< than regular MMX/SSE (e.g. Core1)
+#define AV_CPU_FLAG_3DNOWEXT 0x0020 ///< AMD 3DNowExt
+#define AV_CPU_FLAG_SSE3 0x0040 ///< Prescott SSE3 functions
+#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster
+ ///< than regular MMX/SSE (e.g. Core1)
+#define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions
+#define AV_CPU_FLAG_SSSE3SLOW 0x4000000 ///< SSSE3 supported, but usually not faster
+#define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower
+#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions
+#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions
+#define AV_CPU_FLAG_AESNI 0x80000 ///< Advanced Encryption Standard functions
+#define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used
+#define AV_CPU_FLAG_AVXSLOW 0x8000000 ///< AVX supported, but slow when using YMM registers (e.g. Bulldozer)
+#define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions
+#define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions
+#define AV_CPU_FLAG_CMOV 0x1000 ///< supports cmov instruction
+#define AV_CPU_FLAG_AVX2 0x8000 ///< AVX2 functions: requires OS support even if YMM registers aren't used
+#define AV_CPU_FLAG_FMA3 0x10000 ///< Haswell FMA3 functions
+#define AV_CPU_FLAG_BMI1 0x20000 ///< Bit Manipulation Instruction Set 1
+#define AV_CPU_FLAG_BMI2 0x40000 ///< Bit Manipulation Instruction Set 2
+#define AV_CPU_FLAG_AVX512 0x100000 ///< AVX-512 functions: requires OS support even if YMM/ZMM registers aren't used
+
+#define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard
+#define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06
+#define AV_CPU_FLAG_POWER8 0x0004 ///< ISA 2.07
+
+#define AV_CPU_FLAG_ARMV5TE (1 << 0)
+#define AV_CPU_FLAG_ARMV6 (1 << 1)
+#define AV_CPU_FLAG_ARMV6T2 (1 << 2)
+#define AV_CPU_FLAG_VFP (1 << 3)
+#define AV_CPU_FLAG_VFPV3 (1 << 4)
+#define AV_CPU_FLAG_NEON (1 << 5)
+#define AV_CPU_FLAG_ARMV8 (1 << 6)
+#define AV_CPU_FLAG_VFP_VM (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations
+#define AV_CPU_FLAG_SETEND (1 <<16)
+
+/**
+ * Return the flags which specify extensions supported by the CPU.
+ * The returned value is affected by av_force_cpu_flags() if that was used
+ * before. So av_get_cpu_flags() can easily be used in an application to
+ * detect the enabled cpu flags.
+ */
+int av_get_cpu_flags(void);
+
+/**
+ * Disables cpu detection and forces the specified flags.
+ * -1 is a special case that disables forcing of specific flags.
+ */
+void av_force_cpu_flags(int flags);
+
+/**
+ * Set a mask on flags returned by av_get_cpu_flags().
+ * This function is mainly useful for testing.
+ * Please use av_force_cpu_flags() and av_get_cpu_flags() instead which are more flexible
+ */
+attribute_deprecated void av_set_cpu_flags_mask(int mask);
+
+/**
+ * Parse CPU flags from a string.
+ *
+ * The returned flags contain the specified flags as well as related unspecified flags.
+ *
+ * This function exists only for compatibility with libav.
+ * Please use av_parse_cpu_caps() when possible.
+ * @return a combination of AV_CPU_* flags, negative on error.
+ */
+attribute_deprecated
+int av_parse_cpu_flags(const char *s);
+
+/**
+ * Parse CPU caps from a string and update the given AV_CPU_* flags based on that.
+ *
+ * @return negative on error.
+ */
+int av_parse_cpu_caps(unsigned *flags, const char *s);
+
+/**
+ * @return the number of logical CPU cores present.
+ */
+int av_cpu_count(void);
+
+/**
+ * Get the maximum data alignment that may be required by FFmpeg.
+ *
+ * Note that this is affected by the build configuration and the CPU flags mask,
+ * so e.g. if the CPU supports AVX, but libavutil has been built with
+ * --disable-avx or the AV_CPU_FLAG_AVX flag has been disabled through
+ * av_set_cpu_flags_mask(), then this function will behave as if AVX is not
+ * present.
+ */
+size_t av_cpu_max_align(void);
+
+#endif /* AVUTIL_CPU_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/dict.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/dict.h
new file mode 100644
index 000000000..118f1f00e
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/dict.h
@@ -0,0 +1,200 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Public dictionary API.
+ * @deprecated
+ * AVDictionary is provided for compatibility with libav. It is both in
+ * implementation as well as API inefficient. It does not scale and is
+ * extremely slow with large dictionaries.
+ * It is recommended that new code uses our tree container from tree.c/h
+ * where applicable, which uses AVL trees to achieve O(log n) performance.
+ */
+
+#ifndef AVUTIL_DICT_H
+#define AVUTIL_DICT_H
+
+#include <stdint.h>
+
+#include "version.h"
+
+/**
+ * @addtogroup lavu_dict AVDictionary
+ * @ingroup lavu_data
+ *
+ * @brief Simple key:value store
+ *
+ * @{
+ * Dictionaries are used for storing key:value pairs. To create
+ * an AVDictionary, simply pass an address of a NULL pointer to
+ * av_dict_set(). NULL can be used as an empty dictionary wherever
+ * a pointer to an AVDictionary is required.
+ * Use av_dict_get() to retrieve an entry or iterate over all
+ * entries and finally av_dict_free() to free the dictionary
+ * and all its contents.
+ *
+ @code
+ AVDictionary *d = NULL; // "create" an empty dictionary
+ AVDictionaryEntry *t = NULL;
+
+ av_dict_set(&d, "foo", "bar", 0); // add an entry
+
+ char *k = av_strdup("key"); // if your strings are already allocated,
+ char *v = av_strdup("value"); // you can avoid copying them like this
+ av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
+
+ while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) {
+ <....> // iterate over all entries in d
+ }
+ av_dict_free(&d);
+ @endcode
+ */
+
+#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */
+#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key,
+ ignoring the suffix of the found key string. Only relevant in av_dict_get(). */
+#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been
+ allocated with av_malloc() or another memory allocation function. */
+#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been
+ allocated with av_malloc() or another memory allocation function. */
+#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries.
+#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no
+ delimiter is added, the strings are simply concatenated. */
+#define AV_DICT_MULTIKEY 64 /**< Allow to store several equal keys in the dictionary */
+
+typedef struct AVDictionaryEntry {
+ char *key;
+ char *value;
+} AVDictionaryEntry;
+
+typedef struct AVDictionary AVDictionary;
+
+/**
+ * Get a dictionary entry with matching key.
+ *
+ * The returned entry key or value must not be changed, or it will
+ * cause undefined behavior.
+ *
+ * To iterate through all the dictionary entries, you can set the matching key
+ * to the null string "" and set the AV_DICT_IGNORE_SUFFIX flag.
+ *
+ * @param prev Set to the previous matching element to find the next.
+ * If set to NULL the first matching element is returned.
+ * @param key matching key
+ * @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved
+ * @return found entry or NULL in case no matching entry was found in the dictionary
+ */
+AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
+ const AVDictionaryEntry *prev, int flags);
+
+/**
+ * Get number of entries in dictionary.
+ *
+ * @param m dictionary
+ * @return number of entries in dictionary
+ */
+int av_dict_count(const AVDictionary *m);
+
+/**
+ * Set the given entry in *pm, overwriting an existing entry.
+ *
+ * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set,
+ * these arguments will be freed on error.
+ *
+ * Warning: Adding a new entry to a dictionary invalidates all existing entries
+ * previously returned with av_dict_get.
+ *
+ * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL
+ * a dictionary struct is allocated and put in *pm.
+ * @param key entry key to add to *pm (will either be av_strduped or added as a new key depending on flags)
+ * @param value entry value to add to *pm (will be av_strduped or added as a new key depending on flags).
+ * Passing a NULL value will cause an existing entry to be deleted.
+ * @return >= 0 on success otherwise an error code <0
+ */
+int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags);
+
+/**
+ * Convenience wrapper for av_dict_set that converts the value to a string
+ * and stores it.
+ *
+ * Note: If AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error.
+ */
+int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags);
+
+/**
+ * Parse the key/value pairs list and add the parsed entries to a dictionary.
+ *
+ * In case of failure, all the successfully set entries are stored in
+ * *pm. You may need to manually free the created dictionary.
+ *
+ * @param key_val_sep a 0-terminated list of characters used to separate
+ * key from value
+ * @param pairs_sep a 0-terminated list of characters used to separate
+ * two pairs from each other
+ * @param flags flags to use when adding to dictionary.
+ * AV_DICT_DONT_STRDUP_KEY and AV_DICT_DONT_STRDUP_VAL
+ * are ignored since the key/value tokens will always
+ * be duplicated.
+ * @return 0 on success, negative AVERROR code on failure
+ */
+int av_dict_parse_string(AVDictionary **pm, const char *str,
+ const char *key_val_sep, const char *pairs_sep,
+ int flags);
+
+/**
+ * Copy entries from one AVDictionary struct into another.
+ * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL,
+ * this function will allocate a struct for you and put it in *dst
+ * @param src pointer to source AVDictionary struct
+ * @param flags flags to use when setting entries in *dst
+ * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag
+ * @return 0 on success, negative AVERROR code on failure. If dst was allocated
+ * by this function, callers should free the associated memory.
+ */
+int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags);
+
+/**
+ * Free all the memory allocated for an AVDictionary struct
+ * and all keys and values.
+ */
+void av_dict_free(AVDictionary **m);
+
+/**
+ * Get dictionary entries as a string.
+ *
+ * Create a string containing dictionary's entries.
+ * Such string may be passed back to av_dict_parse_string().
+ * @note String is escaped with backslashes ('\').
+ *
+ * @param[in] m dictionary
+ * @param[out] buffer Pointer to buffer that will be allocated with string containg entries.
+ * Buffer must be freed by the caller when is no longer needed.
+ * @param[in] key_val_sep character used to separate key from value
+ * @param[in] pairs_sep character used to separate two pairs from each other
+ * @return >= 0 on success, negative on error
+ * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same.
+ */
+int av_dict_get_string(const AVDictionary *m, char **buffer,
+ const char key_val_sep, const char pairs_sep);
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_DICT_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/error.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/error.h
new file mode 100644
index 000000000..71df4da35
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/error.h
@@ -0,0 +1,126 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * error code definitions
+ */
+
+#ifndef AVUTIL_ERROR_H
+#define AVUTIL_ERROR_H
+
+#include <errno.h>
+#include <stddef.h>
+
+/**
+ * @addtogroup lavu_error
+ *
+ * @{
+ */
+
+
+/* error handling */
+#if EDOM > 0
+#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions.
+#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value.
+#else
+/* Some platforms have E* and errno already negated. */
+#define AVERROR(e) (e)
+#define AVUNERROR(e) (e)
+#endif
+
+#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d))
+
+#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found
+#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2
+#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small
+#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found
+#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found
+#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found
+#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file
+#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted
+#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library
+#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found
+#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input
+#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found
+#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found
+#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome
+#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found
+
+#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found
+/**
+ * This is semantically identical to AVERROR_BUG
+ * it has been introduced in Libav after our AVERROR_BUG and with a modified value.
+ */
+#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ')
+#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library
+#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
+#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED)
+#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)
+/* HTTP & RTSP errors */
+#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0')
+#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1')
+#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3')
+#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4')
+#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X')
+#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X')
+
+#define AV_ERROR_MAX_STRING_SIZE 64
+
+/**
+ * Put a description of the AVERROR code errnum in errbuf.
+ * In case of failure the global variable errno is set to indicate the
+ * error. Even in case of failure av_strerror() will print a generic
+ * error message indicating the errnum provided to errbuf.
+ *
+ * @param errnum error code to describe
+ * @param errbuf buffer to which description is written
+ * @param errbuf_size the size in bytes of errbuf
+ * @return 0 on success, a negative value if a description for errnum
+ * cannot be found
+ */
+int av_strerror(int errnum, char *errbuf, size_t errbuf_size);
+
+/**
+ * Fill the provided buffer with a string containing an error string
+ * corresponding to the AVERROR code errnum.
+ *
+ * @param errbuf a buffer
+ * @param errbuf_size size in bytes of errbuf
+ * @param errnum error code to describe
+ * @return the buffer in input, filled with the error description
+ * @see av_strerror()
+ */
+static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum)
+{
+ av_strerror(errnum, errbuf, errbuf_size);
+ return errbuf;
+}
+
+/**
+ * Convenience macro, the return value should be used only directly in
+ * function arguments but never stand-alone.
+ */
+#define av_err2str(errnum) \
+ av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum)
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_ERROR_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/frame.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/frame.h
new file mode 100644
index 000000000..9d57d6ce6
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/frame.h
@@ -0,0 +1,893 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @ingroup lavu_frame
+ * reference-counted frame API
+ */
+
+#ifndef AVUTIL_FRAME_H
+#define AVUTIL_FRAME_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "avutil.h"
+#include "buffer.h"
+#include "dict.h"
+#include "rational.h"
+#include "samplefmt.h"
+#include "pixfmt.h"
+#include "version.h"
+
+
+/**
+ * @defgroup lavu_frame AVFrame
+ * @ingroup lavu_data
+ *
+ * @{
+ * AVFrame is an abstraction for reference-counted raw multimedia data.
+ */
+
+enum AVFrameSideDataType {
+ /**
+ * The data is the AVPanScan struct defined in libavcodec.
+ */
+ AV_FRAME_DATA_PANSCAN,
+ /**
+ * ATSC A53 Part 4 Closed Captions.
+ * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data.
+ * The number of bytes of CC data is AVFrameSideData.size.
+ */
+ AV_FRAME_DATA_A53_CC,
+ /**
+ * Stereoscopic 3d metadata.
+ * The data is the AVStereo3D struct defined in libavutil/stereo3d.h.
+ */
+ AV_FRAME_DATA_STEREO3D,
+ /**
+ * The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h.
+ */
+ AV_FRAME_DATA_MATRIXENCODING,
+ /**
+ * Metadata relevant to a downmix procedure.
+ * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h.
+ */
+ AV_FRAME_DATA_DOWNMIX_INFO,
+ /**
+ * ReplayGain information in the form of the AVReplayGain struct.
+ */
+ AV_FRAME_DATA_REPLAYGAIN,
+ /**
+ * This side data contains a 3x3 transformation matrix describing an affine
+ * transformation that needs to be applied to the frame for correct
+ * presentation.
+ *
+ * See libavutil/display.h for a detailed description of the data.
+ */
+ AV_FRAME_DATA_DISPLAYMATRIX,
+ /**
+ * Active Format Description data consisting of a single byte as specified
+ * in ETSI TS 101 154 using AVActiveFormatDescription enum.
+ */
+ AV_FRAME_DATA_AFD,
+ /**
+ * Motion vectors exported by some codecs (on demand through the export_mvs
+ * flag set in the libavcodec AVCodecContext flags2 option).
+ * The data is the AVMotionVector struct defined in
+ * libavutil/motion_vector.h.
+ */
+ AV_FRAME_DATA_MOTION_VECTORS,
+ /**
+ * Recommmends skipping the specified number of samples. This is exported
+ * only if the "skip_manual" AVOption is set in libavcodec.
+ * This has the same format as AV_PKT_DATA_SKIP_SAMPLES.
+ * @code
+ * u32le number of samples to skip from start of this packet
+ * u32le number of samples to skip from end of this packet
+ * u8 reason for start skip
+ * u8 reason for end skip (0=padding silence, 1=convergence)
+ * @endcode
+ */
+ AV_FRAME_DATA_SKIP_SAMPLES,
+ /**
+ * This side data must be associated with an audio frame and corresponds to
+ * enum AVAudioServiceType defined in avcodec.h.
+ */
+ AV_FRAME_DATA_AUDIO_SERVICE_TYPE,
+ /**
+ * Mastering display metadata associated with a video frame. The payload is
+ * an AVMasteringDisplayMetadata type and contains information about the
+ * mastering display color volume.
+ */
+ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA,
+ /**
+ * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer.
+ * This is set on the first frame of a GOP that has a temporal reference of 0.
+ */
+ AV_FRAME_DATA_GOP_TIMECODE,
+
+ /**
+ * The data represents the AVSphericalMapping structure defined in
+ * libavutil/spherical.h.
+ */
+ AV_FRAME_DATA_SPHERICAL,
+
+ /**
+ * Content light level (based on CTA-861.3). This payload contains data in
+ * the form of the AVContentLightMetadata struct.
+ */
+ AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
+
+ /**
+ * The data contains an ICC profile as an opaque octet buffer following the
+ * format described by ISO 15076-1 with an optional name defined in the
+ * metadata key entry "name".
+ */
+ AV_FRAME_DATA_ICC_PROFILE,
+
+#if FF_API_FRAME_QP
+ /**
+ * Implementation-specific description of the format of AV_FRAME_QP_TABLE_DATA.
+ * The contents of this side data are undocumented and internal; use
+ * av_frame_set_qp_table() and av_frame_get_qp_table() to access this in a
+ * meaningful way instead.
+ */
+ AV_FRAME_DATA_QP_TABLE_PROPERTIES,
+
+ /**
+ * Raw QP table data. Its format is described by
+ * AV_FRAME_DATA_QP_TABLE_PROPERTIES. Use av_frame_set_qp_table() and
+ * av_frame_get_qp_table() to access this instead.
+ */
+ AV_FRAME_DATA_QP_TABLE_DATA,
+#endif
+};
+
+enum AVActiveFormatDescription {
+ AV_AFD_SAME = 8,
+ AV_AFD_4_3 = 9,
+ AV_AFD_16_9 = 10,
+ AV_AFD_14_9 = 11,
+ AV_AFD_4_3_SP_14_9 = 13,
+ AV_AFD_16_9_SP_14_9 = 14,
+ AV_AFD_SP_4_3 = 15,
+};
+
+
+/**
+ * Structure to hold side data for an AVFrame.
+ *
+ * sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added
+ * to the end with a minor bump.
+ */
+typedef struct AVFrameSideData {
+ enum AVFrameSideDataType type;
+ uint8_t *data;
+ int size;
+ AVDictionary *metadata;
+ AVBufferRef *buf;
+} AVFrameSideData;
+
+/**
+ * This structure describes decoded (raw) audio or video data.
+ *
+ * AVFrame must be allocated using av_frame_alloc(). Note that this only
+ * allocates the AVFrame itself, the buffers for the data must be managed
+ * through other means (see below).
+ * AVFrame must be freed with av_frame_free().
+ *
+ * AVFrame is typically allocated once and then reused multiple times to hold
+ * different data (e.g. a single AVFrame to hold frames received from a
+ * decoder). In such a case, av_frame_unref() will free any references held by
+ * the frame and reset it to its original clean state before it
+ * is reused again.
+ *
+ * The data described by an AVFrame is usually reference counted through the
+ * AVBuffer API. The underlying buffer references are stored in AVFrame.buf /
+ * AVFrame.extended_buf. An AVFrame is considered to be reference counted if at
+ * least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case,
+ * every single data plane must be contained in one of the buffers in
+ * AVFrame.buf or AVFrame.extended_buf.
+ * There may be a single buffer for all the data, or one separate buffer for
+ * each plane, or anything in between.
+ *
+ * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added
+ * to the end with a minor bump.
+ *
+ * Fields can be accessed through AVOptions, the name string used, matches the
+ * C structure field name for fields accessible through AVOptions. The AVClass
+ * for AVFrame can be obtained from avcodec_get_frame_class()
+ */
+typedef struct AVFrame {
+#define AV_NUM_DATA_POINTERS 8
+ /**
+ * pointer to the picture/channel planes.
+ * This might be different from the first allocated byte
+ *
+ * Some decoders access areas outside 0,0 - width,height, please
+ * see avcodec_align_dimensions2(). Some filters and swscale can read
+ * up to 16 bytes beyond the planes, if these filters are to be used,
+ * then 16 extra bytes must be allocated.
+ *
+ * NOTE: Except for hwaccel formats, pointers not needed by the format
+ * MUST be set to NULL.
+ */
+ uint8_t *data[AV_NUM_DATA_POINTERS];
+
+ /**
+ * For video, size in bytes of each picture line.
+ * For audio, size in bytes of each plane.
+ *
+ * For audio, only linesize[0] may be set. For planar audio, each channel
+ * plane must be the same size.
+ *
+ * For video the linesizes should be multiples of the CPUs alignment
+ * preference, this is 16 or 32 for modern desktop CPUs.
+ * Some code requires such alignment other code can be slower without
+ * correct alignment, for yet other it makes no difference.
+ *
+ * @note The linesize may be larger than the size of usable data -- there
+ * may be extra padding present for performance reasons.
+ */
+ int linesize[AV_NUM_DATA_POINTERS];
+
+ /**
+ * pointers to the data planes/channels.
+ *
+ * For video, this should simply point to data[].
+ *
+ * For planar audio, each channel has a separate data pointer, and
+ * linesize[0] contains the size of each channel buffer.
+ * For packed audio, there is just one data pointer, and linesize[0]
+ * contains the total size of the buffer for all channels.
+ *
+ * Note: Both data and extended_data should always be set in a valid frame,
+ * but for planar audio with more channels that can fit in data,
+ * extended_data must be used in order to access all channels.
+ */
+ uint8_t **extended_data;
+
+ /**
+ * @name Video dimensions
+ * Video frames only. The coded dimensions (in pixels) of the video frame,
+ * i.e. the size of the rectangle that contains some well-defined values.
+ *
+ * @note The part of the frame intended for display/presentation is further
+ * restricted by the @ref cropping "Cropping rectangle".
+ * @{
+ */
+ int width, height;
+ /**
+ * @}
+ */
+
+ /**
+ * number of audio samples (per channel) described by this frame
+ */
+ int nb_samples;
+
+ /**
+ * format of the frame, -1 if unknown or unset
+ * Values correspond to enum AVPixelFormat for video frames,
+ * enum AVSampleFormat for audio)
+ */
+ int format;
+
+ /**
+ * 1 -> keyframe, 0-> not
+ */
+ int key_frame;
+
+ /**
+ * Picture type of the frame.
+ */
+ enum AVPictureType pict_type;
+
+ /**
+ * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
+ */
+ AVRational sample_aspect_ratio;
+
+ /**
+ * Presentation timestamp in time_base units (time when frame should be shown to user).
+ */
+ int64_t pts;
+
+#if FF_API_PKT_PTS
+ /**
+ * PTS copied from the AVPacket that was decoded to produce this frame.
+ * @deprecated use the pts field instead
+ */
+ attribute_deprecated
+ int64_t pkt_pts;
+#endif
+
+ /**
+ * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used)
+ * This is also the Presentation time of this AVFrame calculated from
+ * only AVPacket.dts values without pts values.
+ */
+ int64_t pkt_dts;
+
+ /**
+ * picture number in bitstream order
+ */
+ int coded_picture_number;
+ /**
+ * picture number in display order
+ */
+ int display_picture_number;
+
+ /**
+ * quality (between 1 (good) and FF_LAMBDA_MAX (bad))
+ */
+ int quality;
+
+ /**
+ * for some private data of the user
+ */
+ void *opaque;
+
+#if FF_API_ERROR_FRAME
+ /**
+ * @deprecated unused
+ */
+ attribute_deprecated
+ uint64_t error[AV_NUM_DATA_POINTERS];
+#endif
+
+ /**
+ * When decoding, this signals how much the picture must be delayed.
+ * extra_delay = repeat_pict / (2*fps)
+ */
+ int repeat_pict;
+
+ /**
+ * The content of the picture is interlaced.
+ */
+ int interlaced_frame;
+
+ /**
+ * If the content is interlaced, is top field displayed first.
+ */
+ int top_field_first;
+
+ /**
+ * Tell user application that palette has changed from previous frame.
+ */
+ int palette_has_changed;
+
+ /**
+ * reordered opaque 64 bits (generally an integer or a double precision float
+ * PTS but can be anything).
+ * The user sets AVCodecContext.reordered_opaque to represent the input at
+ * that time,
+ * the decoder reorders values as needed and sets AVFrame.reordered_opaque
+ * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque
+ * @deprecated in favor of pkt_pts
+ */
+ int64_t reordered_opaque;
+
+ /**
+ * Sample rate of the audio data.
+ */
+ int sample_rate;
+
+ /**
+ * Channel layout of the audio data.
+ */
+ uint64_t channel_layout;
+
+ /**
+ * AVBuffer references backing the data for this frame. If all elements of
+ * this array are NULL, then this frame is not reference counted. This array
+ * must be filled contiguously -- if buf[i] is non-NULL then buf[j] must
+ * also be non-NULL for all j < i.
+ *
+ * There may be at most one AVBuffer per data plane, so for video this array
+ * always contains all the references. For planar audio with more than
+ * AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in
+ * this array. Then the extra AVBufferRef pointers are stored in the
+ * extended_buf array.
+ */
+ AVBufferRef *buf[AV_NUM_DATA_POINTERS];
+
+ /**
+ * For planar audio which requires more than AV_NUM_DATA_POINTERS
+ * AVBufferRef pointers, this array will hold all the references which
+ * cannot fit into AVFrame.buf.
+ *
+ * Note that this is different from AVFrame.extended_data, which always
+ * contains all the pointers. This array only contains the extra pointers,
+ * which cannot fit into AVFrame.buf.
+ *
+ * This array is always allocated using av_malloc() by whoever constructs
+ * the frame. It is freed in av_frame_unref().
+ */
+ AVBufferRef **extended_buf;
+ /**
+ * Number of elements in extended_buf.
+ */
+ int nb_extended_buf;
+
+ AVFrameSideData **side_data;
+ int nb_side_data;
+
+/**
+ * @defgroup lavu_frame_flags AV_FRAME_FLAGS
+ * @ingroup lavu_frame
+ * Flags describing additional frame properties.
+ *
+ * @{
+ */
+
+/**
+ * The frame data may be corrupted, e.g. due to decoding errors.
+ */
+#define AV_FRAME_FLAG_CORRUPT (1 << 0)
+/**
+ * A flag to mark the frames which need to be decoded, but shouldn't be output.
+ */
+#define AV_FRAME_FLAG_DISCARD (1 << 2)
+/**
+ * @}
+ */
+
+ /**
+ * Frame flags, a combination of @ref lavu_frame_flags
+ */
+ int flags;
+
+ /**
+ * MPEG vs JPEG YUV range.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVColorRange color_range;
+
+ enum AVColorPrimaries color_primaries;
+
+ enum AVColorTransferCharacteristic color_trc;
+
+ /**
+ * YUV colorspace type.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVColorSpace colorspace;
+
+ enum AVChromaLocation chroma_location;
+
+ /**
+ * frame timestamp estimated using various heuristics, in stream time base
+ * - encoding: unused
+ * - decoding: set by libavcodec, read by user.
+ */
+ int64_t best_effort_timestamp;
+
+ /**
+ * reordered pos from the last AVPacket that has been input into the decoder
+ * - encoding: unused
+ * - decoding: Read by user.
+ */
+ int64_t pkt_pos;
+
+ /**
+ * duration of the corresponding packet, expressed in
+ * AVStream->time_base units, 0 if unknown.
+ * - encoding: unused
+ * - decoding: Read by user.
+ */
+ int64_t pkt_duration;
+
+ /**
+ * metadata.
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ AVDictionary *metadata;
+
+ /**
+ * decode error flags of the frame, set to a combination of
+ * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there
+ * were errors during the decoding.
+ * - encoding: unused
+ * - decoding: set by libavcodec, read by user.
+ */
+ int decode_error_flags;
+#define FF_DECODE_ERROR_INVALID_BITSTREAM 1
+#define FF_DECODE_ERROR_MISSING_REFERENCE 2
+
+ /**
+ * number of audio channels, only used for audio.
+ * - encoding: unused
+ * - decoding: Read by user.
+ */
+ int channels;
+
+ /**
+ * size of the corresponding packet containing the compressed
+ * frame.
+ * It is set to a negative value if unknown.
+ * - encoding: unused
+ * - decoding: set by libavcodec, read by user.
+ */
+ int pkt_size;
+
+#if FF_API_FRAME_QP
+ /**
+ * QP table
+ */
+ attribute_deprecated
+ int8_t *qscale_table;
+ /**
+ * QP store stride
+ */
+ attribute_deprecated
+ int qstride;
+
+ attribute_deprecated
+ int qscale_type;
+
+ attribute_deprecated
+ AVBufferRef *qp_table_buf;
+#endif
+ /**
+ * For hwaccel-format frames, this should be a reference to the
+ * AVHWFramesContext describing the frame.
+ */
+ AVBufferRef *hw_frames_ctx;
+
+ /**
+ * AVBufferRef for free use by the API user. FFmpeg will never check the
+ * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when
+ * the frame is unreferenced. av_frame_copy_props() calls create a new
+ * reference with av_buffer_ref() for the target frame's opaque_ref field.
+ *
+ * This is unrelated to the opaque field, although it serves a similar
+ * purpose.
+ */
+ AVBufferRef *opaque_ref;
+
+ /**
+ * @anchor cropping
+ * @name Cropping
+ * Video frames only. The number of pixels to discard from the the
+ * top/bottom/left/right border of the frame to obtain the sub-rectangle of
+ * the frame intended for presentation.
+ * @{
+ */
+ size_t crop_top;
+ size_t crop_bottom;
+ size_t crop_left;
+ size_t crop_right;
+ /**
+ * @}
+ */
+
+ /**
+ * AVBufferRef for internal use by a single libav* library.
+ * Must not be used to transfer data between libraries.
+ * Has to be NULL when ownership of the frame leaves the respective library.
+ *
+ * Code outside the FFmpeg libs should never check or change the contents of the buffer ref.
+ *
+ * FFmpeg calls av_buffer_unref() on it when the frame is unreferenced.
+ * av_frame_copy_props() calls create a new reference with av_buffer_ref()
+ * for the target frame's private_ref field.
+ */
+ AVBufferRef *private_ref;
+} AVFrame;
+
+#if FF_API_FRAME_GET_SET
+/**
+ * Accessors for some AVFrame fields. These used to be provided for ABI
+ * compatibility, and do not need to be used anymore.
+ */
+attribute_deprecated
+int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_best_effort_timestamp(AVFrame *frame, int64_t val);
+attribute_deprecated
+int64_t av_frame_get_pkt_duration (const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_pkt_duration (AVFrame *frame, int64_t val);
+attribute_deprecated
+int64_t av_frame_get_pkt_pos (const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_pkt_pos (AVFrame *frame, int64_t val);
+attribute_deprecated
+int64_t av_frame_get_channel_layout (const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_channel_layout (AVFrame *frame, int64_t val);
+attribute_deprecated
+int av_frame_get_channels (const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_channels (AVFrame *frame, int val);
+attribute_deprecated
+int av_frame_get_sample_rate (const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_sample_rate (AVFrame *frame, int val);
+attribute_deprecated
+AVDictionary *av_frame_get_metadata (const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_metadata (AVFrame *frame, AVDictionary *val);
+attribute_deprecated
+int av_frame_get_decode_error_flags (const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_decode_error_flags (AVFrame *frame, int val);
+attribute_deprecated
+int av_frame_get_pkt_size(const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_pkt_size(AVFrame *frame, int val);
+#if FF_API_FRAME_QP
+attribute_deprecated
+int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type);
+attribute_deprecated
+int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int type);
+#endif
+attribute_deprecated
+enum AVColorSpace av_frame_get_colorspace(const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_colorspace(AVFrame *frame, enum AVColorSpace val);
+attribute_deprecated
+enum AVColorRange av_frame_get_color_range(const AVFrame *frame);
+attribute_deprecated
+void av_frame_set_color_range(AVFrame *frame, enum AVColorRange val);
+#endif
+
+/**
+ * Get the name of a colorspace.
+ * @return a static string identifying the colorspace; can be NULL.
+ */
+const char *av_get_colorspace_name(enum AVColorSpace val);
+
+/**
+ * Allocate an AVFrame and set its fields to default values. The resulting
+ * struct must be freed using av_frame_free().
+ *
+ * @return An AVFrame filled with default values or NULL on failure.
+ *
+ * @note this only allocates the AVFrame itself, not the data buffers. Those
+ * must be allocated through other means, e.g. with av_frame_get_buffer() or
+ * manually.
+ */
+AVFrame *av_frame_alloc(void);
+
+/**
+ * Free the frame and any dynamically allocated objects in it,
+ * e.g. extended_data. If the frame is reference counted, it will be
+ * unreferenced first.
+ *
+ * @param frame frame to be freed. The pointer will be set to NULL.
+ */
+void av_frame_free(AVFrame **frame);
+
+/**
+ * Set up a new reference to the data described by the source frame.
+ *
+ * Copy frame properties from src to dst and create a new reference for each
+ * AVBufferRef from src.
+ *
+ * If src is not reference counted, new buffers are allocated and the data is
+ * copied.
+ *
+ * @warning: dst MUST have been either unreferenced with av_frame_unref(dst),
+ * or newly allocated with av_frame_alloc() before calling this
+ * function, or undefined behavior will occur.
+ *
+ * @return 0 on success, a negative AVERROR on error
+ */
+int av_frame_ref(AVFrame *dst, const AVFrame *src);
+
+/**
+ * Create a new frame that references the same data as src.
+ *
+ * This is a shortcut for av_frame_alloc()+av_frame_ref().
+ *
+ * @return newly created AVFrame on success, NULL on error.
+ */
+AVFrame *av_frame_clone(const AVFrame *src);
+
+/**
+ * Unreference all the buffers referenced by frame and reset the frame fields.
+ */
+void av_frame_unref(AVFrame *frame);
+
+/**
+ * Move everything contained in src to dst and reset src.
+ *
+ * @warning: dst is not unreferenced, but directly overwritten without reading
+ * or deallocating its contents. Call av_frame_unref(dst) manually
+ * before calling this function to ensure that no memory is leaked.
+ */
+void av_frame_move_ref(AVFrame *dst, AVFrame *src);
+
+/**
+ * Allocate new buffer(s) for audio or video data.
+ *
+ * The following fields must be set on frame before calling this function:
+ * - format (pixel format for video, sample format for audio)
+ * - width and height for video
+ * - nb_samples and channel_layout for audio
+ *
+ * This function will fill AVFrame.data and AVFrame.buf arrays and, if
+ * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf.
+ * For planar formats, one buffer will be allocated for each plane.
+ *
+ * @warning: if frame already has been allocated, calling this function will
+ * leak memory. In addition, undefined behavior can occur in certain
+ * cases.
+ *
+ * @param frame frame in which to store the new buffers.
+ * @param align Required buffer size alignment. If equal to 0, alignment will be
+ * chosen automatically for the current CPU. It is highly
+ * recommended to pass 0 here unless you know what you are doing.
+ *
+ * @return 0 on success, a negative AVERROR on error.
+ */
+int av_frame_get_buffer(AVFrame *frame, int align);
+
+/**
+ * Check if the frame data is writable.
+ *
+ * @return A positive value if the frame data is writable (which is true if and
+ * only if each of the underlying buffers has only one reference, namely the one
+ * stored in this frame). Return 0 otherwise.
+ *
+ * If 1 is returned the answer is valid until av_buffer_ref() is called on any
+ * of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly).
+ *
+ * @see av_frame_make_writable(), av_buffer_is_writable()
+ */
+int av_frame_is_writable(AVFrame *frame);
+
+/**
+ * Ensure that the frame data is writable, avoiding data copy if possible.
+ *
+ * Do nothing if the frame is writable, allocate new buffers and copy the data
+ * if it is not.
+ *
+ * @return 0 on success, a negative AVERROR on error.
+ *
+ * @see av_frame_is_writable(), av_buffer_is_writable(),
+ * av_buffer_make_writable()
+ */
+int av_frame_make_writable(AVFrame *frame);
+
+/**
+ * Copy the frame data from src to dst.
+ *
+ * This function does not allocate anything, dst must be already initialized and
+ * allocated with the same parameters as src.
+ *
+ * This function only copies the frame data (i.e. the contents of the data /
+ * extended data arrays), not any other properties.
+ *
+ * @return >= 0 on success, a negative AVERROR on error.
+ */
+int av_frame_copy(AVFrame *dst, const AVFrame *src);
+
+/**
+ * Copy only "metadata" fields from src to dst.
+ *
+ * Metadata for the purpose of this function are those fields that do not affect
+ * the data layout in the buffers. E.g. pts, sample rate (for audio) or sample
+ * aspect ratio (for video), but not width/height or channel layout.
+ * Side data is also copied.
+ */
+int av_frame_copy_props(AVFrame *dst, const AVFrame *src);
+
+/**
+ * Get the buffer reference a given data plane is stored in.
+ *
+ * @param plane index of the data plane of interest in frame->extended_data.
+ *
+ * @return the buffer reference that contains the plane or NULL if the input
+ * frame is not valid.
+ */
+AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane);
+
+/**
+ * Add a new side data to a frame.
+ *
+ * @param frame a frame to which the side data should be added
+ * @param type type of the added side data
+ * @param size size of the side data
+ *
+ * @return newly added side data on success, NULL on error
+ */
+AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
+ enum AVFrameSideDataType type,
+ int size);
+
+/**
+ * Add a new side data to a frame from an existing AVBufferRef
+ *
+ * @param frame a frame to which the side data should be added
+ * @param type the type of the added side data
+ * @param buf an AVBufferRef to add as side data. The ownership of
+ * the reference is transferred to the frame.
+ *
+ * @return newly added side data on success, NULL on error. On failure
+ * the frame is unchanged and the AVBufferRef remains owned by
+ * the caller.
+ */
+AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
+ enum AVFrameSideDataType type,
+ AVBufferRef *buf);
+
+/**
+ * @return a pointer to the side data of a given type on success, NULL if there
+ * is no side data with such type in this frame.
+ */
+AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
+ enum AVFrameSideDataType type);
+
+/**
+ * If side data of the supplied type exists in the frame, free it and remove it
+ * from the frame.
+ */
+void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
+
+
+/**
+ * Flags for frame cropping.
+ */
+enum {
+ /**
+ * Apply the maximum possible cropping, even if it requires setting the
+ * AVFrame.data[] entries to unaligned pointers. Passing unaligned data
+ * to FFmpeg API is generally not allowed, and causes undefined behavior
+ * (such as crashes). You can pass unaligned data only to FFmpeg APIs that
+ * are explicitly documented to accept it. Use this flag only if you
+ * absolutely know what you are doing.
+ */
+ AV_FRAME_CROP_UNALIGNED = 1 << 0,
+};
+
+/**
+ * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/
+ * crop_bottom fields. If cropping is successful, the function will adjust the
+ * data pointers and the width/height fields, and set the crop fields to 0.
+ *
+ * In all cases, the cropping boundaries will be rounded to the inherent
+ * alignment of the pixel format. In some cases, such as for opaque hwaccel
+ * formats, the left/top cropping is ignored. The crop fields are set to 0 even
+ * if the cropping was rounded or ignored.
+ *
+ * @param frame the frame which should be cropped
+ * @param flags Some combination of AV_FRAME_CROP_* flags, or 0.
+ *
+ * @return >= 0 on success, a negative AVERROR on error. If the cropping fields
+ * were invalid, AVERROR(ERANGE) is returned, and nothing is changed.
+ */
+int av_frame_apply_cropping(AVFrame *frame, int flags);
+
+/**
+ * @return a string identifying the side data type
+ */
+const char *av_frame_side_data_name(enum AVFrameSideDataType type);
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_FRAME_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/hwcontext.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/hwcontext.h
new file mode 100644
index 000000000..f5a4b6238
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/hwcontext.h
@@ -0,0 +1,584 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_HWCONTEXT_H
+#define AVUTIL_HWCONTEXT_H
+
+#include "buffer.h"
+#include "frame.h"
+#include "log.h"
+#include "pixfmt.h"
+
+enum AVHWDeviceType {
+ AV_HWDEVICE_TYPE_NONE,
+ AV_HWDEVICE_TYPE_VDPAU,
+ AV_HWDEVICE_TYPE_CUDA,
+ AV_HWDEVICE_TYPE_VAAPI,
+ AV_HWDEVICE_TYPE_DXVA2,
+ AV_HWDEVICE_TYPE_QSV,
+ AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
+ AV_HWDEVICE_TYPE_D3D11VA,
+ AV_HWDEVICE_TYPE_DRM,
+ AV_HWDEVICE_TYPE_OPENCL,
+ AV_HWDEVICE_TYPE_MEDIACODEC,
+};
+
+typedef struct AVHWDeviceInternal AVHWDeviceInternal;
+
+/**
+ * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
+ * i.e. state that is not tied to a concrete processing configuration.
+ * E.g., in an API that supports hardware-accelerated encoding and decoding,
+ * this struct will (if possible) wrap the state that is common to both encoding
+ * and decoding and from which specific instances of encoders or decoders can be
+ * derived.
+ *
+ * This struct is reference-counted with the AVBuffer mechanism. The
+ * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
+ * points to the actual AVHWDeviceContext. Further objects derived from
+ * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with
+ * specific properties) will hold an internal reference to it. After all the
+ * references are released, the AVHWDeviceContext itself will be freed,
+ * optionally invoking a user-specified callback for uninitializing the hardware
+ * state.
+ */
+typedef struct AVHWDeviceContext {
+ /**
+ * A class for logging. Set by av_hwdevice_ctx_alloc().
+ */
+ const AVClass *av_class;
+
+ /**
+ * Private data used internally by libavutil. Must not be accessed in any
+ * way by the caller.
+ */
+ AVHWDeviceInternal *internal;
+
+ /**
+ * This field identifies the underlying API used for hardware access.
+ *
+ * This field is set when this struct is allocated and never changed
+ * afterwards.
+ */
+ enum AVHWDeviceType type;
+
+ /**
+ * The format-specific data, allocated and freed by libavutil along with
+ * this context.
+ *
+ * Should be cast by the user to the format-specific context defined in the
+ * corresponding header (hwcontext_*.h) and filled as described in the
+ * documentation before calling av_hwdevice_ctx_init().
+ *
+ * After calling av_hwdevice_ctx_init() this struct should not be modified
+ * by the caller.
+ */
+ void *hwctx;
+
+ /**
+ * This field may be set by the caller before calling av_hwdevice_ctx_init().
+ *
+ * If non-NULL, this callback will be called when the last reference to
+ * this context is unreferenced, immediately before it is freed.
+ *
+ * @note when other objects (e.g an AVHWFramesContext) are derived from this
+ * struct, this callback will be invoked after all such child objects
+ * are fully uninitialized and their respective destructors invoked.
+ */
+ void (*free)(struct AVHWDeviceContext *ctx);
+
+ /**
+ * Arbitrary user data, to be used e.g. by the free() callback.
+ */
+ void *user_opaque;
+} AVHWDeviceContext;
+
+typedef struct AVHWFramesInternal AVHWFramesInternal;
+
+/**
+ * This struct describes a set or pool of "hardware" frames (i.e. those with
+ * data not located in normal system memory). All the frames in the pool are
+ * assumed to be allocated in the same way and interchangeable.
+ *
+ * This struct is reference-counted with the AVBuffer mechanism and tied to a
+ * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
+ * yields a reference, whose data field points to the actual AVHWFramesContext
+ * struct.
+ */
+typedef struct AVHWFramesContext {
+ /**
+ * A class for logging.
+ */
+ const AVClass *av_class;
+
+ /**
+ * Private data used internally by libavutil. Must not be accessed in any
+ * way by the caller.
+ */
+ AVHWFramesInternal *internal;
+
+ /**
+ * A reference to the parent AVHWDeviceContext. This reference is owned and
+ * managed by the enclosing AVHWFramesContext, but the caller may derive
+ * additional references from it.
+ */
+ AVBufferRef *device_ref;
+
+ /**
+ * The parent AVHWDeviceContext. This is simply a pointer to
+ * device_ref->data provided for convenience.
+ *
+ * Set by libavutil in av_hwframe_ctx_init().
+ */
+ AVHWDeviceContext *device_ctx;
+
+ /**
+ * The format-specific data, allocated and freed automatically along with
+ * this context.
+ *
+ * Should be cast by the user to the format-specific context defined in the
+ * corresponding header (hwframe_*.h) and filled as described in the
+ * documentation before calling av_hwframe_ctx_init().
+ *
+ * After any frames using this context are created, the contents of this
+ * struct should not be modified by the caller.
+ */
+ void *hwctx;
+
+ /**
+ * This field may be set by the caller before calling av_hwframe_ctx_init().
+ *
+ * If non-NULL, this callback will be called when the last reference to
+ * this context is unreferenced, immediately before it is freed.
+ */
+ void (*free)(struct AVHWFramesContext *ctx);
+
+ /**
+ * Arbitrary user data, to be used e.g. by the free() callback.
+ */
+ void *user_opaque;
+
+ /**
+ * A pool from which the frames are allocated by av_hwframe_get_buffer().
+ * This field may be set by the caller before calling av_hwframe_ctx_init().
+ * The buffers returned by calling av_buffer_pool_get() on this pool must
+ * have the properties described in the documentation in the corresponding hw
+ * type's header (hwcontext_*.h). The pool will be freed strictly before
+ * this struct's free() callback is invoked.
+ *
+ * This field may be NULL, then libavutil will attempt to allocate a pool
+ * internally. Note that certain device types enforce pools allocated at
+ * fixed size (frame count), which cannot be extended dynamically. In such a
+ * case, initial_pool_size must be set appropriately.
+ */
+ AVBufferPool *pool;
+
+ /**
+ * Initial size of the frame pool. If a device type does not support
+ * dynamically resizing the pool, then this is also the maximum pool size.
+ *
+ * May be set by the caller before calling av_hwframe_ctx_init(). Must be
+ * set if pool is NULL and the device type does not support dynamic pools.
+ */
+ int initial_pool_size;
+
+ /**
+ * The pixel format identifying the underlying HW surface type.
+ *
+ * Must be a hwaccel format, i.e. the corresponding descriptor must have the
+ * AV_PIX_FMT_FLAG_HWACCEL flag set.
+ *
+ * Must be set by the user before calling av_hwframe_ctx_init().
+ */
+ enum AVPixelFormat format;
+
+ /**
+ * The pixel format identifying the actual data layout of the hardware
+ * frames.
+ *
+ * Must be set by the caller before calling av_hwframe_ctx_init().
+ *
+ * @note when the underlying API does not provide the exact data layout, but
+ * only the colorspace/bit depth, this field should be set to the fully
+ * planar version of that format (e.g. for 8-bit 420 YUV it should be
+ * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else).
+ */
+ enum AVPixelFormat sw_format;
+
+ /**
+ * The allocated dimensions of the frames in this pool.
+ *
+ * Must be set by the user before calling av_hwframe_ctx_init().
+ */
+ int width, height;
+} AVHWFramesContext;
+
+/**
+ * Look up an AVHWDeviceType by name.
+ *
+ * @param name String name of the device type (case-insensitive).
+ * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if
+ * not found.
+ */
+enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name);
+
+/** Get the string name of an AVHWDeviceType.
+ *
+ * @param type Type from enum AVHWDeviceType.
+ * @return Pointer to a static string containing the name, or NULL if the type
+ * is not valid.
+ */
+const char *av_hwdevice_get_type_name(enum AVHWDeviceType type);
+
+/**
+ * Iterate over supported device types.
+ *
+ * @param type AV_HWDEVICE_TYPE_NONE initially, then the previous type
+ * returned by this function in subsequent iterations.
+ * @return The next usable device type from enum AVHWDeviceType, or
+ * AV_HWDEVICE_TYPE_NONE if there are no more.
+ */
+enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev);
+
+/**
+ * Allocate an AVHWDeviceContext for a given hardware type.
+ *
+ * @param type the type of the hardware device to allocate.
+ * @return a reference to the newly created AVHWDeviceContext on success or NULL
+ * on failure.
+ */
+AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type);
+
+/**
+ * Finalize the device context before use. This function must be called after
+ * the context is filled with all the required information and before it is
+ * used in any way.
+ *
+ * @param ref a reference to the AVHWDeviceContext
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_hwdevice_ctx_init(AVBufferRef *ref);
+
+/**
+ * Open a device of the specified type and create an AVHWDeviceContext for it.
+ *
+ * This is a convenience function intended to cover the simple cases. Callers
+ * who need to fine-tune device creation/management should open the device
+ * manually and then wrap it in an AVHWDeviceContext using
+ * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init().
+ *
+ * The returned context is already initialized and ready for use, the caller
+ * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of
+ * the created AVHWDeviceContext are set by this function and should not be
+ * touched by the caller.
+ *
+ * @param device_ctx On success, a reference to the newly-created device context
+ * will be written here. The reference is owned by the caller
+ * and must be released with av_buffer_unref() when no longer
+ * needed. On failure, NULL will be written to this pointer.
+ * @param type The type of the device to create.
+ * @param device A type-specific string identifying the device to open.
+ * @param opts A dictionary of additional (type-specific) options to use in
+ * opening the device. The dictionary remains owned by the caller.
+ * @param flags currently unused
+ *
+ * @return 0 on success, a negative AVERROR code on failure.
+ */
+int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type,
+ const char *device, AVDictionary *opts, int flags);
+
+/**
+ * Create a new device of the specified type from an existing device.
+ *
+ * If the source device is a device of the target type or was originally
+ * derived from such a device (possibly through one or more intermediate
+ * devices of other types), then this will return a reference to the
+ * existing device of the same type as is requested.
+ *
+ * Otherwise, it will attempt to derive a new device from the given source
+ * device. If direct derivation to the new type is not implemented, it will
+ * attempt the same derivation from each ancestor of the source device in
+ * turn looking for an implemented derivation method.
+ *
+ * @param dst_ctx On success, a reference to the newly-created
+ * AVHWDeviceContext.
+ * @param type The type of the new device to create.
+ * @param src_ctx A reference to an existing AVHWDeviceContext which will be
+ * used to create the new device.
+ * @param flags Currently unused; should be set to zero.
+ * @return Zero on success, a negative AVERROR code on failure.
+ */
+int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx,
+ enum AVHWDeviceType type,
+ AVBufferRef *src_ctx, int flags);
+
+
+/**
+ * Allocate an AVHWFramesContext tied to a given device context.
+ *
+ * @param device_ctx a reference to a AVHWDeviceContext. This function will make
+ * a new reference for internal use, the one passed to the
+ * function remains owned by the caller.
+ * @return a reference to the newly created AVHWFramesContext on success or NULL
+ * on failure.
+ */
+AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx);
+
+/**
+ * Finalize the context before use. This function must be called after the
+ * context is filled with all the required information and before it is attached
+ * to any frames.
+ *
+ * @param ref a reference to the AVHWFramesContext
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_hwframe_ctx_init(AVBufferRef *ref);
+
+/**
+ * Allocate a new frame attached to the given AVHWFramesContext.
+ *
+ * @param hwframe_ctx a reference to an AVHWFramesContext
+ * @param frame an empty (freshly allocated or unreffed) frame to be filled with
+ * newly allocated buffers.
+ * @param flags currently unused, should be set to zero
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags);
+
+/**
+ * Copy data to or from a hw surface. At least one of dst/src must have an
+ * AVHWFramesContext attached.
+ *
+ * If src has an AVHWFramesContext attached, then the format of dst (if set)
+ * must use one of the formats returned by av_hwframe_transfer_get_formats(src,
+ * AV_HWFRAME_TRANSFER_DIRECTION_FROM).
+ * If dst has an AVHWFramesContext attached, then the format of src must use one
+ * of the formats returned by av_hwframe_transfer_get_formats(dst,
+ * AV_HWFRAME_TRANSFER_DIRECTION_TO)
+ *
+ * dst may be "clean" (i.e. with data/buf pointers unset), in which case the
+ * data buffers will be allocated by this function using av_frame_get_buffer().
+ * If dst->format is set, then this format will be used, otherwise (when
+ * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen.
+ *
+ * The two frames must have matching allocated dimensions (i.e. equal to
+ * AVHWFramesContext.width/height), since not all device types support
+ * transferring a sub-rectangle of the whole surface. The display dimensions
+ * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but
+ * also have to be equal for both frames. When the display dimensions are
+ * smaller than the allocated dimensions, the content of the padding in the
+ * destination frame is unspecified.
+ *
+ * @param dst the destination frame. dst is not touched on failure.
+ * @param src the source frame.
+ * @param flags currently unused, should be set to zero
+ * @return 0 on success, a negative AVERROR error code on failure.
+ */
+int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags);
+
+enum AVHWFrameTransferDirection {
+ /**
+ * Transfer the data from the queried hw frame.
+ */
+ AV_HWFRAME_TRANSFER_DIRECTION_FROM,
+
+ /**
+ * Transfer the data to the queried hw frame.
+ */
+ AV_HWFRAME_TRANSFER_DIRECTION_TO,
+};
+
+/**
+ * Get a list of possible source or target formats usable in
+ * av_hwframe_transfer_data().
+ *
+ * @param hwframe_ctx the frame context to obtain the information for
+ * @param dir the direction of the transfer
+ * @param formats the pointer to the output format list will be written here.
+ * The list is terminated with AV_PIX_FMT_NONE and must be freed
+ * by the caller when no longer needed using av_free().
+ * If this function returns successfully, the format list will
+ * have at least one item (not counting the terminator).
+ * On failure, the contents of this pointer are unspecified.
+ * @param flags currently unused, should be set to zero
+ * @return 0 on success, a negative AVERROR code on failure.
+ */
+int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx,
+ enum AVHWFrameTransferDirection dir,
+ enum AVPixelFormat **formats, int flags);
+
+
+/**
+ * This struct describes the constraints on hardware frames attached to
+ * a given device with a hardware-specific configuration. This is returned
+ * by av_hwdevice_get_hwframe_constraints() and must be freed by
+ * av_hwframe_constraints_free() after use.
+ */
+typedef struct AVHWFramesConstraints {
+ /**
+ * A list of possible values for format in the hw_frames_ctx,
+ * terminated by AV_PIX_FMT_NONE. This member will always be filled.
+ */
+ enum AVPixelFormat *valid_hw_formats;
+
+ /**
+ * A list of possible values for sw_format in the hw_frames_ctx,
+ * terminated by AV_PIX_FMT_NONE. Can be NULL if this information is
+ * not known.
+ */
+ enum AVPixelFormat *valid_sw_formats;
+
+ /**
+ * The minimum size of frames in this hw_frames_ctx.
+ * (Zero if not known.)
+ */
+ int min_width;
+ int min_height;
+
+ /**
+ * The maximum size of frames in this hw_frames_ctx.
+ * (INT_MAX if not known / no limit.)
+ */
+ int max_width;
+ int max_height;
+} AVHWFramesConstraints;
+
+/**
+ * Allocate a HW-specific configuration structure for a given HW device.
+ * After use, the user must free all members as required by the specific
+ * hardware structure being used, then free the structure itself with
+ * av_free().
+ *
+ * @param device_ctx a reference to the associated AVHWDeviceContext.
+ * @return The newly created HW-specific configuration structure on
+ * success or NULL on failure.
+ */
+void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx);
+
+/**
+ * Get the constraints on HW frames given a device and the HW-specific
+ * configuration to be used with that device. If no HW-specific
+ * configuration is provided, returns the maximum possible capabilities
+ * of the device.
+ *
+ * @param ref a reference to the associated AVHWDeviceContext.
+ * @param hwconfig a filled HW-specific configuration structure, or NULL
+ * to return the maximum possible capabilities of the device.
+ * @return AVHWFramesConstraints structure describing the constraints
+ * on the device, or NULL if not available.
+ */
+AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
+ const void *hwconfig);
+
+/**
+ * Free an AVHWFrameConstraints structure.
+ *
+ * @param constraints The (filled or unfilled) AVHWFrameConstraints structure.
+ */
+void av_hwframe_constraints_free(AVHWFramesConstraints **constraints);
+
+
+/**
+ * Flags to apply to frame mappings.
+ */
+enum {
+ /**
+ * The mapping must be readable.
+ */
+ AV_HWFRAME_MAP_READ = 1 << 0,
+ /**
+ * The mapping must be writeable.
+ */
+ AV_HWFRAME_MAP_WRITE = 1 << 1,
+ /**
+ * The mapped frame will be overwritten completely in subsequent
+ * operations, so the current frame data need not be loaded. Any values
+ * which are not overwritten are unspecified.
+ */
+ AV_HWFRAME_MAP_OVERWRITE = 1 << 2,
+ /**
+ * The mapping must be direct. That is, there must not be any copying in
+ * the map or unmap steps. Note that performance of direct mappings may
+ * be much lower than normal memory.
+ */
+ AV_HWFRAME_MAP_DIRECT = 1 << 3,
+};
+
+/**
+ * Map a hardware frame.
+ *
+ * This has a number of different possible effects, depending on the format
+ * and origin of the src and dst frames. On input, src should be a usable
+ * frame with valid buffers and dst should be blank (typically as just created
+ * by av_frame_alloc()). src should have an associated hwframe context, and
+ * dst may optionally have a format and associated hwframe context.
+ *
+ * If src was created by mapping a frame from the hwframe context of dst,
+ * then this function undoes the mapping - dst is replaced by a reference to
+ * the frame that src was originally mapped from.
+ *
+ * If both src and dst have an associated hwframe context, then this function
+ * attempts to map the src frame from its hardware context to that of dst and
+ * then fill dst with appropriate data to be usable there. This will only be
+ * possible if the hwframe contexts and associated devices are compatible -
+ * given compatible devices, av_hwframe_ctx_create_derived() can be used to
+ * create a hwframe context for dst in which mapping should be possible.
+ *
+ * If src has a hwframe context but dst does not, then the src frame is
+ * mapped to normal memory and should thereafter be usable as a normal frame.
+ * If the format is set on dst, then the mapping will attempt to create dst
+ * with that format and fail if it is not possible. If format is unset (is
+ * AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate
+ * format to use is (probably the sw_format of the src hwframe context).
+ *
+ * A return value of AVERROR(ENOSYS) indicates that the mapping is not
+ * possible with the given arguments and hwframe setup, while other return
+ * values indicate that it failed somehow.
+ *
+ * @param dst Destination frame, to contain the mapping.
+ * @param src Source frame, to be mapped.
+ * @param flags Some combination of AV_HWFRAME_MAP_* flags.
+ * @return Zero on success, negative AVERROR code on failure.
+ */
+int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags);
+
+
+/**
+ * Create and initialise an AVHWFramesContext as a mapping of another existing
+ * AVHWFramesContext on a different device.
+ *
+ * av_hwframe_ctx_init() should not be called after this.
+ *
+ * @param derived_frame_ctx On success, a reference to the newly created
+ * AVHWFramesContext.
+ * @param derived_device_ctx A reference to the device to create the new
+ * AVHWFramesContext on.
+ * @param source_frame_ctx A reference to an existing AVHWFramesContext
+ * which will be mapped to the derived context.
+ * @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the
+ * mapping parameters to apply to frames which are allocated
+ * in the derived device.
+ * @return Zero on success, negative AVERROR code on failure.
+ */
+int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx,
+ enum AVPixelFormat format,
+ AVBufferRef *derived_device_ctx,
+ AVBufferRef *source_frame_ctx,
+ int flags);
+
+#endif /* AVUTIL_HWCONTEXT_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/intfloat.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/intfloat.h
new file mode 100644
index 000000000..fe3d7ec4a
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/intfloat.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011 Mans Rullgard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_INTFLOAT_H
+#define AVUTIL_INTFLOAT_H
+
+#include <stdint.h>
+#include "attributes.h"
+
+union av_intfloat32 {
+ uint32_t i;
+ float f;
+};
+
+union av_intfloat64 {
+ uint64_t i;
+ double f;
+};
+
+/**
+ * Reinterpret a 32-bit integer as a float.
+ */
+static av_always_inline float av_int2float(uint32_t i)
+{
+ union av_intfloat32 v;
+ v.i = i;
+ return v.f;
+}
+
+/**
+ * Reinterpret a float as a 32-bit integer.
+ */
+static av_always_inline uint32_t av_float2int(float f)
+{
+ union av_intfloat32 v;
+ v.f = f;
+ return v.i;
+}
+
+/**
+ * Reinterpret a 64-bit integer as a double.
+ */
+static av_always_inline double av_int2double(uint64_t i)
+{
+ union av_intfloat64 v;
+ v.i = i;
+ return v.f;
+}
+
+/**
+ * Reinterpret a double as a 64-bit integer.
+ */
+static av_always_inline uint64_t av_double2int(double f)
+{
+ union av_intfloat64 v;
+ v.f = f;
+ return v.i;
+}
+
+#endif /* AVUTIL_INTFLOAT_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/log.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/log.h
new file mode 100644
index 000000000..d9554e609
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/log.h
@@ -0,0 +1,362 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_LOG_H
+#define AVUTIL_LOG_H
+
+#include <stdarg.h>
+#include "avutil.h"
+#include "attributes.h"
+#include "version.h"
+
+typedef enum {
+ AV_CLASS_CATEGORY_NA = 0,
+ AV_CLASS_CATEGORY_INPUT,
+ AV_CLASS_CATEGORY_OUTPUT,
+ AV_CLASS_CATEGORY_MUXER,
+ AV_CLASS_CATEGORY_DEMUXER,
+ AV_CLASS_CATEGORY_ENCODER,
+ AV_CLASS_CATEGORY_DECODER,
+ AV_CLASS_CATEGORY_FILTER,
+ AV_CLASS_CATEGORY_BITSTREAM_FILTER,
+ AV_CLASS_CATEGORY_SWSCALER,
+ AV_CLASS_CATEGORY_SWRESAMPLER,
+ AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40,
+ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
+ AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,
+ AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
+ AV_CLASS_CATEGORY_DEVICE_OUTPUT,
+ AV_CLASS_CATEGORY_DEVICE_INPUT,
+ AV_CLASS_CATEGORY_NB ///< not part of ABI/API
+}AVClassCategory;
+
+#define AV_IS_INPUT_DEVICE(category) \
+ (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) || \
+ ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) || \
+ ((category) == AV_CLASS_CATEGORY_DEVICE_INPUT))
+
+#define AV_IS_OUTPUT_DEVICE(category) \
+ (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT) || \
+ ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) || \
+ ((category) == AV_CLASS_CATEGORY_DEVICE_OUTPUT))
+
+struct AVOptionRanges;
+
+/**
+ * Describe the class of an AVClass context structure. That is an
+ * arbitrary struct of which the first field is a pointer to an
+ * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
+ */
+typedef struct AVClass {
+ /**
+ * The name of the class; usually it is the same name as the
+ * context structure type to which the AVClass is associated.
+ */
+ const char* class_name;
+
+ /**
+ * A pointer to a function which returns the name of a context
+ * instance ctx associated with the class.
+ */
+ const char* (*item_name)(void* ctx);
+
+ /**
+ * a pointer to the first option specified in the class if any or NULL
+ *
+ * @see av_set_default_options()
+ */
+ const struct AVOption *option;
+
+ /**
+ * LIBAVUTIL_VERSION with which this structure was created.
+ * This is used to allow fields to be added without requiring major
+ * version bumps everywhere.
+ */
+
+ int version;
+
+ /**
+ * Offset in the structure where log_level_offset is stored.
+ * 0 means there is no such variable
+ */
+ int log_level_offset_offset;
+
+ /**
+ * Offset in the structure where a pointer to the parent context for
+ * logging is stored. For example a decoder could pass its AVCodecContext
+ * to eval as such a parent context, which an av_log() implementation
+ * could then leverage to display the parent context.
+ * The offset can be NULL.
+ */
+ int parent_log_context_offset;
+
+ /**
+ * Return next AVOptions-enabled child or NULL
+ */
+ void* (*child_next)(void *obj, void *prev);
+
+ /**
+ * Return an AVClass corresponding to the next potential
+ * AVOptions-enabled child.
+ *
+ * The difference between child_next and this is that
+ * child_next iterates over _already existing_ objects, while
+ * child_class_next iterates over _all possible_ children.
+ */
+ const struct AVClass* (*child_class_next)(const struct AVClass *prev);
+
+ /**
+ * Category used for visualization (like color)
+ * This is only set if the category is equal for all objects using this class.
+ * available since version (51 << 16 | 56 << 8 | 100)
+ */
+ AVClassCategory category;
+
+ /**
+ * Callback to return the category.
+ * available since version (51 << 16 | 59 << 8 | 100)
+ */
+ AVClassCategory (*get_category)(void* ctx);
+
+ /**
+ * Callback to return the supported/allowed ranges.
+ * available since version (52.12)
+ */
+ int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags);
+} AVClass;
+
+/**
+ * @addtogroup lavu_log
+ *
+ * @{
+ *
+ * @defgroup lavu_log_constants Logging Constants
+ *
+ * @{
+ */
+
+/**
+ * Print no output.
+ */
+#define AV_LOG_QUIET -8
+
+/**
+ * Something went really wrong and we will crash now.
+ */
+#define AV_LOG_PANIC 0
+
+/**
+ * Something went wrong and recovery is not possible.
+ * For example, no header was found for a format which depends
+ * on headers or an illegal combination of parameters is used.
+ */
+#define AV_LOG_FATAL 8
+
+/**
+ * Something went wrong and cannot losslessly be recovered.
+ * However, not all future data is affected.
+ */
+#define AV_LOG_ERROR 16
+
+/**
+ * Something somehow does not look correct. This may or may not
+ * lead to problems. An example would be the use of '-vstrict -2'.
+ */
+#define AV_LOG_WARNING 24
+
+/**
+ * Standard information.
+ */
+#define AV_LOG_INFO 32
+
+/**
+ * Detailed information.
+ */
+#define AV_LOG_VERBOSE 40
+
+/**
+ * Stuff which is only useful for libav* developers.
+ */
+#define AV_LOG_DEBUG 48
+
+/**
+ * Extremely verbose debugging, useful for libav* development.
+ */
+#define AV_LOG_TRACE 56
+
+#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET)
+
+/**
+ * @}
+ */
+
+/**
+ * Sets additional colors for extended debugging sessions.
+ * @code
+ av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), "Message in purple\n");
+ @endcode
+ * Requires 256color terminal support. Uses outside debugging is not
+ * recommended.
+ */
+#define AV_LOG_C(x) ((x) << 8)
+
+/**
+ * Send the specified message to the log if the level is less than or equal
+ * to the current av_log_level. By default, all logging messages are sent to
+ * stderr. This behavior can be altered by setting a different logging callback
+ * function.
+ * @see av_log_set_callback
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct or NULL if general log.
+ * @param level The importance level of the message expressed using a @ref
+ * lavu_log_constants "Logging Constant".
+ * @param fmt The format string (printf-compatible) that specifies how
+ * subsequent arguments are converted to output.
+ */
+void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4);
+
+
+/**
+ * Send the specified message to the log if the level is less than or equal
+ * to the current av_log_level. By default, all logging messages are sent to
+ * stderr. This behavior can be altered by setting a different logging callback
+ * function.
+ * @see av_log_set_callback
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct.
+ * @param level The importance level of the message expressed using a @ref
+ * lavu_log_constants "Logging Constant".
+ * @param fmt The format string (printf-compatible) that specifies how
+ * subsequent arguments are converted to output.
+ * @param vl The arguments referenced by the format string.
+ */
+void av_vlog(void *avcl, int level, const char *fmt, va_list vl);
+
+/**
+ * Get the current log level
+ *
+ * @see lavu_log_constants
+ *
+ * @return Current log level
+ */
+int av_log_get_level(void);
+
+/**
+ * Set the log level
+ *
+ * @see lavu_log_constants
+ *
+ * @param level Logging level
+ */
+void av_log_set_level(int level);
+
+/**
+ * Set the logging callback
+ *
+ * @note The callback must be thread safe, even if the application does not use
+ * threads itself as some codecs are multithreaded.
+ *
+ * @see av_log_default_callback
+ *
+ * @param callback A logging function with a compatible signature.
+ */
+void av_log_set_callback(void (*callback)(void*, int, const char*, va_list));
+
+/**
+ * Default logging callback
+ *
+ * It prints the message to stderr, optionally colorizing it.
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct.
+ * @param level The importance level of the message expressed using a @ref
+ * lavu_log_constants "Logging Constant".
+ * @param fmt The format string (printf-compatible) that specifies how
+ * subsequent arguments are converted to output.
+ * @param vl The arguments referenced by the format string.
+ */
+void av_log_default_callback(void *avcl, int level, const char *fmt,
+ va_list vl);
+
+/**
+ * Return the context name
+ *
+ * @param ctx The AVClass context
+ *
+ * @return The AVClass class_name
+ */
+const char* av_default_item_name(void* ctx);
+AVClassCategory av_default_get_category(void *ptr);
+
+/**
+ * Format a line of log the same way as the default callback.
+ * @param line buffer to receive the formatted line
+ * @param line_size size of the buffer
+ * @param print_prefix used to store whether the prefix must be printed;
+ * must point to a persistent integer initially set to 1
+ */
+void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl,
+ char *line, int line_size, int *print_prefix);
+
+/**
+ * Format a line of log the same way as the default callback.
+ * @param line buffer to receive the formatted line;
+ * may be NULL if line_size is 0
+ * @param line_size size of the buffer; at most line_size-1 characters will
+ * be written to the buffer, plus one null terminator
+ * @param print_prefix used to store whether the prefix must be printed;
+ * must point to a persistent integer initially set to 1
+ * @return Returns a negative value if an error occurred, otherwise returns
+ * the number of characters that would have been written for a
+ * sufficiently large buffer, not including the terminating null
+ * character. If the return value is not less than line_size, it means
+ * that the log message was truncated to fit the buffer.
+ */
+int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl,
+ char *line, int line_size, int *print_prefix);
+
+/**
+ * Skip repeated messages, this requires the user app to use av_log() instead of
+ * (f)printf as the 2 would otherwise interfere and lead to
+ * "Last message repeated x times" messages below (f)printf messages with some
+ * bad luck.
+ * Also to receive the last, "last repeated" line if any, the user app must
+ * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end
+ */
+#define AV_LOG_SKIP_REPEATED 1
+
+/**
+ * Include the log severity in messages originating from codecs.
+ *
+ * Results in messages such as:
+ * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts
+ */
+#define AV_LOG_PRINT_LEVEL 2
+
+void av_log_set_flags(int arg);
+int av_log_get_flags(void);
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_LOG_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/macros.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/macros.h
new file mode 100644
index 000000000..2007ee561
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/macros.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @ingroup lavu
+ * Utility Preprocessor macros
+ */
+
+#ifndef AVUTIL_MACROS_H
+#define AVUTIL_MACROS_H
+
+/**
+ * @addtogroup preproc_misc Preprocessor String Macros
+ *
+ * String manipulation macros
+ *
+ * @{
+ */
+
+#define AV_STRINGIFY(s) AV_TOSTRING(s)
+#define AV_TOSTRING(s) #s
+
+#define AV_GLUE(a, b) a ## b
+#define AV_JOIN(a, b) AV_GLUE(a, b)
+
+/**
+ * @}
+ */
+
+#define AV_PRAGMA(s) _Pragma(#s)
+
+#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1))
+
+#endif /* AVUTIL_MACROS_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/mathematics.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/mathematics.h
new file mode 100644
index 000000000..54901800b
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/mathematics.h
@@ -0,0 +1,242 @@
+/*
+ * copyright (c) 2005-2012 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @addtogroup lavu_math
+ * Mathematical utilities for working with timestamp and time base.
+ */
+
+#ifndef AVUTIL_MATHEMATICS_H
+#define AVUTIL_MATHEMATICS_H
+
+#include <stdint.h>
+#include <math.h>
+#include "attributes.h"
+#include "rational.h"
+#include "intfloat.h"
+
+#ifndef M_E
+#define M_E 2.7182818284590452354 /* e */
+#endif
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942 /* log_e 2 */
+#endif
+#ifndef M_LN10
+#define M_LN10 2.30258509299404568402 /* log_e 10 */
+#endif
+#ifndef M_LOG2_10
+#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */
+#endif
+#ifndef M_PHI
+#define M_PHI 1.61803398874989484820 /* phi / golden ratio */
+#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846 /* pi */
+#endif
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923 /* pi/2 */
+#endif
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
+#endif
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
+#endif
+#ifndef NAN
+#define NAN av_int2float(0x7fc00000)
+#endif
+#ifndef INFINITY
+#define INFINITY av_int2float(0x7f800000)
+#endif
+
+/**
+ * @addtogroup lavu_math
+ *
+ * @{
+ */
+
+/**
+ * Rounding methods.
+ */
+enum AVRounding {
+ AV_ROUND_ZERO = 0, ///< Round toward zero.
+ AV_ROUND_INF = 1, ///< Round away from zero.
+ AV_ROUND_DOWN = 2, ///< Round toward -infinity.
+ AV_ROUND_UP = 3, ///< Round toward +infinity.
+ AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero.
+ /**
+ * Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through
+ * unchanged, avoiding special cases for #AV_NOPTS_VALUE.
+ *
+ * Unlike other values of the enumeration AVRounding, this value is a
+ * bitmask that must be used in conjunction with another value of the
+ * enumeration through a bitwise OR, in order to set behavior for normal
+ * cases.
+ *
+ * @code{.c}
+ * av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
+ * // Rescaling 3:
+ * // Calculating 3 * 1 / 2
+ * // 3 / 2 is rounded up to 2
+ * // => 2
+ *
+ * av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
+ * // Rescaling AV_NOPTS_VALUE:
+ * // AV_NOPTS_VALUE == INT64_MIN
+ * // AV_NOPTS_VALUE is passed through
+ * // => AV_NOPTS_VALUE
+ * @endcode
+ */
+ AV_ROUND_PASS_MINMAX = 8192,
+};
+
+/**
+ * Compute the greatest common divisor of two integer operands.
+ *
+ * @param a,b Operands
+ * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0;
+ * if a == 0 and b == 0, returns 0.
+ */
+int64_t av_const av_gcd(int64_t a, int64_t b);
+
+/**
+ * Rescale a 64-bit integer with rounding to nearest.
+ *
+ * The operation is mathematically equivalent to `a * b / c`, but writing that
+ * directly can overflow.
+ *
+ * This function is equivalent to av_rescale_rnd() with #AV_ROUND_NEAR_INF.
+ *
+ * @see av_rescale_rnd(), av_rescale_q(), av_rescale_q_rnd()
+ */
+int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const;
+
+/**
+ * Rescale a 64-bit integer with specified rounding.
+ *
+ * The operation is mathematically equivalent to `a * b / c`, but writing that
+ * directly can overflow, and does not support different rounding methods.
+ *
+ * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd()
+ */
+int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) av_const;
+
+/**
+ * Rescale a 64-bit integer by 2 rational numbers.
+ *
+ * The operation is mathematically equivalent to `a * bq / cq`.
+ *
+ * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF.
+ *
+ * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd()
+ */
+int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;
+
+/**
+ * Rescale a 64-bit integer by 2 rational numbers with specified rounding.
+ *
+ * The operation is mathematically equivalent to `a * bq / cq`.
+ *
+ * @see av_rescale(), av_rescale_rnd(), av_rescale_q()
+ */
+int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq,
+ enum AVRounding rnd) av_const;
+
+/**
+ * Compare two timestamps each in its own time base.
+ *
+ * @return One of the following values:
+ * - -1 if `ts_a` is before `ts_b`
+ * - 1 if `ts_a` is after `ts_b`
+ * - 0 if they represent the same position
+ *
+ * @warning
+ * The result of the function is undefined if one of the timestamps is outside
+ * the `int64_t` range when represented in the other's timebase.
+ */
+int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b);
+
+/**
+ * Compare the remainders of two integer operands divided by a common divisor.
+ *
+ * In other words, compare the least significant `log2(mod)` bits of integers
+ * `a` and `b`.
+ *
+ * @code{.c}
+ * av_compare_mod(0x11, 0x02, 0x10) < 0 // since 0x11 % 0x10 (0x1) < 0x02 % 0x10 (0x2)
+ * av_compare_mod(0x11, 0x02, 0x20) > 0 // since 0x11 % 0x20 (0x11) > 0x02 % 0x20 (0x02)
+ * @endcode
+ *
+ * @param a,b Operands
+ * @param mod Divisor; must be a power of 2
+ * @return
+ * - a negative value if `a % mod < b % mod`
+ * - a positive value if `a % mod > b % mod`
+ * - zero if `a % mod == b % mod`
+ */
+int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod);
+
+/**
+ * Rescale a timestamp while preserving known durations.
+ *
+ * This function is designed to be called per audio packet to scale the input
+ * timestamp to a different time base. Compared to a simple av_rescale_q()
+ * call, this function is robust against possible inconsistent frame durations.
+ *
+ * The `last` parameter is a state variable that must be preserved for all
+ * subsequent calls for the same stream. For the first call, `*last` should be
+ * initialized to #AV_NOPTS_VALUE.
+ *
+ * @param[in] in_tb Input time base
+ * @param[in] in_ts Input timestamp
+ * @param[in] fs_tb Duration time base; typically this is finer-grained
+ * (greater) than `in_tb` and `out_tb`
+ * @param[in] duration Duration till the next call to this function (i.e.
+ * duration of the current packet/frame)
+ * @param[in,out] last Pointer to a timestamp expressed in terms of
+ * `fs_tb`, acting as a state variable
+ * @param[in] out_tb Output timebase
+ * @return Timestamp expressed in terms of `out_tb`
+ *
+ * @note In the context of this function, "duration" is in term of samples, not
+ * seconds.
+ */
+int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb);
+
+/**
+ * Add a value to a timestamp.
+ *
+ * This function guarantees that when the same value is repeatly added that
+ * no accumulation of rounding errors occurs.
+ *
+ * @param[in] ts Input timestamp
+ * @param[in] ts_tb Input timestamp time base
+ * @param[in] inc Value to be added
+ * @param[in] inc_tb Time base of `inc`
+ */
+int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc);
+
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_MATHEMATICS_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/mem.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/mem.h
new file mode 100644
index 000000000..7e0b12a8a
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/mem.h
@@ -0,0 +1,700 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @ingroup lavu_mem
+ * Memory handling functions
+ */
+
+#ifndef AVUTIL_MEM_H
+#define AVUTIL_MEM_H
+
+#include <limits.h>
+#include <stdint.h>
+
+#include "attributes.h"
+#include "error.h"
+#include "avutil.h"
+
+/**
+ * @addtogroup lavu_mem
+ * Utilities for manipulating memory.
+ *
+ * FFmpeg has several applications of memory that are not required of a typical
+ * program. For example, the computing-heavy components like video decoding and
+ * encoding can be sped up significantly through the use of aligned memory.
+ *
+ * However, for each of FFmpeg's applications of memory, there might not be a
+ * recognized or standardized API for that specific use. Memory alignment, for
+ * instance, varies wildly depending on operating systems, architectures, and
+ * compilers. Hence, this component of @ref libavutil is created to make
+ * dealing with memory consistently possible on all platforms.
+ *
+ * @{
+ *
+ * @defgroup lavu_mem_macros Alignment Macros
+ * Helper macros for declaring aligned variables.
+ * @{
+ */
+
+/**
+ * @def DECLARE_ALIGNED(n,t,v)
+ * Declare a variable that is aligned in memory.
+ *
+ * @code{.c}
+ * DECLARE_ALIGNED(16, uint16_t, aligned_int) = 42;
+ * DECLARE_ALIGNED(32, uint8_t, aligned_array)[128];
+ *
+ * // The default-alignment equivalent would be
+ * uint16_t aligned_int = 42;
+ * uint8_t aligned_array[128];
+ * @endcode
+ *
+ * @param n Minimum alignment in bytes
+ * @param t Type of the variable (or array element)
+ * @param v Name of the variable
+ */
+
+/**
+ * @def DECLARE_ASM_ALIGNED(n,t,v)
+ * Declare an aligned variable appropriate for use in inline assembly code.
+ *
+ * @code{.c}
+ * DECLARE_ASM_ALIGNED(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008);
+ * @endcode
+ *
+ * @param n Minimum alignment in bytes
+ * @param t Type of the variable (or array element)
+ * @param v Name of the variable
+ */
+
+/**
+ * @def DECLARE_ASM_CONST(n,t,v)
+ * Declare a static constant aligned variable appropriate for use in inline
+ * assembly code.
+ *
+ * @code{.c}
+ * DECLARE_ASM_CONST(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008);
+ * @endcode
+ *
+ * @param n Minimum alignment in bytes
+ * @param t Type of the variable (or array element)
+ * @param v Name of the variable
+ */
+
+#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C)
+ #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v
+ #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v
+ #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v
+#elif defined(__DJGPP__)
+ #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v
+ #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v
+ #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v
+#elif defined(__GNUC__) || defined(__clang__)
+ #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v
+ #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v
+ #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v
+#elif defined(_MSC_VER)
+ #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v
+ #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v
+ #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v
+#else
+ #define DECLARE_ALIGNED(n,t,v) t v
+ #define DECLARE_ASM_ALIGNED(n,t,v) t v
+ #define DECLARE_ASM_CONST(n,t,v) static const t v
+#endif
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup lavu_mem_attrs Function Attributes
+ * Function attributes applicable to memory handling functions.
+ *
+ * These function attributes can help compilers emit more useful warnings, or
+ * generate better code.
+ * @{
+ */
+
+/**
+ * @def av_malloc_attrib
+ * Function attribute denoting a malloc-like function.
+ *
+ * @see <a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007bmalloc_007d-function-attribute-3251">Function attribute `malloc` in GCC's documentation</a>
+ */
+
+#if AV_GCC_VERSION_AT_LEAST(3,1)
+ #define av_malloc_attrib __attribute__((__malloc__))
+#else
+ #define av_malloc_attrib
+#endif
+
+/**
+ * @def av_alloc_size(...)
+ * Function attribute used on a function that allocates memory, whose size is
+ * given by the specified parameter(s).
+ *
+ * @code{.c}
+ * void *av_malloc(size_t size) av_alloc_size(1);
+ * void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2);
+ * @endcode
+ *
+ * @param ... One or two parameter indexes, separated by a comma
+ *
+ * @see <a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007balloc_005fsize_007d-function-attribute-3220">Function attribute `alloc_size` in GCC's documentation</a>
+ */
+
+#if AV_GCC_VERSION_AT_LEAST(4,3)
+ #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__)))
+#else
+ #define av_alloc_size(...)
+#endif
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup lavu_mem_funcs Heap Management
+ * Functions responsible for allocating, freeing, and copying memory.
+ *
+ * All memory allocation functions have a built-in upper limit of `INT_MAX`
+ * bytes. This may be changed with av_max_alloc(), although exercise extreme
+ * caution when doing so.
+ *
+ * @{
+ */
+
+/**
+ * Allocate a memory block with alignment suitable for all memory accesses
+ * (including vectors if available on the CPU).
+ *
+ * @param size Size in bytes for the memory block to be allocated
+ * @return Pointer to the allocated block, or `NULL` if the block cannot
+ * be allocated
+ * @see av_mallocz()
+ */
+void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1);
+
+/**
+ * Allocate a memory block with alignment suitable for all memory accesses
+ * (including vectors if available on the CPU) and zero all the bytes of the
+ * block.
+ *
+ * @param size Size in bytes for the memory block to be allocated
+ * @return Pointer to the allocated block, or `NULL` if it cannot be allocated
+ * @see av_malloc()
+ */
+void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1);
+
+/**
+ * Allocate a memory block for an array with av_malloc().
+ *
+ * The allocated memory will have size `size * nmemb` bytes.
+ *
+ * @param nmemb Number of element
+ * @param size Size of a single element
+ * @return Pointer to the allocated block, or `NULL` if the block cannot
+ * be allocated
+ * @see av_malloc()
+ */
+av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size);
+
+/**
+ * Allocate a memory block for an array with av_mallocz().
+ *
+ * The allocated memory will have size `size * nmemb` bytes.
+ *
+ * @param nmemb Number of elements
+ * @param size Size of the single element
+ * @return Pointer to the allocated block, or `NULL` if the block cannot
+ * be allocated
+ *
+ * @see av_mallocz()
+ * @see av_malloc_array()
+ */
+av_alloc_size(1, 2) void *av_mallocz_array(size_t nmemb, size_t size);
+
+/**
+ * Non-inlined equivalent of av_mallocz_array().
+ *
+ * Created for symmetry with the calloc() C function.
+ */
+void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib;
+
+/**
+ * Allocate, reallocate, or free a block of memory.
+ *
+ * If `ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is
+ * zero, free the memory block pointed to by `ptr`. Otherwise, expand or
+ * shrink that block of memory according to `size`.
+ *
+ * @param ptr Pointer to a memory block already allocated with
+ * av_realloc() or `NULL`
+ * @param size Size in bytes of the memory block to be allocated or
+ * reallocated
+ *
+ * @return Pointer to a newly-reallocated block or `NULL` if the block
+ * cannot be reallocated or the function is used to free the memory block
+ *
+ * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be
+ * correctly aligned.
+ * @see av_fast_realloc()
+ * @see av_reallocp()
+ */
+void *av_realloc(void *ptr, size_t size) av_alloc_size(2);
+
+/**
+ * Allocate, reallocate, or free a block of memory through a pointer to a
+ * pointer.
+ *
+ * If `*ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is
+ * zero, free the memory block pointed to by `*ptr`. Otherwise, expand or
+ * shrink that block of memory according to `size`.
+ *
+ * @param[in,out] ptr Pointer to a pointer to a memory block already allocated
+ * with av_realloc(), or a pointer to `NULL`. The pointer
+ * is updated on success, or freed on failure.
+ * @param[in] size Size in bytes for the memory block to be allocated or
+ * reallocated
+ *
+ * @return Zero on success, an AVERROR error code on failure
+ *
+ * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be
+ * correctly aligned.
+ */
+av_warn_unused_result
+int av_reallocp(void *ptr, size_t size);
+
+/**
+ * Allocate, reallocate, or free a block of memory.
+ *
+ * This function does the same thing as av_realloc(), except:
+ * - It takes two size arguments and allocates `nelem * elsize` bytes,
+ * after checking the result of the multiplication for integer overflow.
+ * - It frees the input block in case of failure, thus avoiding the memory
+ * leak with the classic
+ * @code{.c}
+ * buf = realloc(buf);
+ * if (!buf)
+ * return -1;
+ * @endcode
+ * pattern.
+ */
+void *av_realloc_f(void *ptr, size_t nelem, size_t elsize);
+
+/**
+ * Allocate, reallocate, or free an array.
+ *
+ * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. If
+ * `nmemb` is zero, free the memory block pointed to by `ptr`.
+ *
+ * @param ptr Pointer to a memory block already allocated with
+ * av_realloc() or `NULL`
+ * @param nmemb Number of elements in the array
+ * @param size Size of the single element of the array
+ *
+ * @return Pointer to a newly-reallocated block or NULL if the block
+ * cannot be reallocated or the function is used to free the memory block
+ *
+ * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be
+ * correctly aligned.
+ * @see av_reallocp_array()
+ */
+av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size);
+
+/**
+ * Allocate, reallocate, or free an array through a pointer to a pointer.
+ *
+ * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. If `nmemb` is
+ * zero, free the memory block pointed to by `*ptr`.
+ *
+ * @param[in,out] ptr Pointer to a pointer to a memory block already
+ * allocated with av_realloc(), or a pointer to `NULL`.
+ * The pointer is updated on success, or freed on failure.
+ * @param[in] nmemb Number of elements
+ * @param[in] size Size of the single element
+ *
+ * @return Zero on success, an AVERROR error code on failure
+ *
+ * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be
+ * correctly aligned.
+ */
+av_alloc_size(2, 3) int av_reallocp_array(void *ptr, size_t nmemb, size_t size);
+
+/**
+ * Reallocate the given buffer if it is not large enough, otherwise do nothing.
+ *
+ * If the given buffer is `NULL`, then a new uninitialized buffer is allocated.
+ *
+ * If the given buffer is not large enough, and reallocation fails, `NULL` is
+ * returned and `*size` is set to 0, but the original buffer is not changed or
+ * freed.
+ *
+ * A typical use pattern follows:
+ *
+ * @code{.c}
+ * uint8_t *buf = ...;
+ * uint8_t *new_buf = av_fast_realloc(buf, &current_size, size_needed);
+ * if (!new_buf) {
+ * // Allocation failed; clean up original buffer
+ * av_freep(&buf);
+ * return AVERROR(ENOMEM);
+ * }
+ * @endcode
+ *
+ * @param[in,out] ptr Already allocated buffer, or `NULL`
+ * @param[in,out] size Pointer to current size of buffer `ptr`. `*size` is
+ * changed to `min_size` in case of success or 0 in
+ * case of failure
+ * @param[in] min_size New size of buffer `ptr`
+ * @return `ptr` if the buffer is large enough, a pointer to newly reallocated
+ * buffer if the buffer was not large enough, or `NULL` in case of
+ * error
+ * @see av_realloc()
+ * @see av_fast_malloc()
+ */
+void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size);
+
+/**
+ * Allocate a buffer, reusing the given one if large enough.
+ *
+ * Contrary to av_fast_realloc(), the current buffer contents might not be
+ * preserved and on error the old buffer is freed, thus no special handling to
+ * avoid memleaks is necessary.
+ *
+ * `*ptr` is allowed to be `NULL`, in which case allocation always happens if
+ * `size_needed` is greater than 0.
+ *
+ * @code{.c}
+ * uint8_t *buf = ...;
+ * av_fast_malloc(&buf, &current_size, size_needed);
+ * if (!buf) {
+ * // Allocation failed; buf already freed
+ * return AVERROR(ENOMEM);
+ * }
+ * @endcode
+ *
+ * @param[in,out] ptr Pointer to pointer to an already allocated buffer.
+ * `*ptr` will be overwritten with pointer to new
+ * buffer on success or `NULL` on failure
+ * @param[in,out] size Pointer to current size of buffer `*ptr`. `*size` is
+ * changed to `min_size` in case of success or 0 in
+ * case of failure
+ * @param[in] min_size New size of buffer `*ptr`
+ * @see av_realloc()
+ * @see av_fast_mallocz()
+ */
+void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size);
+
+/**
+ * Allocate and clear a buffer, reusing the given one if large enough.
+ *
+ * Like av_fast_malloc(), but all newly allocated space is initially cleared.
+ * Reused buffer is not cleared.
+ *
+ * `*ptr` is allowed to be `NULL`, in which case allocation always happens if
+ * `size_needed` is greater than 0.
+ *
+ * @param[in,out] ptr Pointer to pointer to an already allocated buffer.
+ * `*ptr` will be overwritten with pointer to new
+ * buffer on success or `NULL` on failure
+ * @param[in,out] size Pointer to current size of buffer `*ptr`. `*size` is
+ * changed to `min_size` in case of success or 0 in
+ * case of failure
+ * @param[in] min_size New size of buffer `*ptr`
+ * @see av_fast_malloc()
+ */
+void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size);
+
+/**
+ * Free a memory block which has been allocated with a function of av_malloc()
+ * or av_realloc() family.
+ *
+ * @param ptr Pointer to the memory block which should be freed.
+ *
+ * @note `ptr = NULL` is explicitly allowed.
+ * @note It is recommended that you use av_freep() instead, to prevent leaving
+ * behind dangling pointers.
+ * @see av_freep()
+ */
+void av_free(void *ptr);
+
+/**
+ * Free a memory block which has been allocated with a function of av_malloc()
+ * or av_realloc() family, and set the pointer pointing to it to `NULL`.
+ *
+ * @code{.c}
+ * uint8_t *buf = av_malloc(16);
+ * av_free(buf);
+ * // buf now contains a dangling pointer to freed memory, and accidental
+ * // dereference of buf will result in a use-after-free, which may be a
+ * // security risk.
+ *
+ * uint8_t *buf = av_malloc(16);
+ * av_freep(&buf);
+ * // buf is now NULL, and accidental dereference will only result in a
+ * // NULL-pointer dereference.
+ * @endcode
+ *
+ * @param ptr Pointer to the pointer to the memory block which should be freed
+ * @note `*ptr = NULL` is safe and leads to no action.
+ * @see av_free()
+ */
+void av_freep(void *ptr);
+
+/**
+ * Duplicate a string.
+ *
+ * @param s String to be duplicated
+ * @return Pointer to a newly-allocated string containing a
+ * copy of `s` or `NULL` if the string cannot be allocated
+ * @see av_strndup()
+ */
+char *av_strdup(const char *s) av_malloc_attrib;
+
+/**
+ * Duplicate a substring of a string.
+ *
+ * @param s String to be duplicated
+ * @param len Maximum length of the resulting string (not counting the
+ * terminating byte)
+ * @return Pointer to a newly-allocated string containing a
+ * substring of `s` or `NULL` if the string cannot be allocated
+ */
+char *av_strndup(const char *s, size_t len) av_malloc_attrib;
+
+/**
+ * Duplicate a buffer with av_malloc().
+ *
+ * @param p Buffer to be duplicated
+ * @param size Size in bytes of the buffer copied
+ * @return Pointer to a newly allocated buffer containing a
+ * copy of `p` or `NULL` if the buffer cannot be allocated
+ */
+void *av_memdup(const void *p, size_t size);
+
+/**
+ * Overlapping memcpy() implementation.
+ *
+ * @param dst Destination buffer
+ * @param back Number of bytes back to start copying (i.e. the initial size of
+ * the overlapping window); must be > 0
+ * @param cnt Number of bytes to copy; must be >= 0
+ *
+ * @note `cnt > back` is valid, this will copy the bytes we just copied,
+ * thus creating a repeating pattern with a period length of `back`.
+ */
+void av_memcpy_backptr(uint8_t *dst, int back, int cnt);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup lavu_mem_dynarray Dynamic Array
+ *
+ * Utilities to make an array grow when needed.
+ *
+ * Sometimes, the programmer would want to have an array that can grow when
+ * needed. The libavutil dynamic array utilities fill that need.
+ *
+ * libavutil supports two systems of appending elements onto a dynamically
+ * allocated array, the first one storing the pointer to the value in the
+ * array, and the second storing the value directly. In both systems, the
+ * caller is responsible for maintaining a variable containing the length of
+ * the array, as well as freeing of the array after use.
+ *
+ * The first system stores pointers to values in a block of dynamically
+ * allocated memory. Since only pointers are stored, the function does not need
+ * to know the size of the type. Both av_dynarray_add() and
+ * av_dynarray_add_nofree() implement this system.
+ *
+ * @code
+ * type **array = NULL; //< an array of pointers to values
+ * int nb = 0; //< a variable to keep track of the length of the array
+ *
+ * type to_be_added = ...;
+ * type to_be_added2 = ...;
+ *
+ * av_dynarray_add(&array, &nb, &to_be_added);
+ * if (nb == 0)
+ * return AVERROR(ENOMEM);
+ *
+ * av_dynarray_add(&array, &nb, &to_be_added2);
+ * if (nb == 0)
+ * return AVERROR(ENOMEM);
+ *
+ * // Now:
+ * // nb == 2
+ * // &to_be_added == array[0]
+ * // &to_be_added2 == array[1]
+ *
+ * av_freep(&array);
+ * @endcode
+ *
+ * The second system stores the value directly in a block of memory. As a
+ * result, the function has to know the size of the type. av_dynarray2_add()
+ * implements this mechanism.
+ *
+ * @code
+ * type *array = NULL; //< an array of values
+ * int nb = 0; //< a variable to keep track of the length of the array
+ *
+ * type to_be_added = ...;
+ * type to_be_added2 = ...;
+ *
+ * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), NULL);
+ * if (!addr)
+ * return AVERROR(ENOMEM);
+ * memcpy(addr, &to_be_added, sizeof(to_be_added));
+ *
+ * // Shortcut of the above.
+ * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array),
+ * (const void *)&to_be_added2);
+ * if (!addr)
+ * return AVERROR(ENOMEM);
+ *
+ * // Now:
+ * // nb == 2
+ * // to_be_added == array[0]
+ * // to_be_added2 == array[1]
+ *
+ * av_freep(&array);
+ * @endcode
+ *
+ * @{
+ */
+
+/**
+ * Add the pointer to an element to a dynamic array.
+ *
+ * The array to grow is supposed to be an array of pointers to
+ * structures, and the element to add must be a pointer to an already
+ * allocated structure.
+ *
+ * The array is reallocated when its size reaches powers of 2.
+ * Therefore, the amortized cost of adding an element is constant.
+ *
+ * In case of success, the pointer to the array is updated in order to
+ * point to the new grown array, and the number pointed to by `nb_ptr`
+ * is incremented.
+ * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and
+ * `*nb_ptr` is set to 0.
+ *
+ * @param[in,out] tab_ptr Pointer to the array to grow
+ * @param[in,out] nb_ptr Pointer to the number of elements in the array
+ * @param[in] elem Element to add
+ * @see av_dynarray_add_nofree(), av_dynarray2_add()
+ */
+void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem);
+
+/**
+ * Add an element to a dynamic array.
+ *
+ * Function has the same functionality as av_dynarray_add(),
+ * but it doesn't free memory on fails. It returns error code
+ * instead and leave current buffer untouched.
+ *
+ * @return >=0 on success, negative otherwise
+ * @see av_dynarray_add(), av_dynarray2_add()
+ */
+av_warn_unused_result
+int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem);
+
+/**
+ * Add an element of size `elem_size` to a dynamic array.
+ *
+ * The array is reallocated when its number of elements reaches powers of 2.
+ * Therefore, the amortized cost of adding an element is constant.
+ *
+ * In case of success, the pointer to the array is updated in order to
+ * point to the new grown array, and the number pointed to by `nb_ptr`
+ * is incremented.
+ * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and
+ * `*nb_ptr` is set to 0.
+ *
+ * @param[in,out] tab_ptr Pointer to the array to grow
+ * @param[in,out] nb_ptr Pointer to the number of elements in the array
+ * @param[in] elem_size Size in bytes of an element in the array
+ * @param[in] elem_data Pointer to the data of the element to add. If
+ * `NULL`, the space of the newly added element is
+ * allocated but left uninitialized.
+ *
+ * @return Pointer to the data of the element to copy in the newly allocated
+ * space
+ * @see av_dynarray_add(), av_dynarray_add_nofree()
+ */
+void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
+ const uint8_t *elem_data);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup lavu_mem_misc Miscellaneous Functions
+ *
+ * Other functions related to memory allocation.
+ *
+ * @{
+ */
+
+/**
+ * Multiply two `size_t` values checking for overflow.
+ *
+ * @param[in] a,b Operands of multiplication
+ * @param[out] r Pointer to the result of the operation
+ * @return 0 on success, AVERROR(EINVAL) on overflow
+ */
+static inline int av_size_mult(size_t a, size_t b, size_t *r)
+{
+ size_t t = a * b;
+ /* Hack inspired from glibc: don't try the division if nelem and elsize
+ * are both less than sqrt(SIZE_MAX). */
+ if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b)
+ return AVERROR(EINVAL);
+ *r = t;
+ return 0;
+}
+
+/**
+ * Set the maximum size that may be allocated in one block.
+ *
+ * The value specified with this function is effective for all libavutil's @ref
+ * lavu_mem_funcs "heap management functions."
+ *
+ * By default, the max value is defined as `INT_MAX`.
+ *
+ * @param max Value to be set as the new maximum size
+ *
+ * @warning Exercise extreme caution when using this function. Don't touch
+ * this if you do not understand the full consequence of doing so.
+ */
+void av_max_alloc(size_t max);
+
+/**
+ * @}
+ * @}
+ */
+
+#endif /* AVUTIL_MEM_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/pixfmt.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/pixfmt.h
new file mode 100644
index 000000000..e184a5667
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/pixfmt.h
@@ -0,0 +1,529 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_PIXFMT_H
+#define AVUTIL_PIXFMT_H
+
+/**
+ * @file
+ * pixel format definitions
+ */
+
+#include "libavutil/avconfig.h"
+#include "version.h"
+
+#define AVPALETTE_SIZE 1024
+#define AVPALETTE_COUNT 256
+
+/**
+ * Pixel format.
+ *
+ * @note
+ * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA
+ * color is put together as:
+ * (A << 24) | (R << 16) | (G << 8) | B
+ * This is stored as BGRA on little-endian CPU architectures and ARGB on
+ * big-endian CPUs.
+ *
+ * @par
+ * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized
+ * image data is stored in AVFrame.data[0]. The palette is transported in
+ * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is
+ * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is
+ * also endian-specific). Note also that the individual RGB32 palette
+ * components stored in AVFrame.data[1] should be in the range 0..255.
+ * This is important as many custom PAL8 video codecs that were designed
+ * to run on the IBM VGA graphics adapter use 6-bit palette components.
+ *
+ * @par
+ * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like
+ * for pal8. This palette is filled in automatically by the function
+ * allocating the picture.
+ */
+enum AVPixelFormat {
+ AV_PIX_FMT_NONE = -1,
+ AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+ AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
+ AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB...
+ AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR...
+ AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+ AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
+ AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
+ AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
+ AV_PIX_FMT_GRAY8, ///< Y , 8bpp
+ AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
+ AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
+ AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette
+ AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range
+ AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range
+ AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range
+ AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
+ AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
+ AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
+ AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
+ AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
+ AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
+ AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
+ AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb)
+ AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
+ AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped
+
+ AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
+ AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
+ AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
+ AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
+
+ AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian
+ AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian
+ AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
+ AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
+ AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
+ AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian
+ AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian
+
+ AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
+ AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
+ AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
+ AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
+
+ AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
+ AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
+ AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined
+ AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined
+
+#if FF_API_VAAPI
+ /** @name Deprecated pixel formats */
+ /**@{*/
+ AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
+ AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
+ AV_PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID
+ /**@}*/
+ AV_PIX_FMT_VAAPI = AV_PIX_FMT_VAAPI_VLD,
+#else
+ /**
+ * Hardware acceleration through VA-API, data[3] contains a
+ * VASurfaceID.
+ */
+ AV_PIX_FMT_VAAPI,
+#endif
+
+ AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
+
+ AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined
+ AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined
+ AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined
+ AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined
+ AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha
+
+ AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8
+ AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8
+
+ AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian
+ AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian
+
+ /**
+ * The following 12 formats have the disadvantage of needing 1 format for each bit depth.
+ * Notice that each 9/10 bits sample is stored in 16 bits with extra padding.
+ * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better.
+ */
+ AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp
+ AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP
+ AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian
+ AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian
+ AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big-endian
+ AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian
+ AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian
+ AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian
+ AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
+ AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
+ AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian
+ AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian
+ AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian
+ AV_PIX_FMT_YUVA422P9LE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian
+ AV_PIX_FMT_YUVA444P9BE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
+ AV_PIX_FMT_YUVA444P9LE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
+ AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)
+ AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
+ AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)
+ AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
+ AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)
+ AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
+ AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)
+ AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
+ AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)
+ AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
+ AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)
+ AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
+
+ AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface
+
+ AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0
+ AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0
+ AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+ AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+
+ AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
+ AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
+ AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
+ AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
+
+ AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
+
+ AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian)
+ AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian)
+
+ AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp
+ AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian
+ AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian
+ /**
+ * HW acceleration through QSV, data[3] contains a pointer to the
+ * mfxFrameSurface1 structure.
+ */
+ AV_PIX_FMT_QSV,
+ /**
+ * HW acceleration though MMAL, data[3] contains a pointer to the
+ * MMAL_BUFFER_HEADER_T structure.
+ */
+ AV_PIX_FMT_MMAL,
+
+ AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
+
+ /**
+ * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers
+ * exactly as for system memory frames.
+ */
+ AV_PIX_FMT_CUDA,
+
+ AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
+ AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
+ AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
+ AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
+
+ AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian
+ AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian
+ AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian
+ AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian
+ AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range
+
+ AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples */
+ AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples */
+ AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples */
+ AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples */
+ AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian */
+ AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian */
+ AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */
+ AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian */
+ AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian */
+ AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian */
+ AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian */
+ AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian */
+
+ AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing
+
+ AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
+ AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian
+ AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
+ AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian
+ AV_PIX_FMT_AYUV64LE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
+ AV_PIX_FMT_AYUV64BE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
+
+ AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox
+
+ AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian
+ AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian
+
+ AV_PIX_FMT_GBRAP12BE, ///< planar GBR 4:4:4:4 48bpp, big-endian
+ AV_PIX_FMT_GBRAP12LE, ///< planar GBR 4:4:4:4 48bpp, little-endian
+
+ AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian
+ AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian
+
+ AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec
+
+ AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian
+ AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian
+ AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian
+ AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian
+
+ AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian
+ AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian
+
+ /**
+ * Hardware surfaces for Direct3D11.
+ *
+ * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11
+ * hwaccel API and filtering support AV_PIX_FMT_D3D11 only.
+ *
+ * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the
+ * texture array index of the frame as intptr_t if the ID3D11Texture2D is
+ * an array texture (or always 0 if it's a normal texture).
+ */
+ AV_PIX_FMT_D3D11,
+
+ AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian
+ AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian
+
+ AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian
+ AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian
+ AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian
+ AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian
+
+ /**
+ * DRM-managed buffers exposed through PRIME buffer sharing.
+ *
+ * data[0] points to an AVDRMFrameDescriptor.
+ */
+ AV_PIX_FMT_DRM_PRIME,
+ /**
+ * Hardware surfaces for OpenCL.
+ *
+ * data[i] contain 2D image objects (typed in C as cl_mem, used
+ * in OpenCL as image2d_t) for each plane of the surface.
+ */
+ AV_PIX_FMT_OPENCL,
+
+ AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
+};
+
+#if AV_HAVE_BIGENDIAN
+# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be
+#else
+# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le
+#endif
+
+#define AV_PIX_FMT_RGB32 AV_PIX_FMT_NE(ARGB, BGRA)
+#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR)
+#define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA)
+#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB)
+#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0)
+#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0)
+
+#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE)
+#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE)
+#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE)
+#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE)
+#define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE)
+#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE)
+#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE)
+#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE)
+#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE)
+#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE)
+#define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE)
+#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE)
+#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE)
+#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE)
+#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE)
+
+#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE)
+#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE)
+#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE)
+#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE)
+#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE)
+#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE)
+#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE)
+#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE)
+#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE)
+#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE)
+#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE)
+#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE)
+#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE)
+#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE)
+#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE)
+#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE)
+#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE)
+
+#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE)
+#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE)
+#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE)
+#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE)
+#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE)
+#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE)
+#define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE)
+#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE)
+
+#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE, BAYER_BGGR16LE)
+#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE, BAYER_RGGB16LE)
+#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE)
+#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE)
+
+#define AV_PIX_FMT_GBRPF32 AV_PIX_FMT_NE(GBRPF32BE, GBRPF32LE)
+#define AV_PIX_FMT_GBRAPF32 AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE)
+
+#define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE)
+#define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE)
+#define AV_PIX_FMT_YUVA444P9 AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE)
+#define AV_PIX_FMT_YUVA420P10 AV_PIX_FMT_NE(YUVA420P10BE, YUVA420P10LE)
+#define AV_PIX_FMT_YUVA422P10 AV_PIX_FMT_NE(YUVA422P10BE, YUVA422P10LE)
+#define AV_PIX_FMT_YUVA444P10 AV_PIX_FMT_NE(YUVA444P10BE, YUVA444P10LE)
+#define AV_PIX_FMT_YUVA420P16 AV_PIX_FMT_NE(YUVA420P16BE, YUVA420P16LE)
+#define AV_PIX_FMT_YUVA422P16 AV_PIX_FMT_NE(YUVA422P16BE, YUVA422P16LE)
+#define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE)
+
+#define AV_PIX_FMT_XYZ12 AV_PIX_FMT_NE(XYZ12BE, XYZ12LE)
+#define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE)
+#define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE)
+#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE)
+#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE)
+
+/**
+ * Chromaticity coordinates of the source primaries.
+ * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.1.
+ */
+enum AVColorPrimaries {
+ AVCOL_PRI_RESERVED0 = 0,
+ AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B
+ AVCOL_PRI_UNSPECIFIED = 2,
+ AVCOL_PRI_RESERVED = 3,
+ AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
+
+ AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
+ AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
+ AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above
+ AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C
+ AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020
+ AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ)
+ AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428,
+ AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3
+ AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3
+ AVCOL_PRI_JEDEC_P22 = 22, ///< JEDEC P22 phosphors
+ AVCOL_PRI_NB ///< Not part of ABI
+};
+
+/**
+ * Color Transfer Characteristic.
+ * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.2.
+ */
+enum AVColorTransferCharacteristic {
+ AVCOL_TRC_RESERVED0 = 0,
+ AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361
+ AVCOL_TRC_UNSPECIFIED = 2,
+ AVCOL_TRC_RESERVED = 3,
+ AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
+ AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG
+ AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC
+ AVCOL_TRC_SMPTE240M = 7,
+ AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics"
+ AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)"
+ AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)"
+ AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4
+ AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut
+ AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)
+ AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system
+ AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system
+ AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems
+ AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084,
+ AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1
+ AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
+ AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
+ AVCOL_TRC_NB ///< Not part of ABI
+};
+
+/**
+ * YUV colorspace type.
+ * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.3.
+ */
+enum AVColorSpace {
+ AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)
+ AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
+ AVCOL_SPC_UNSPECIFIED = 2,
+ AVCOL_SPC_RESERVED = 3,
+ AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
+ AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
+ AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
+ AVCOL_SPC_SMPTE240M = 7, ///< functionally identical to above
+ AVCOL_SPC_YCGCO = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
+ AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO,
+ AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system
+ AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system
+ AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x
+ AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system
+ AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system
+ AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp
+ AVCOL_SPC_NB ///< Not part of ABI
+};
+
+/**
+ * MPEG vs JPEG YUV range.
+ */
+enum AVColorRange {
+ AVCOL_RANGE_UNSPECIFIED = 0,
+ AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges
+ AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges
+ AVCOL_RANGE_NB ///< Not part of ABI
+};
+
+/**
+ * Location of chroma samples.
+ *
+ * Illustration showing the location of the first (top left) chroma sample of the
+ * image, the left shows only luma, the right
+ * shows the location of the chroma sample, the 2 could be imagined to overlay
+ * each other but are drawn separately due to limitations of ASCII
+ *
+ * 1st 2nd 1st 2nd horizontal luma sample positions
+ * v v v v
+ * ______ ______
+ *1st luma line > |X X ... |3 4 X ... X are luma samples,
+ * | |1 2 1-6 are possible chroma positions
+ *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position
+ */
+enum AVChromaLocation {
+ AVCHROMA_LOC_UNSPECIFIED = 0,
+ AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0
+ AVCHROMA_LOC_CENTER = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0
+ AVCHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2
+ AVCHROMA_LOC_TOP = 4,
+ AVCHROMA_LOC_BOTTOMLEFT = 5,
+ AVCHROMA_LOC_BOTTOM = 6,
+ AVCHROMA_LOC_NB ///< Not part of ABI
+};
+
+#endif /* AVUTIL_PIXFMT_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/rational.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/rational.h
new file mode 100644
index 000000000..5c6b67b4e
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/rational.h
@@ -0,0 +1,214 @@
+/*
+ * rational numbers
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @ingroup lavu_math_rational
+ * Utilties for rational number calculation.
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#ifndef AVUTIL_RATIONAL_H
+#define AVUTIL_RATIONAL_H
+
+#include <stdint.h>
+#include <limits.h>
+#include "attributes.h"
+
+/**
+ * @defgroup lavu_math_rational AVRational
+ * @ingroup lavu_math
+ * Rational number calculation.
+ *
+ * While rational numbers can be expressed as floating-point numbers, the
+ * conversion process is a lossy one, so are floating-point operations. On the
+ * other hand, the nature of FFmpeg demands highly accurate calculation of
+ * timestamps. This set of rational number utilities serves as a generic
+ * interface for manipulating rational numbers as pairs of numerators and
+ * denominators.
+ *
+ * Many of the functions that operate on AVRational's have the suffix `_q`, in
+ * reference to the mathematical symbol "ℚ" (Q) which denotes the set of all
+ * rational numbers.
+ *
+ * @{
+ */
+
+/**
+ * Rational number (pair of numerator and denominator).
+ */
+typedef struct AVRational{
+ int num; ///< Numerator
+ int den; ///< Denominator
+} AVRational;
+
+/**
+ * Create an AVRational.
+ *
+ * Useful for compilers that do not support compound literals.
+ *
+ * @note The return value is not reduced.
+ * @see av_reduce()
+ */
+static inline AVRational av_make_q(int num, int den)
+{
+ AVRational r = { num, den };
+ return r;
+}
+
+/**
+ * Compare two rationals.
+ *
+ * @param a First rational
+ * @param b Second rational
+ *
+ * @return One of the following values:
+ * - 0 if `a == b`
+ * - 1 if `a > b`
+ * - -1 if `a < b`
+ * - `INT_MIN` if one of the values is of the form `0 / 0`
+ */
+static inline int av_cmp_q(AVRational a, AVRational b){
+ const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;
+
+ if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1;
+ else if(b.den && a.den) return 0;
+ else if(a.num && b.num) return (a.num>>31) - (b.num>>31);
+ else return INT_MIN;
+}
+
+/**
+ * Convert an AVRational to a `double`.
+ * @param a AVRational to convert
+ * @return `a` in floating-point form
+ * @see av_d2q()
+ */
+static inline double av_q2d(AVRational a){
+ return a.num / (double) a.den;
+}
+
+/**
+ * Reduce a fraction.
+ *
+ * This is useful for framerate calculations.
+ *
+ * @param[out] dst_num Destination numerator
+ * @param[out] dst_den Destination denominator
+ * @param[in] num Source numerator
+ * @param[in] den Source denominator
+ * @param[in] max Maximum allowed values for `dst_num` & `dst_den`
+ * @return 1 if the operation is exact, 0 otherwise
+ */
+int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max);
+
+/**
+ * Multiply two rationals.
+ * @param b First rational
+ * @param c Second rational
+ * @return b*c
+ */
+AVRational av_mul_q(AVRational b, AVRational c) av_const;
+
+/**
+ * Divide one rational by another.
+ * @param b First rational
+ * @param c Second rational
+ * @return b/c
+ */
+AVRational av_div_q(AVRational b, AVRational c) av_const;
+
+/**
+ * Add two rationals.
+ * @param b First rational
+ * @param c Second rational
+ * @return b+c
+ */
+AVRational av_add_q(AVRational b, AVRational c) av_const;
+
+/**
+ * Subtract one rational from another.
+ * @param b First rational
+ * @param c Second rational
+ * @return b-c
+ */
+AVRational av_sub_q(AVRational b, AVRational c) av_const;
+
+/**
+ * Invert a rational.
+ * @param q value
+ * @return 1 / q
+ */
+static av_always_inline AVRational av_inv_q(AVRational q)
+{
+ AVRational r = { q.den, q.num };
+ return r;
+}
+
+/**
+ * Convert a double precision floating point number to a rational.
+ *
+ * In case of infinity, the returned value is expressed as `{1, 0}` or
+ * `{-1, 0}` depending on the sign.
+ *
+ * @param d `double` to convert
+ * @param max Maximum allowed numerator and denominator
+ * @return `d` in AVRational form
+ * @see av_q2d()
+ */
+AVRational av_d2q(double d, int max) av_const;
+
+/**
+ * Find which of the two rationals is closer to another rational.
+ *
+ * @param q Rational to be compared against
+ * @param q1,q2 Rationals to be tested
+ * @return One of the following values:
+ * - 1 if `q1` is nearer to `q` than `q2`
+ * - -1 if `q2` is nearer to `q` than `q1`
+ * - 0 if they have the same distance
+ */
+int av_nearer_q(AVRational q, AVRational q1, AVRational q2);
+
+/**
+ * Find the value in a list of rationals nearest a given reference rational.
+ *
+ * @param q Reference rational
+ * @param q_list Array of rationals terminated by `{0, 0}`
+ * @return Index of the nearest value found in the array
+ */
+int av_find_nearest_q_idx(AVRational q, const AVRational* q_list);
+
+/**
+ * Convert an AVRational to a IEEE 32-bit `float` expressed in fixed-point
+ * format.
+ *
+ * @param q Rational to be converted
+ * @return Equivalent floating-point value, expressed as an unsigned 32-bit
+ * integer.
+ * @note The returned value is platform-indepedant.
+ */
+uint32_t av_q2intfloat(AVRational q);
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_RATIONAL_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/samplefmt.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/samplefmt.h
new file mode 100644
index 000000000..8cd43ae85
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/samplefmt.h
@@ -0,0 +1,272 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_SAMPLEFMT_H
+#define AVUTIL_SAMPLEFMT_H
+
+#include <stdint.h>
+
+#include "avutil.h"
+#include "attributes.h"
+
+/**
+ * @addtogroup lavu_audio
+ * @{
+ *
+ * @defgroup lavu_sampfmts Audio sample formats
+ *
+ * Audio sample format enumeration and related convenience functions.
+ * @{
+ */
+
+/**
+ * Audio sample formats
+ *
+ * - The data described by the sample format is always in native-endian order.
+ * Sample values can be expressed by native C types, hence the lack of a signed
+ * 24-bit sample format even though it is a common raw audio data format.
+ *
+ * - The floating-point formats are based on full volume being in the range
+ * [-1.0, 1.0]. Any values outside this range are beyond full volume level.
+ *
+ * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg
+ * (such as AVFrame in libavcodec) is as follows:
+ *
+ * @par
+ * For planar sample formats, each audio channel is in a separate data plane,
+ * and linesize is the buffer size, in bytes, for a single plane. All data
+ * planes must be the same size. For packed sample formats, only the first data
+ * plane is used, and samples for each channel are interleaved. In this case,
+ * linesize is the buffer size, in bytes, for the 1 plane.
+ *
+ */
+enum AVSampleFormat {
+ AV_SAMPLE_FMT_NONE = -1,
+ AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
+ AV_SAMPLE_FMT_S16, ///< signed 16 bits
+ AV_SAMPLE_FMT_S32, ///< signed 32 bits
+ AV_SAMPLE_FMT_FLT, ///< float
+ AV_SAMPLE_FMT_DBL, ///< double
+
+ AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
+ AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
+ AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
+ AV_SAMPLE_FMT_FLTP, ///< float, planar
+ AV_SAMPLE_FMT_DBLP, ///< double, planar
+ AV_SAMPLE_FMT_S64, ///< signed 64 bits
+ AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar
+
+ AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
+};
+
+/**
+ * Return the name of sample_fmt, or NULL if sample_fmt is not
+ * recognized.
+ */
+const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt);
+
+/**
+ * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE
+ * on error.
+ */
+enum AVSampleFormat av_get_sample_fmt(const char *name);
+
+/**
+ * Return the planar<->packed alternative form of the given sample format, or
+ * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the
+ * requested planar/packed format, the format returned is the same as the
+ * input.
+ */
+enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar);
+
+/**
+ * Get the packed alternative form of the given sample format.
+ *
+ * If the passed sample_fmt is already in packed format, the format returned is
+ * the same as the input.
+ *
+ * @return the packed alternative form of the given sample format or
+ AV_SAMPLE_FMT_NONE on error.
+ */
+enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt);
+
+/**
+ * Get the planar alternative form of the given sample format.
+ *
+ * If the passed sample_fmt is already in planar format, the format returned is
+ * the same as the input.
+ *
+ * @return the planar alternative form of the given sample format or
+ AV_SAMPLE_FMT_NONE on error.
+ */
+enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt);
+
+/**
+ * Generate a string corresponding to the sample format with
+ * sample_fmt, or a header if sample_fmt is negative.
+ *
+ * @param buf the buffer where to write the string
+ * @param buf_size the size of buf
+ * @param sample_fmt the number of the sample format to print the
+ * corresponding info string, or a negative value to print the
+ * corresponding header.
+ * @return the pointer to the filled buffer or NULL if sample_fmt is
+ * unknown or in case of other errors
+ */
+char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt);
+
+/**
+ * Return number of bytes per sample.
+ *
+ * @param sample_fmt the sample format
+ * @return number of bytes per sample or zero if unknown for the given
+ * sample format
+ */
+int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt);
+
+/**
+ * Check if the sample format is planar.
+ *
+ * @param sample_fmt the sample format to inspect
+ * @return 1 if the sample format is planar, 0 if it is interleaved
+ */
+int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt);
+
+/**
+ * Get the required buffer size for the given audio parameters.
+ *
+ * @param[out] linesize calculated linesize, may be NULL
+ * @param nb_channels the number of channels
+ * @param nb_samples the number of samples in a single channel
+ * @param sample_fmt the sample format
+ * @param align buffer size alignment (0 = default, 1 = no alignment)
+ * @return required buffer size, or negative error code on failure
+ */
+int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
+ enum AVSampleFormat sample_fmt, int align);
+
+/**
+ * @}
+ *
+ * @defgroup lavu_sampmanip Samples manipulation
+ *
+ * Functions that manipulate audio samples
+ * @{
+ */
+
+/**
+ * Fill plane data pointers and linesize for samples with sample
+ * format sample_fmt.
+ *
+ * The audio_data array is filled with the pointers to the samples data planes:
+ * for planar, set the start point of each channel's data within the buffer,
+ * for packed, set the start point of the entire buffer only.
+ *
+ * The value pointed to by linesize is set to the aligned size of each
+ * channel's data buffer for planar layout, or to the aligned size of the
+ * buffer for all channels for packed layout.
+ *
+ * The buffer in buf must be big enough to contain all the samples
+ * (use av_samples_get_buffer_size() to compute its minimum size),
+ * otherwise the audio_data pointers will point to invalid data.
+ *
+ * @see enum AVSampleFormat
+ * The documentation for AVSampleFormat describes the data layout.
+ *
+ * @param[out] audio_data array to be filled with the pointer for each channel
+ * @param[out] linesize calculated linesize, may be NULL
+ * @param buf the pointer to a buffer containing the samples
+ * @param nb_channels the number of channels
+ * @param nb_samples the number of samples in a single channel
+ * @param sample_fmt the sample format
+ * @param align buffer size alignment (0 = default, 1 = no alignment)
+ * @return >=0 on success or a negative error code on failure
+ * @todo return minimum size in bytes required for the buffer in case
+ * of success at the next bump
+ */
+int av_samples_fill_arrays(uint8_t **audio_data, int *linesize,
+ const uint8_t *buf,
+ int nb_channels, int nb_samples,
+ enum AVSampleFormat sample_fmt, int align);
+
+/**
+ * Allocate a samples buffer for nb_samples samples, and fill data pointers and
+ * linesize accordingly.
+ * The allocated samples buffer can be freed by using av_freep(&audio_data[0])
+ * Allocated data will be initialized to silence.
+ *
+ * @see enum AVSampleFormat
+ * The documentation for AVSampleFormat describes the data layout.
+ *
+ * @param[out] audio_data array to be filled with the pointer for each channel
+ * @param[out] linesize aligned size for audio buffer(s), may be NULL
+ * @param nb_channels number of audio channels
+ * @param nb_samples number of samples per channel
+ * @param align buffer size alignment (0 = default, 1 = no alignment)
+ * @return >=0 on success or a negative error code on failure
+ * @todo return the size of the allocated buffer in case of success at the next bump
+ * @see av_samples_fill_arrays()
+ * @see av_samples_alloc_array_and_samples()
+ */
+int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels,
+ int nb_samples, enum AVSampleFormat sample_fmt, int align);
+
+/**
+ * Allocate a data pointers array, samples buffer for nb_samples
+ * samples, and fill data pointers and linesize accordingly.
+ *
+ * This is the same as av_samples_alloc(), but also allocates the data
+ * pointers array.
+ *
+ * @see av_samples_alloc()
+ */
+int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels,
+ int nb_samples, enum AVSampleFormat sample_fmt, int align);
+
+/**
+ * Copy samples from src to dst.
+ *
+ * @param dst destination array of pointers to data planes
+ * @param src source array of pointers to data planes
+ * @param dst_offset offset in samples at which the data will be written to dst
+ * @param src_offset offset in samples at which the data will be read from src
+ * @param nb_samples number of samples to be copied
+ * @param nb_channels number of audio channels
+ * @param sample_fmt audio sample format
+ */
+int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset,
+ int src_offset, int nb_samples, int nb_channels,
+ enum AVSampleFormat sample_fmt);
+
+/**
+ * Fill an audio buffer with silence.
+ *
+ * @param audio_data array of pointers to data planes
+ * @param offset offset in samples at which to start filling
+ * @param nb_samples number of samples to fill
+ * @param nb_channels number of audio channels
+ * @param sample_fmt audio sample format
+ */
+int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples,
+ int nb_channels, enum AVSampleFormat sample_fmt);
+
+/**
+ * @}
+ * @}
+ */
+#endif /* AVUTIL_SAMPLEFMT_H */
diff --git a/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/version.h b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/version.h
new file mode 100644
index 000000000..3a63e6355
--- /dev/null
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/include/libavutil/version.h
@@ -0,0 +1,139 @@
+/*
+ * copyright (c) 2003 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @ingroup lavu
+ * Libavutil version macros
+ */
+
+#ifndef AVUTIL_VERSION_H
+#define AVUTIL_VERSION_H
+
+#include "macros.h"
+
+/**
+ * @addtogroup version_utils
+ *
+ * Useful to check and match library version in order to maintain
+ * backward compatibility.
+ *
+ * The FFmpeg libraries follow a versioning sheme very similar to
+ * Semantic Versioning (http://semver.org/)
+ * The difference is that the component called PATCH is called MICRO in FFmpeg
+ * and its value is reset to 100 instead of 0 to keep it above or equal to 100.
+ * Also we do not increase MICRO for every bugfix or change in git master.
+ *
+ * Prior to FFmpeg 3.2 point releases did not change any lib version number to
+ * avoid aliassing different git master checkouts.
+ * Starting with FFmpeg 3.2, the released library versions will occupy
+ * a separate MAJOR.MINOR that is not used on the master development branch.
+ * That is if we branch a release of master 55.10.123 we will bump to 55.11.100
+ * for the release and master will continue at 55.12.100 after it. Each new
+ * point release will then bump the MICRO improving the usefulness of the lib
+ * versions.
+ *
+ * @{
+ */
+
+#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c))
+#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c
+#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c)
+
+/**
+ * Extract version components from the full ::AV_VERSION_INT int as returned
+ * by functions like ::avformat_version() and ::avcodec_version()
+ */
+#define AV_VERSION_MAJOR(a) ((a) >> 16)
+#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8)
+#define AV_VERSION_MICRO(a) ((a) & 0xFF)
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup lavu_ver Version and Build diagnostics
+ *
+ * Macros and function useful to check at compiletime and at runtime
+ * which version of libavutil is in use.
+ *
+ * @{
+ */
+
+#define LIBAVUTIL_VERSION_MAJOR 56
+#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MICRO 100
+
+#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
+ LIBAVUTIL_VERSION_MINOR, \
+ LIBAVUTIL_VERSION_MICRO)
+#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \
+ LIBAVUTIL_VERSION_MINOR, \
+ LIBAVUTIL_VERSION_MICRO)
+#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT
+
+#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION)
+
+/**
+ * @defgroup lavu_depr_guards Deprecation Guards
+ * FF_API_* defines may be placed below to indicate public API that will be
+ * dropped at a future version bump. The defines themselves are not part of
+ * the public API and may change, break or disappear at any time.
+ *
+ * @note, when bumping the major version it is recommended to manually
+ * disable each FF_API_* in its own commit instead of disabling them all
+ * at once through the bump. This improves the git bisect-ability of the change.
+ *
+ * @{
+ */
+
+#ifndef FF_API_VAAPI
+#define FF_API_VAAPI (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
+#ifndef FF_API_FRAME_QP
+#define FF_API_FRAME_QP (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
+#ifndef FF_API_PLUS1_MINUS1
+#define FF_API_PLUS1_MINUS1 (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
+#ifndef FF_API_ERROR_FRAME
+#define FF_API_ERROR_FRAME (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
+#ifndef FF_API_PKT_PTS
+#define FF_API_PKT_PTS (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
+#ifndef FF_API_CRYPTO_SIZE_T
+#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
+#ifndef FF_API_FRAME_GET_SET
+#define FF_API_FRAME_GET_SET (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
+#ifndef FF_API_PSEUDOPAL
+#define FF_API_PSEUDOPAL (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
+
+
+/**
+ * @}
+ * @}
+ */
+
+#endif /* AVUTIL_VERSION_H */
diff --git a/dom/speakermanager/moz.build b/dom/media/platforms/ffmpeg/ffmpeg58/moz.build
index 22ed849fb..6bd5db8d7 100644
--- a/dom/speakermanager/moz.build
+++ b/dom/media/platforms/ffmpeg/ffmpeg58/moz.build
@@ -4,20 +4,22 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
-
-EXPORTS += [
- 'SpeakerManager.h',
- 'SpeakerManagerService.h',
- 'SpeakerManagerServiceChild.h',
-]
-
UNIFIED_SOURCES += [
- 'SpeakerManager.cpp',
- 'SpeakerManagerService.cpp',
- 'SpeakerManagerServiceChild.cpp',
+ '../FFmpegAudioDecoder.cpp',
+ '../FFmpegDataDecoder.cpp',
+ '../FFmpegDecoderModule.cpp',
+ '../FFmpegVideoDecoder.cpp',
+]
+LOCAL_INCLUDES += [
+ '..',
+ 'include',
]
-include('/ipc/chromium/chromium-config.mozbuild')
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += [ '-Wno-deprecated-declarations' ]
+if CONFIG['CLANG_CXX']:
+ CXXFLAGS += [
+ '-Wno-unknown-attributes',
+ ]
FINAL_LIBRARY = 'xul'
diff --git a/dom/media/platforms/ffmpeg/moz.build b/dom/media/platforms/ffmpeg/moz.build
index 604e445aa..af96fb521 100644
--- a/dom/media/platforms/ffmpeg/moz.build
+++ b/dom/media/platforms/ffmpeg/moz.build
@@ -13,6 +13,7 @@ DIRS += [
'libav54',
'libav55',
'ffmpeg57',
+ 'ffmpeg58',
]
UNIFIED_SOURCES += [
diff --git a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp b/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
deleted file mode 100644
index 0bc3fbea9..000000000
--- a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "MediaCodecProxy.h"
-#include <OMX_IVCommon.h>
-#include <gui/Surface.h>
-#include <ICrypto.h>
-#include "GonkAudioDecoderManager.h"
-#include "MediaDecoderReader.h"
-#include "VideoUtils.h"
-#include "nsTArray.h"
-#include "mozilla/Logging.h"
-#include "stagefright/MediaBuffer.h"
-#include "stagefright/MetaData.h"
-#include "stagefright/MediaErrors.h"
-#include <stagefright/foundation/AMessage.h>
-#include <stagefright/foundation/ALooper.h>
-#include "media/openmax/OMX_Audio.h"
-#include "MediaData.h"
-#include "MediaInfo.h"
-
-#define CODECCONFIG_TIMEOUT_US 10000LL
-#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL
-
-#include <android/log.h>
-#define GADM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkAudioDecoderManager", __VA_ARGS__)
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-
-using namespace android;
-typedef android::MediaCodecProxy MediaCodecProxy;
-
-namespace mozilla {
-
-GonkAudioDecoderManager::GonkAudioDecoderManager(const AudioInfo& aConfig)
- : mAudioChannels(aConfig.mChannels)
- , mAudioRate(aConfig.mRate)
- , mAudioProfile(aConfig.mProfile)
- , mAudioCompactor(mAudioQueue)
-{
- MOZ_COUNT_CTOR(GonkAudioDecoderManager);
- MOZ_ASSERT(mAudioChannels);
- mCodecSpecificData = aConfig.mCodecSpecificConfig;
- mMimeType = aConfig.mMimeType;
-}
-
-GonkAudioDecoderManager::~GonkAudioDecoderManager()
-{
- MOZ_COUNT_DTOR(GonkAudioDecoderManager);
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkAudioDecoderManager::Init()
-{
- if (InitMediaCodecProxy()) {
- return InitPromise::CreateAndResolve(TrackType::kAudioTrack, __func__);
- } else {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-}
-
-bool
-GonkAudioDecoderManager::InitMediaCodecProxy()
-{
- status_t rv = OK;
- if (!InitLoopers(MediaData::AUDIO_DATA)) {
- return false;
- }
-
- mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false);
- if (!mDecoder.get()) {
- return false;
- }
- if (!mDecoder->AllocateAudioMediaCodec())
- {
- mDecoder = nullptr;
- return false;
- }
- sp<AMessage> format = new AMessage;
- // Fixed values
- GADM_LOG("Configure audio mime type:%s, chan no:%d, sample-rate:%d, profile:%d",
- mMimeType.get(), mAudioChannels, mAudioRate, mAudioProfile);
- format->setString("mime", mMimeType.get());
- format->setInt32("channel-count", mAudioChannels);
- format->setInt32("sample-rate", mAudioRate);
- format->setInt32("aac-profile", mAudioProfile);
- status_t err = mDecoder->configure(format, nullptr, nullptr, 0);
- if (err != OK || !mDecoder->Prepare()) {
- return false;
- }
-
- if (mMimeType.EqualsLiteral("audio/mp4a-latm")) {
- rv = mDecoder->Input(mCodecSpecificData->Elements(), mCodecSpecificData->Length(), 0,
- android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
- CODECCONFIG_TIMEOUT_US);
- }
-
- if (rv == OK) {
- return true;
- } else {
- GADM_LOG("Failed to input codec specific data!");
- return false;
- }
-}
-
-nsresult
-GonkAudioDecoderManager::CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset)
-{
- if (!(aBuffer != nullptr && aBuffer->data() != nullptr)) {
- GADM_LOG("Audio Buffer is not valid!");
- return NS_ERROR_UNEXPECTED;
- }
-
- int64_t timeUs;
- if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- if (aBuffer->range_length() == 0) {
- // Some decoders may return spurious empty buffers that we just want to ignore
- // quoted from Android's AwesomePlayer.cpp
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- if (mLastTime > timeUs) {
- GADM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
- MOZ_ASSERT(false);
- return NS_ERROR_NOT_AVAILABLE;
- }
- mLastTime = timeUs;
-
- const uint8_t *data = static_cast<const uint8_t*>(aBuffer->data());
- size_t dataOffset = aBuffer->range_offset();
- size_t size = aBuffer->range_length();
-
- uint32_t frames = size / (2 * mAudioChannels);
-
- CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
- if (!duration.isValid()) {
- return NS_ERROR_UNEXPECTED;
- }
-
- typedef AudioCompactor::NativeCopy OmxCopy;
- mAudioCompactor.Push(aStreamOffset,
- timeUs,
- mAudioRate,
- frames,
- mAudioChannels,
- OmxCopy(data+dataOffset,
- size,
- mAudioChannels));
- return NS_OK;
-}
-
-nsresult
-GonkAudioDecoderManager::Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutData)
-{
- aOutData = nullptr;
- if (mAudioQueue.GetSize() > 0) {
- aOutData = mAudioQueue.PopFront();
- return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK;
- }
-
- status_t err;
- MediaBuffer* audioBuffer = nullptr;
- err = mDecoder->Output(&audioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
- AutoReleaseMediaBuffer a(audioBuffer, mDecoder.get());
-
- switch (err) {
- case OK:
- {
- nsresult rv = CreateAudioData(audioBuffer, aStreamOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- break;
- }
- case android::INFO_FORMAT_CHANGED:
- {
- // If the format changed, update our cached info.
- GADM_LOG("Decoder format changed");
- sp<AMessage> audioCodecFormat;
-
- if (mDecoder->getOutputFormat(&audioCodecFormat) != OK ||
- audioCodecFormat == nullptr) {
- return NS_ERROR_UNEXPECTED;
- }
-
- int32_t codec_channel_count = 0;
- int32_t codec_sample_rate = 0;
-
- if (!audioCodecFormat->findInt32("channel-count", &codec_channel_count) ||
- !audioCodecFormat->findInt32("sample-rate", &codec_sample_rate)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- // Update AudioInfo
- AudioConfig::ChannelLayout layout(codec_channel_count);
- if (!layout.IsValid()) {
- return NS_ERROR_FAILURE;
- }
- mAudioChannels = codec_channel_count;
- mAudioRate = codec_sample_rate;
-
- return Output(aStreamOffset, aOutData);
- }
- case android::INFO_OUTPUT_BUFFERS_CHANGED:
- {
- GADM_LOG("Info Output Buffers Changed");
- if (mDecoder->UpdateOutputBuffers()) {
- return Output(aStreamOffset, aOutData);
- }
- return NS_ERROR_FAILURE;
- }
- case -EAGAIN:
- {
- return NS_ERROR_NOT_AVAILABLE;
- }
- case android::ERROR_END_OF_STREAM:
- {
- GADM_LOG("Got EOS frame!");
- nsresult rv = CreateAudioData(audioBuffer, aStreamOffset);
- NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT);
- MOZ_ASSERT(mAudioQueue.GetSize() > 0);
- mAudioQueue.Finish();
- break;
- }
- case -ETIMEDOUT:
- {
- GADM_LOG("Timeout. can try again next time");
- return NS_ERROR_UNEXPECTED;
- }
- default:
- {
- GADM_LOG("Decoder failed, err=%d", err);
- return NS_ERROR_UNEXPECTED;
- }
- }
-
- if (mAudioQueue.GetSize() > 0) {
- aOutData = mAudioQueue.PopFront();
- // Return NS_ERROR_ABORT at the last sample.
- return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK;
- }
-
- return NS_ERROR_NOT_AVAILABLE;
-}
-
-void
-GonkAudioDecoderManager::ProcessFlush()
-{
- GADM_LOG("FLUSH<<<");
- mAudioQueue.Reset();
- GADM_LOG(">>>FLUSH");
- GonkDecoderManager::ProcessFlush();
-}
-
-void
-GonkAudioDecoderManager::ResetEOS()
-{
- GADM_LOG("ResetEOS(<<<");
- mAudioQueue.Reset();
- GADM_LOG(">>>ResetEOS(");
- GonkDecoderManager::ResetEOS();
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkAudioDecoderManager.h b/dom/media/platforms/gonk/GonkAudioDecoderManager.h
deleted file mode 100644
index aa35d620e..000000000
--- a/dom/media/platforms/gonk/GonkAudioDecoderManager.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkAudioDecoderManager_h_)
-#define GonkAudioDecoderManager_h_
-
-#include "AudioCompactor.h"
-#include "mozilla/RefPtr.h"
-#include "GonkMediaDataDecoder.h"
-
-using namespace android;
-
-namespace android {
-class MOZ_EXPORT MediaBuffer;
-} // namespace android
-
-namespace mozilla {
-
-class GonkAudioDecoderManager : public GonkDecoderManager {
-typedef android::MediaCodecProxy MediaCodecProxy;
-public:
- GonkAudioDecoderManager(const AudioInfo& aConfig);
-
- virtual ~GonkAudioDecoderManager();
-
- RefPtr<InitPromise> Init() override;
-
- nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) override;
-
- void ProcessFlush() override;
- virtual void ResetEOS() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk audio decoder";
- }
-
-private:
- bool InitMediaCodecProxy();
-
- nsresult CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset);
-
- uint32_t mAudioChannels;
- uint32_t mAudioRate;
- const uint32_t mAudioProfile;
-
- MediaQueue<AudioData> mAudioQueue;
-
- AudioCompactor mAudioCompactor;
-
-};
-
-} // namespace mozilla
-
-#endif // GonkAudioDecoderManager_h_
diff --git a/dom/media/platforms/gonk/GonkDecoderModule.cpp b/dom/media/platforms/gonk/GonkDecoderModule.cpp
deleted file mode 100644
index 537bc299c..000000000
--- a/dom/media/platforms/gonk/GonkDecoderModule.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "GonkDecoderModule.h"
-#include "GonkVideoDecoderManager.h"
-#include "GonkAudioDecoderManager.h"
-#include "mozilla/DebugOnly.h"
-#include "GonkMediaDataDecoder.h"
-
-namespace mozilla {
-GonkDecoderModule::GonkDecoderModule()
-{
-}
-
-GonkDecoderModule::~GonkDecoderModule()
-{
-}
-
-already_AddRefed<MediaDataDecoder>
-GonkDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
-{
- RefPtr<MediaDataDecoder> decoder =
- new GonkMediaDataDecoder(new GonkVideoDecoderManager(aParams.mImageContainer, aParams.VideoConfig()),
- aParams.mCallback);
- return decoder.forget();
-}
-
-already_AddRefed<MediaDataDecoder>
-GonkDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
-{
- RefPtr<MediaDataDecoder> decoder =
- new GonkMediaDataDecoder(new GonkAudioDecoderManager(aParams.AudioConfig()),
- aParams.mCallback);
- return decoder.forget();
-}
-
-PlatformDecoderModule::ConversionRequired
-GonkDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- if (aConfig.IsVideo()) {
- return ConversionRequired::kNeedAnnexB;
- } else {
- return ConversionRequired::kNeedNone;
- }
-}
-
-bool
-GonkDecoderModule::SupportsMimeType(const nsACString& aMimeType,
- DecoderDoctorDiagnostics* aDiagnostics) const
-{
- return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
- aMimeType.EqualsLiteral("audio/3gpp") ||
- aMimeType.EqualsLiteral("audio/amr-wb") ||
- aMimeType.EqualsLiteral("audio/mpeg") ||
- aMimeType.EqualsLiteral("video/mp4") ||
- aMimeType.EqualsLiteral("video/mp4v-es") ||
- aMimeType.EqualsLiteral("video/avc") ||
- aMimeType.EqualsLiteral("video/3gpp");
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkDecoderModule.h b/dom/media/platforms/gonk/GonkDecoderModule.h
deleted file mode 100644
index 4f29f0e75..000000000
--- a/dom/media/platforms/gonk/GonkDecoderModule.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkPlatformDecoderModule_h_)
-#define GonkPlatformDecoderModule_h_
-
-#include "PlatformDecoderModule.h"
-
-namespace mozilla {
-
-class GonkDecoderModule : public PlatformDecoderModule {
-public:
- GonkDecoderModule();
- virtual ~GonkDecoderModule();
-
- // Decode thread.
- already_AddRefed<MediaDataDecoder>
- CreateVideoDecoder(const CreateDecoderParams& aParams) override;
-
- // Decode thread.
- already_AddRefed<MediaDataDecoder>
- CreateAudioDecoder(const CreateDecoderParams& aParams) override;
-
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override;
-
- bool SupportsMimeType(const nsACString& aMimeType,
- DecoderDoctorDiagnostics* aDiagnostics) const override;
-
-};
-
-} // namespace mozilla
-
-#endif
diff --git a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp b/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp
deleted file mode 100644
index 6d59d72e1..000000000
--- a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "GonkMediaDataDecoder.h"
-#include "VideoUtils.h"
-#include "nsTArray.h"
-#include "MediaCodecProxy.h"
-
-#include <stagefright/foundation/ADebug.h>
-
-#include "mozilla/Logging.h"
-#include <android/log.h>
-#define GMDD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkMediaDataDecoder", __VA_ARGS__)
-#define INPUT_TIMEOUT_US 0LL // Don't wait for buffer if none is available.
-#define MIN_QUEUED_SAMPLES 2
-
-#ifdef DEBUG
-#include <utils/AndroidThreads.h>
-#endif
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-
-using namespace android;
-
-namespace mozilla {
-
-bool
-GonkDecoderManager::InitLoopers(MediaData::Type aType)
-{
- MOZ_ASSERT(mDecodeLooper.get() == nullptr && mTaskLooper.get() == nullptr);
- MOZ_ASSERT(aType == MediaData::VIDEO_DATA || aType == MediaData::AUDIO_DATA);
-
- const char* suffix = (aType == MediaData::VIDEO_DATA ? "video" : "audio");
- mDecodeLooper = new ALooper;
- android::AString name("MediaCodecProxy/");
- name.append(suffix);
- mDecodeLooper->setName(name.c_str());
-
- mTaskLooper = new ALooper;
- name.setTo("GonkDecoderManager/");
- name.append(suffix);
- mTaskLooper->setName(name.c_str());
- mTaskLooper->registerHandler(this);
-
-#ifdef DEBUG
- sp<AMessage> findThreadId(new AMessage(kNotifyFindLooperId, id()));
- findThreadId->post();
-#endif
-
- return mDecodeLooper->start() == OK && mTaskLooper->start() == OK;
-}
-
-nsresult
-GonkDecoderManager::Input(MediaRawData* aSample)
-{
- RefPtr<MediaRawData> sample;
-
- if (aSample) {
- sample = aSample;
- } else {
- // It means EOS with empty sample.
- sample = new MediaRawData();
- }
- {
- MutexAutoLock lock(mMutex);
- mQueuedSamples.AppendElement(sample);
- }
-
- sp<AMessage> input = new AMessage(kNotifyProcessInput, id());
- if (!aSample) {
- input->setInt32("input-eos", 1);
- }
- input->post();
- return NS_OK;
-}
-
-int32_t
-GonkDecoderManager::ProcessQueuedSamples()
-{
- MOZ_ASSERT(OnTaskLooper());
-
- MutexAutoLock lock(mMutex);
- status_t rv;
- while (mQueuedSamples.Length()) {
- RefPtr<MediaRawData> data = mQueuedSamples.ElementAt(0);
- rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
- data->Size(),
- data->mTime,
- 0,
- INPUT_TIMEOUT_US);
- if (rv == OK) {
- mQueuedSamples.RemoveElementAt(0);
- mWaitOutput.AppendElement(WaitOutputInfo(data->mOffset, data->mTime,
- /* eos */ data->Data() == nullptr));
- } else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
- // In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
- // buffer on time.
- break;
- } else {
- return rv;
- }
- }
- return mQueuedSamples.Length();
-}
-
-nsresult
-GonkDecoderManager::Flush()
-{
- if (mDecoder == nullptr) {
- GMDD_LOG("Decoder is not initialized");
- return NS_ERROR_UNEXPECTED;
- }
-
- if (!mInitPromise.IsEmpty()) {
- return NS_OK;
- }
-
- {
- MutexAutoLock lock(mMutex);
- mQueuedSamples.Clear();
- }
-
- MonitorAutoLock lock(mFlushMonitor);
- mIsFlushing = true;
- sp<AMessage> flush = new AMessage(kNotifyProcessFlush, id());
- flush->post();
- while (mIsFlushing) {
- lock.Wait();
- }
- return NS_OK;
-}
-
-nsresult
-GonkDecoderManager::Shutdown()
-{
- if (mDecoder.get()) {
- mDecoder->stop();
- mDecoder->ReleaseMediaResources();
- mDecoder = nullptr;
- }
-
- mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
-
- return NS_OK;
-}
-
-size_t
-GonkDecoderManager::NumQueuedSamples()
-{
- MutexAutoLock lock(mMutex);
- return mQueuedSamples.Length();
-}
-
-void
-GonkDecoderManager::ProcessInput(bool aEndOfStream)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- status_t rv = ProcessQueuedSamples();
- if (rv >= 0) {
- if (!aEndOfStream && rv <= MIN_QUEUED_SAMPLES) {
- mDecodeCallback->InputExhausted();
- }
-
- if (mToDo.get() == nullptr) {
- mToDo = new AMessage(kNotifyDecoderActivity, id());
- if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- mDecoder->requestActivityNotification(mToDo);
- } else if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- } else {
- GMDD_LOG("input processed: error#%d", rv);
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
-}
-
-void
-GonkDecoderManager::ProcessFlush()
-{
- MOZ_ASSERT(OnTaskLooper());
-
- mLastTime = INT64_MIN;
- MonitorAutoLock lock(mFlushMonitor);
- mWaitOutput.Clear();
- if (mDecoder->flush() != OK) {
- GMDD_LOG("flush error");
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
- mIsFlushing = false;
- lock.NotifyAll();
-}
-
-// Use output timestamp to determine which output buffer is already returned
-// and remove corresponding info, except for EOS, from the waiting list.
-// This method handles the cases that audio decoder sends multiple output
-// buffers for one input.
-void
-GonkDecoderManager::UpdateWaitingList(int64_t aForgetUpTo)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- size_t i;
- for (i = 0; i < mWaitOutput.Length(); i++) {
- const auto& item = mWaitOutput.ElementAt(i);
- if (item.mEOS || item.mTimestamp > aForgetUpTo) {
- break;
- }
- }
- if (i > 0) {
- mWaitOutput.RemoveElementsAt(0, i);
- }
-}
-
-void
-GonkDecoderManager::ProcessToDo(bool aEndOfStream)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- MOZ_ASSERT(mToDo.get() != nullptr);
- mToDo.clear();
-
- if (NumQueuedSamples() > 0 && ProcessQueuedSamples() < 0) {
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- return;
- }
-
- while (mWaitOutput.Length() > 0) {
- RefPtr<MediaData> output;
- WaitOutputInfo wait = mWaitOutput.ElementAt(0);
- nsresult rv = Output(wait.mOffset, output);
- if (rv == NS_OK) {
- MOZ_ASSERT(output);
- mDecodeCallback->Output(output);
- UpdateWaitingList(output->mTime);
- } else if (rv == NS_ERROR_ABORT) {
- // EOS
- MOZ_ASSERT(mQueuedSamples.IsEmpty());
- if (output) {
- mDecodeCallback->Output(output);
- UpdateWaitingList(output->mTime);
- }
- MOZ_ASSERT(mWaitOutput.Length() == 1);
- mWaitOutput.RemoveElementAt(0);
- mDecodeCallback->DrainComplete();
- ResetEOS();
- return;
- } else if (rv == NS_ERROR_NOT_AVAILABLE) {
- break;
- } else {
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- return;
- }
- }
-
- if (!aEndOfStream && NumQueuedSamples() <= MIN_QUEUED_SAMPLES) {
- mDecodeCallback->InputExhausted();
- // No need to shedule todo task this time because InputExhausted() will
- // cause Input() to be invoked and do it for us.
- return;
- }
-
- if (NumQueuedSamples() || mWaitOutput.Length() > 0) {
- mToDo = new AMessage(kNotifyDecoderActivity, id());
- if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- mDecoder->requestActivityNotification(mToDo);
- }
-}
-
-void
-GonkDecoderManager::ResetEOS()
-{
- // After eos, android::MediaCodec needs to be flushed to receive next input
- mWaitOutput.Clear();
- if (mDecoder->flush() != OK) {
- GMDD_LOG("flush error");
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
-}
-
-void
-GonkDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
-{
- switch (aMessage->what()) {
- case kNotifyProcessInput:
- {
- int32_t eos = 0;
- ProcessInput(aMessage->findInt32("input-eos", &eos) && eos);
- break;
- }
- case kNotifyProcessFlush:
- {
- ProcessFlush();
- break;
- }
- case kNotifyDecoderActivity:
- {
- int32_t eos = 0;
- ProcessToDo(aMessage->findInt32("input-eos", &eos) && eos);
- break;
- }
-#ifdef DEBUG
- case kNotifyFindLooperId:
- {
- mTaskLooperId = androidGetThreadId();
- MOZ_ASSERT(mTaskLooperId);
- break;
- }
-#endif
- default:
- {
- TRESPASS();
- break;
- }
- }
-}
-
-#ifdef DEBUG
-bool
-GonkDecoderManager::OnTaskLooper()
-{
- return androidGetThreadId() == mTaskLooperId;
-}
-#endif
-
-GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
- MediaDataDecoderCallback* aCallback)
- : mManager(aManager)
-{
- MOZ_COUNT_CTOR(GonkMediaDataDecoder);
- mManager->SetDecodeCallback(aCallback);
-}
-
-GonkMediaDataDecoder::~GonkMediaDataDecoder()
-{
- MOZ_COUNT_DTOR(GonkMediaDataDecoder);
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkMediaDataDecoder::Init()
-{
- return mManager->Init();
-}
-
-void
-GonkMediaDataDecoder::Shutdown()
-{
- mManager->Shutdown();
-
- // Because codec allocated runnable and init promise is at reader TaskQueue,
- // so manager needs to be destroyed at reader TaskQueue to prevent racing.
- mManager = nullptr;
-}
-
-// Inserts data into the decoder's pipeline.
-void
-GonkMediaDataDecoder::Input(MediaRawData* aSample)
-{
- mManager->Input(aSample);
-}
-
-void
-GonkMediaDataDecoder::Flush()
-{
- mManager->Flush();
-}
-
-void
-GonkMediaDataDecoder::Drain()
-{
- mManager->Input(nullptr);
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkMediaDataDecoder.h b/dom/media/platforms/gonk/GonkMediaDataDecoder.h
deleted file mode 100644
index bba2a8645..000000000
--- a/dom/media/platforms/gonk/GonkMediaDataDecoder.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkMediaDataDecoder_h_)
-#define GonkMediaDataDecoder_h_
-#include "PlatformDecoderModule.h"
-#include <stagefright/foundation/AHandler.h>
-
-namespace android {
-struct ALooper;
-class MediaBuffer;
-class MediaCodecProxy;
-} // namespace android
-
-namespace mozilla {
-class MediaRawData;
-
-// Manage the data flow from inputting encoded data and outputting decode data.
-class GonkDecoderManager : public android::AHandler {
-public:
- typedef TrackInfo::TrackType TrackType;
- typedef MediaDataDecoder::InitPromise InitPromise;
-
- virtual ~GonkDecoderManager() {}
-
- virtual RefPtr<InitPromise> Init() = 0;
- virtual const char* GetDescriptionName() const = 0;
-
- // Asynchronously send sample into mDecoder. If out of input buffer, aSample
- // will be queued for later re-send.
- nsresult Input(MediaRawData* aSample);
-
- // Flush the queued samples and signal decoder to throw all pending input/output away.
- nsresult Flush();
-
- // Shutdown decoder and rejects the init promise.
- virtual nsresult Shutdown();
-
- // How many samples are waiting for processing.
- size_t NumQueuedSamples();
-
- // Set callback for decoder events, such as requesting more input,
- // returning output, or reporting error.
- void SetDecodeCallback(MediaDataDecoderCallback* aCallback)
- {
- mDecodeCallback = aCallback;
- }
-
-protected:
- GonkDecoderManager()
- : mMutex("GonkDecoderManager")
- , mLastTime(INT64_MIN)
- , mFlushMonitor("GonkDecoderManager::Flush")
- , mIsFlushing(false)
- , mDecodeCallback(nullptr)
- {}
-
- bool InitLoopers(MediaData::Type aType);
-
- void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
-
- // Produces decoded output. It returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
- // when output is not produced yet.
- // If this returns a failure code other than NS_ERROR_NOT_AVAILABLE, an error
- // will be reported through mDecodeCallback.
- virtual nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) = 0;
-
- // Send queued samples to OMX. It returns how many samples are still in
- // queue after processing, or negative error code if failed.
- int32_t ProcessQueuedSamples();
-
- void ProcessInput(bool aEndOfStream);
- virtual void ProcessFlush();
- void ProcessToDo(bool aEndOfStream);
- virtual void ResetEOS();
-
- RefPtr<MediaByteBuffer> mCodecSpecificData;
-
- nsAutoCString mMimeType;
-
- // MediaCodedc's wrapper that performs the decoding.
- android::sp<android::MediaCodecProxy> mDecoder;
- // Looper for mDecoder to run on.
- android::sp<android::ALooper> mDecodeLooper;
- // Looper to run decode tasks such as processing input, output, flush, and
- // recycling output buffers.
- android::sp<android::ALooper> mTaskLooper;
- // Message codes for tasks running on mTaskLooper.
- enum {
- // Decoder will send this to indicate internal state change such as input or
- // output buffers availability. Used to run pending input & output tasks.
- kNotifyDecoderActivity = 'nda ',
- // Signal the decoder to flush.
- kNotifyProcessFlush = 'npf ',
- // Used to process queued samples when there is new input.
- kNotifyProcessInput = 'npi ',
-#ifdef DEBUG
- kNotifyFindLooperId = 'nfli',
-#endif
- };
-
- MozPromiseHolder<InitPromise> mInitPromise;
-
- Mutex mMutex; // Protects mQueuedSamples.
- // A queue that stores the samples waiting to be sent to mDecoder.
- // Empty element means EOS and there shouldn't be any sample be queued after it.
- // Samples are queued in caller's thread and dequeued in mTaskLooper.
- nsTArray<RefPtr<MediaRawData>> mQueuedSamples;
-
- // The last decoded frame presentation time. Only accessed on mTaskLooper.
- int64_t mLastTime;
-
- Monitor mFlushMonitor; // Waits for flushing to complete.
- bool mIsFlushing; // Protected by mFlushMonitor.
-
- // Remembers the notification that is currently waiting for the decoder event
- // to avoid requesting more than one notification at the time, which is
- // forbidden by mDecoder.
- android::sp<android::AMessage> mToDo;
-
- // Stores sample info for output buffer processing later.
- struct WaitOutputInfo {
- WaitOutputInfo(int64_t aOffset, int64_t aTimestamp, bool aEOS)
- : mOffset(aOffset)
- , mTimestamp(aTimestamp)
- , mEOS(aEOS)
- {}
- const int64_t mOffset;
- const int64_t mTimestamp;
- const bool mEOS;
- };
-
- nsTArray<WaitOutputInfo> mWaitOutput;
-
- MediaDataDecoderCallback* mDecodeCallback; // Reports decoder output or error.
-
-private:
- void UpdateWaitingList(int64_t aForgetUpTo);
-
-#ifdef DEBUG
- typedef void* LooperId;
-
- bool OnTaskLooper();
- LooperId mTaskLooperId;
-#endif
-};
-
-class AutoReleaseMediaBuffer
-{
-public:
- AutoReleaseMediaBuffer(android::MediaBuffer* aBuffer, android::MediaCodecProxy* aCodec)
- : mBuffer(aBuffer)
- , mCodec(aCodec)
- {}
-
- ~AutoReleaseMediaBuffer()
- {
- MOZ_ASSERT(mCodec.get());
- if (mBuffer) {
- mCodec->ReleaseMediaBuffer(mBuffer);
- }
- }
-
- android::MediaBuffer* forget()
- {
- android::MediaBuffer* tmp = mBuffer;
- mBuffer = nullptr;
- return tmp;
- }
-
-private:
- android::MediaBuffer* mBuffer;
- android::sp<android::MediaCodecProxy> mCodec;
-};
-
-// Samples are decoded using the GonkDecoder (MediaCodec)
-// created by the GonkDecoderManager. This class implements
-// the higher-level logic that drives mapping the Gonk to the async
-// MediaDataDecoder interface. The specifics of decoding the exact stream
-// type are handled by GonkDecoderManager and the GonkDecoder it creates.
-class GonkMediaDataDecoder : public MediaDataDecoder {
-public:
- GonkMediaDataDecoder(GonkDecoderManager* aDecoderManager,
- MediaDataDecoderCallback* aCallback);
-
- ~GonkMediaDataDecoder();
-
- RefPtr<InitPromise> Init() override;
-
- void Input(MediaRawData* aSample) override;
-
- void Flush() override;
-
- void Drain() override;
-
- void Shutdown() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk decoder";
- }
-
-private:
-
- android::sp<GonkDecoderManager> mManager;
-};
-
-} // namespace mozilla
-
-#endif // GonkMediaDataDecoder_h_
diff --git a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
deleted file mode 100644
index 0c7b3b6af..000000000
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ /dev/null
@@ -1,772 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "MediaCodecProxy.h"
-#include <OMX_IVCommon.h>
-#include <gui/Surface.h>
-#include <ICrypto.h>
-#include "GonkVideoDecoderManager.h"
-#include "GrallocImages.h"
-#include "MediaDecoderReader.h"
-#include "ImageContainer.h"
-#include "VideoUtils.h"
-#include "nsThreadUtils.h"
-#include "Layers.h"
-#include "mozilla/Logging.h"
-#include <stagefright/MediaBuffer.h>
-#include <stagefright/MetaData.h>
-#include <stagefright/MediaErrors.h>
-#include <stagefright/foundation/AString.h>
-#include "GonkNativeWindow.h"
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/TextureClient.h"
-#include "mozilla/layers/TextureClientRecycleAllocator.h"
-#include <cutils/properties.h>
-
-#define CODECCONFIG_TIMEOUT_US 10000LL
-#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL
-
-#include <android/log.h>
-#define GVDM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkVideoDecoderManager", __VA_ARGS__)
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-using namespace mozilla::layers;
-using namespace android;
-typedef android::MediaCodecProxy MediaCodecProxy;
-
-namespace mozilla {
-
-class GonkTextureClientAllocationHelper : public layers::ITextureClientAllocationHelper
-{
-public:
- GonkTextureClientAllocationHelper(uint32_t aGrallocFormat,
- gfx::IntSize aSize)
- : ITextureClientAllocationHelper(gfx::SurfaceFormat::UNKNOWN,
- aSize,
- BackendSelector::Content,
- TextureFlags::DEALLOCATE_CLIENT,
- ALLOC_DISALLOW_BUFFERTEXTURECLIENT)
- , mGrallocFormat(aGrallocFormat)
- {}
-
- already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override
- {
- uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
- android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
- android::GraphicBuffer::USAGE_HW_TEXTURE;
-
- GrallocTextureData* texData = GrallocTextureData::Create(mSize, mGrallocFormat,
- gfx::BackendType::NONE,
- usage, aAllocator->GetTextureForwarder());
- if (!texData) {
- return nullptr;
- }
- sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
- if (!graphicBuffer.get()) {
- return nullptr;
- }
- RefPtr<TextureClient> textureClient =
- TextureClient::CreateWithData(texData, TextureFlags::DEALLOCATE_CLIENT, aAllocator->GetTextureForwarder());
- return textureClient.forget();
- }
-
- bool IsCompatible(TextureClient* aTextureClient) override
- {
- if (!aTextureClient) {
- return false;
- }
- sp<GraphicBuffer> graphicBuffer =
- static_cast<GrallocTextureData*>(aTextureClient->GetInternalData())->GetGraphicBuffer();
- if (!graphicBuffer.get() ||
- static_cast<uint32_t>(graphicBuffer->getPixelFormat()) != mGrallocFormat ||
- aTextureClient->GetSize() != mSize) {
- return false;
- }
- return true;
- }
-
-private:
- uint32_t mGrallocFormat;
-};
-
-GonkVideoDecoderManager::GonkVideoDecoderManager(
- mozilla::layers::ImageContainer* aImageContainer,
- const VideoInfo& aConfig)
- : mConfig(aConfig)
- , mImageContainer(aImageContainer)
- , mColorConverterBufferSize(0)
- , mPendingReleaseItemsLock("GonkVideoDecoderManager::mPendingReleaseItemsLock")
- , mNeedsCopyBuffer(false)
-{
- MOZ_COUNT_CTOR(GonkVideoDecoderManager);
-}
-
-GonkVideoDecoderManager::~GonkVideoDecoderManager()
-{
- MOZ_COUNT_DTOR(GonkVideoDecoderManager);
-}
-
-nsresult
-GonkVideoDecoderManager::Shutdown()
-{
- mVideoCodecRequest.DisconnectIfExists();
- return GonkDecoderManager::Shutdown();
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkVideoDecoderManager::Init()
-{
- mNeedsCopyBuffer = false;
-
- uint32_t maxWidth, maxHeight;
- char propValue[PROPERTY_VALUE_MAX];
- property_get("ro.moz.omx.hw.max_width", propValue, "-1");
- maxWidth = -1 == atoi(propValue) ? MAX_VIDEO_WIDTH : atoi(propValue);
- property_get("ro.moz.omx.hw.max_height", propValue, "-1");
- maxHeight = -1 == atoi(propValue) ? MAX_VIDEO_HEIGHT : atoi(propValue) ;
-
- if (uint32_t(mConfig.mImage.width * mConfig.mImage.height) > maxWidth * maxHeight) {
- GVDM_LOG("Video resolution exceeds hw codec capability");
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- // Validate the container-reported frame and pictureRect sizes. This ensures
- // that our video frame creation code doesn't overflow.
- if (!IsValidVideoRegion(mConfig.mImage, mConfig.ImageRect(), mConfig.mDisplay)) {
- GVDM_LOG("It is not a valid region");
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- mReaderTaskQueue = AbstractThread::GetCurrent()->AsTaskQueue();
- MOZ_ASSERT(mReaderTaskQueue);
-
- if (mDecodeLooper.get() != nullptr) {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- if (!InitLoopers(MediaData::VIDEO_DATA)) {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- RefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
- android::sp<GonkVideoDecoderManager> self = this;
- mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper,
- mConfig.mMimeType.get(),
- false);
-
- uint32_t capability = MediaCodecProxy::kEmptyCapability;
- if (mDecoder->getCapability(&capability) == OK && (capability &
- MediaCodecProxy::kCanExposeGraphicBuffer)) {
-#if ANDROID_VERSION >= 21
- sp<IGonkGraphicBufferConsumer> consumer;
- GonkBufferQueue::createBufferQueue(&mGraphicBufferProducer, &consumer);
- mNativeWindow = new GonkNativeWindow(consumer);
-#else
- mNativeWindow = new GonkNativeWindow();
-#endif
- }
-
- mVideoCodecRequest.Begin(mDecoder->AsyncAllocateVideoMediaCodec()
- ->Then(mReaderTaskQueue, __func__,
- [self] (bool) -> void {
- self->mVideoCodecRequest.Complete();
- self->codecReserved();
- }, [self] (bool) -> void {
- self->mVideoCodecRequest.Complete();
- self->codecCanceled();
- }));
-
- return p;
-}
-
-nsresult
-GonkVideoDecoderManager::CreateVideoData(MediaBuffer* aBuffer,
- int64_t aStreamOffset,
- VideoData **v)
-{
- *v = nullptr;
- RefPtr<VideoData> data;
- int64_t timeUs;
- int32_t keyFrame;
-
- if (aBuffer == nullptr) {
- GVDM_LOG("Video Buffer is not valid!");
- return NS_ERROR_UNEXPECTED;
- }
-
- AutoReleaseMediaBuffer autoRelease(aBuffer, mDecoder.get());
-
- if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- GVDM_LOG("Decoder did not return frame time");
- return NS_ERROR_UNEXPECTED;
- }
-
- if (mLastTime > timeUs) {
- GVDM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
- return NS_ERROR_NOT_AVAILABLE;
- }
- mLastTime = timeUs;
-
- if (aBuffer->range_length() == 0) {
- // Some decoders may return spurious empty buffers that we just want to ignore
- // quoted from Android's AwesomePlayer.cpp
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- if (!aBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
- keyFrame = 0;
- }
-
- gfx::IntRect picture =
- mConfig.ScaledImageRect(mFrameInfo.mWidth, mFrameInfo.mHeight);
- if (aBuffer->graphicBuffer().get()) {
- data = CreateVideoDataFromGraphicBuffer(aBuffer, picture);
- if (data && !mNeedsCopyBuffer) {
- // RecycleCallback() will be responsible for release the buffer.
- autoRelease.forget();
- }
- mNeedsCopyBuffer = false;
- } else {
- data = CreateVideoDataFromDataBuffer(aBuffer, picture);
- }
-
- if (!data) {
- return NS_ERROR_UNEXPECTED;
- }
- // Fill necessary info.
- data->mOffset = aStreamOffset;
- data->mTime = timeUs;
- data->mKeyframe = keyFrame;
-
- data.forget(v);
- return NS_OK;
-}
-
-// Copy pixels from one planar YUV to another.
-static void
-CopyYUV(PlanarYCbCrData& aSource, PlanarYCbCrData& aDestination)
-{
- // Fill Y plane.
- uint8_t* srcY = aSource.mYChannel;
- gfx::IntSize ySize = aSource.mYSize;
- uint8_t* destY = aDestination.mYChannel;
- // Y plane.
- for (int i = 0; i < ySize.height; i++) {
- memcpy(destY, srcY, ySize.width);
- srcY += aSource.mYStride;
- destY += aDestination.mYStride;
- }
-
- // Fill UV plane.
- // Line start
- uint8_t* srcU = aSource.mCbChannel;
- uint8_t* srcV = aSource.mCrChannel;
- uint8_t* destU = aDestination.mCbChannel;
- uint8_t* destV = aDestination.mCrChannel;
-
- gfx::IntSize uvSize = aSource.mCbCrSize;
- for (int i = 0; i < uvSize.height; i++) {
- uint8_t* su = srcU;
- uint8_t* sv = srcV;
- uint8_t* du = destU;
- uint8_t* dv =destV;
- for (int j = 0; j < uvSize.width; j++) {
- *du++ = *su++;
- *dv++ = *sv++;
- // Move to next pixel.
- su += aSource.mCbSkip;
- sv += aSource.mCrSkip;
- du += aDestination.mCbSkip;
- dv += aDestination.mCrSkip;
- }
- // Move to next line.
- srcU += aSource.mCbCrStride;
- srcV += aSource.mCbCrStride;
- destU += aDestination.mCbCrStride;
- destV += aDestination.mCbCrStride;
- }
-}
-
-inline static int
-Align(int aX, int aAlign)
-{
- return (aX + aAlign - 1) & ~(aAlign - 1);
-}
-
-// Venus formats are doucmented in kernel/include/media/msm_media_info.h:
-// * Y_Stride : Width aligned to 128
-// * UV_Stride : Width aligned to 128
-// * Y_Scanlines: Height aligned to 32
-// * UV_Scanlines: Height/2 aligned to 16
-// * Total size = align((Y_Stride * Y_Scanlines
-// * + UV_Stride * UV_Scanlines + 4096), 4096)
-static void
-CopyVenus(uint8_t* aSrc, uint8_t* aDest, uint32_t aWidth, uint32_t aHeight)
-{
- size_t yStride = Align(aWidth, 128);
- uint8_t* s = aSrc;
- uint8_t* d = aDest;
- for (size_t i = 0; i < aHeight; i++) {
- memcpy(d, s, aWidth);
- s += yStride;
- d += yStride;
- }
- size_t uvStride = yStride;
- size_t uvLines = (aHeight + 1) / 2;
- size_t ySize = yStride * Align(aHeight, 32);
- s = aSrc + ySize;
- d = aDest + ySize;
- for (size_t i = 0; i < uvLines; i++) {
- memcpy(d, s, aWidth);
- s += uvStride;
- d += uvStride;
- }
-}
-
-static void
-CopyGraphicBuffer(sp<GraphicBuffer>& aSource, sp<GraphicBuffer>& aDestination)
-{
- void* srcPtr = nullptr;
- aSource->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &srcPtr);
- void* destPtr = nullptr;
- aDestination->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destPtr);
- MOZ_ASSERT(srcPtr && destPtr);
-
- // Build PlanarYCbCrData for source buffer.
- PlanarYCbCrData srcData;
- switch (aSource->getPixelFormat()) {
- case HAL_PIXEL_FORMAT_YV12: {
- // Android YV12 format is defined in system/core/include/system/graphics.h
- srcData.mYChannel = static_cast<uint8_t*>(srcPtr);
- srcData.mYSkip = 0;
- srcData.mYSize.width = aSource->getWidth();
- srcData.mYSize.height = aSource->getHeight();
- srcData.mYStride = aSource->getStride();
- // 4:2:0.
- srcData.mCbCrSize.width = srcData.mYSize.width / 2;
- srcData.mCbCrSize.height = srcData.mYSize.height / 2;
- srcData.mCrChannel = srcData.mYChannel + (srcData.mYStride * srcData.mYSize.height);
- // Aligned to 16 bytes boundary.
- srcData.mCbCrStride = Align(srcData.mYStride / 2, 16);
- srcData.mCrSkip = 0;
- srcData.mCbChannel = srcData.mCrChannel + (srcData.mCbCrStride * srcData.mCbCrSize.height);
- srcData.mCbSkip = 0;
-
- // Build PlanarYCbCrData for destination buffer.
- PlanarYCbCrData destData;
- destData.mYChannel = static_cast<uint8_t*>(destPtr);
- destData.mYSkip = 0;
- destData.mYSize.width = aDestination->getWidth();
- destData.mYSize.height = aDestination->getHeight();
- destData.mYStride = aDestination->getStride();
- // 4:2:0.
- destData.mCbCrSize.width = destData.mYSize.width / 2;
- destData.mCbCrSize.height = destData.mYSize.height / 2;
- destData.mCrChannel = destData.mYChannel + (destData.mYStride * destData.mYSize.height);
- // Aligned to 16 bytes boundary.
- destData.mCbCrStride = Align(destData.mYStride / 2, 16);
- destData.mCrSkip = 0;
- destData.mCbChannel = destData.mCrChannel + (destData.mCbCrStride * destData.mCbCrSize.height);
- destData.mCbSkip = 0;
-
- CopyYUV(srcData, destData);
- break;
- }
- case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
- CopyVenus(static_cast<uint8_t*>(srcPtr),
- static_cast<uint8_t*>(destPtr),
- aSource->getWidth(),
- aSource->getHeight());
- break;
- default:
- NS_ERROR("Unsupported input gralloc image type. Should never be here.");
- }
-
-
- aSource->unlock();
- aDestination->unlock();
-}
-
-already_AddRefed<VideoData>
-GonkVideoDecoderManager::CreateVideoDataFromGraphicBuffer(MediaBuffer* aSource,
- gfx::IntRect& aPicture)
-{
- sp<GraphicBuffer> srcBuffer(aSource->graphicBuffer());
- RefPtr<TextureClient> textureClient;
-
- if (mNeedsCopyBuffer) {
- // Copy buffer contents for bug 1199809.
- if (!mCopyAllocator) {
- RefPtr<layers::ImageBridgeChild> bridge = layers::ImageBridgeChild::GetSingleton();
- mCopyAllocator = new TextureClientRecycleAllocator(bridge);
- }
- if (!mCopyAllocator) {
- GVDM_LOG("Create buffer allocator failed!");
- return nullptr;
- }
-
- gfx::IntSize size(srcBuffer->getWidth(), srcBuffer->getHeight());
- GonkTextureClientAllocationHelper helper(srcBuffer->getPixelFormat(), size);
- textureClient = mCopyAllocator->CreateOrRecycle(helper);
- if (!textureClient) {
- GVDM_LOG("Copy buffer allocation failed!");
- return nullptr;
- }
-
- sp<GraphicBuffer> destBuffer =
- static_cast<GrallocTextureData*>(textureClient->GetInternalData())->GetGraphicBuffer();
-
- CopyGraphicBuffer(srcBuffer, destBuffer);
- } else {
- textureClient = mNativeWindow->getTextureClientFromBuffer(srcBuffer.get());
- textureClient->SetRecycleCallback(GonkVideoDecoderManager::RecycleCallback, this);
- static_cast<GrallocTextureData*>(textureClient->GetInternalData())->SetMediaBuffer(aSource);
- }
-
- RefPtr<VideoData> data =
- VideoData::CreateAndCopyIntoTextureClient(mConfig,
- 0, // Filled later by caller.
- 0, // Filled later by caller.
- 1, // No way to pass sample duration from muxer to
- // OMX codec, so we hardcode the duration here.
- textureClient,
- false, // Filled later by caller.
- -1,
- aPicture);
- return data.forget();
-}
-
-already_AddRefed<VideoData>
-GonkVideoDecoderManager::CreateVideoDataFromDataBuffer(MediaBuffer* aSource, gfx::IntRect& aPicture)
-{
- if (!aSource->data()) {
- GVDM_LOG("No data in Video Buffer!");
- return nullptr;
- }
- uint8_t *yuv420p_buffer = (uint8_t *)aSource->data();
- int32_t stride = mFrameInfo.mStride;
- int32_t slice_height = mFrameInfo.mSliceHeight;
-
- // Converts to OMX_COLOR_FormatYUV420Planar
- if (mFrameInfo.mColorFormat != OMX_COLOR_FormatYUV420Planar) {
- ARect crop;
- crop.top = 0;
- crop.bottom = mFrameInfo.mHeight;
- crop.left = 0;
- crop.right = mFrameInfo.mWidth;
- yuv420p_buffer = GetColorConverterBuffer(mFrameInfo.mWidth, mFrameInfo.mHeight);
- if (mColorConverter.convertDecoderOutputToI420(aSource->data(),
- mFrameInfo.mWidth, mFrameInfo.mHeight, crop, yuv420p_buffer) != OK) {
- GVDM_LOG("Color conversion failed!");
- return nullptr;
- }
- stride = mFrameInfo.mWidth;
- slice_height = mFrameInfo.mHeight;
- }
-
- size_t yuv420p_y_size = stride * slice_height;
- size_t yuv420p_u_size = ((stride + 1) / 2) * ((slice_height + 1) / 2);
- uint8_t *yuv420p_y = yuv420p_buffer;
- uint8_t *yuv420p_u = yuv420p_y + yuv420p_y_size;
- uint8_t *yuv420p_v = yuv420p_u + yuv420p_u_size;
-
- VideoData::YCbCrBuffer b;
- b.mPlanes[0].mData = yuv420p_y;
- b.mPlanes[0].mWidth = mFrameInfo.mWidth;
- b.mPlanes[0].mHeight = mFrameInfo.mHeight;
- b.mPlanes[0].mStride = stride;
- b.mPlanes[0].mOffset = 0;
- b.mPlanes[0].mSkip = 0;
-
- b.mPlanes[1].mData = yuv420p_u;
- b.mPlanes[1].mWidth = (mFrameInfo.mWidth + 1) / 2;
- b.mPlanes[1].mHeight = (mFrameInfo.mHeight + 1) / 2;
- b.mPlanes[1].mStride = (stride + 1) / 2;
- b.mPlanes[1].mOffset = 0;
- b.mPlanes[1].mSkip = 0;
-
- b.mPlanes[2].mData = yuv420p_v;
- b.mPlanes[2].mWidth =(mFrameInfo.mWidth + 1) / 2;
- b.mPlanes[2].mHeight = (mFrameInfo.mHeight + 1) / 2;
- b.mPlanes[2].mStride = (stride + 1) / 2;
- b.mPlanes[2].mOffset = 0;
- b.mPlanes[2].mSkip = 0;
-
- RefPtr<VideoData> data =
- VideoData::CreateAndCopyData(mConfig,
- mImageContainer,
- 0, // Filled later by caller.
- 0, // Filled later by caller.
- 1, // We don't know the duration.
- b,
- 0, // Filled later by caller.
- -1,
- aPicture);
-
- return data.forget();
-}
-
-bool
-GonkVideoDecoderManager::SetVideoFormat()
-{
- // read video metadata from MediaCodec
- sp<AMessage> codecFormat;
- if (mDecoder->getOutputFormat(&codecFormat) == OK) {
- AString mime;
- int32_t width = 0;
- int32_t height = 0;
- int32_t stride = 0;
- int32_t slice_height = 0;
- int32_t color_format = 0;
- int32_t crop_left = 0;
- int32_t crop_top = 0;
- int32_t crop_right = 0;
- int32_t crop_bottom = 0;
- if (!codecFormat->findString("mime", &mime) ||
- !codecFormat->findInt32("width", &width) ||
- !codecFormat->findInt32("height", &height) ||
- !codecFormat->findInt32("stride", &stride) ||
- !codecFormat->findInt32("slice-height", &slice_height) ||
- !codecFormat->findInt32("color-format", &color_format) ||
- !codecFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
- GVDM_LOG("Failed to find values");
- return false;
- }
- mFrameInfo.mWidth = width;
- mFrameInfo.mHeight = height;
- mFrameInfo.mStride = stride;
- mFrameInfo.mSliceHeight = slice_height;
- mFrameInfo.mColorFormat = color_format;
-
- nsIntSize displaySize(width, height);
- if (!IsValidVideoRegion(mConfig.mDisplay,
- mConfig.ScaledImageRect(width, height),
- displaySize)) {
- GVDM_LOG("It is not a valid region");
- return false;
- }
- return true;
- }
- GVDM_LOG("Fail to get output format");
- return false;
-}
-
-// Blocks until decoded sample is produced by the deoder.
-nsresult
-GonkVideoDecoderManager::Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutData)
-{
- aOutData = nullptr;
- status_t err;
- if (mDecoder == nullptr) {
- GVDM_LOG("Decoder is not inited");
- return NS_ERROR_UNEXPECTED;
- }
- MediaBuffer* outputBuffer = nullptr;
- err = mDecoder->Output(&outputBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
-
- switch (err) {
- case OK:
- {
- RefPtr<VideoData> data;
- nsresult rv = CreateVideoData(outputBuffer, aStreamOffset, getter_AddRefs(data));
- if (rv == NS_ERROR_NOT_AVAILABLE) {
- // Decoder outputs a empty video buffer, try again
- return NS_ERROR_NOT_AVAILABLE;
- } else if (rv != NS_OK || data == nullptr) {
- GVDM_LOG("Failed to create VideoData");
- return NS_ERROR_UNEXPECTED;
- }
- aOutData = data;
- return NS_OK;
- }
- case android::INFO_FORMAT_CHANGED:
- {
- // If the format changed, update our cached info.
- GVDM_LOG("Decoder format changed");
- if (!SetVideoFormat()) {
- return NS_ERROR_UNEXPECTED;
- }
- return Output(aStreamOffset, aOutData);
- }
- case android::INFO_OUTPUT_BUFFERS_CHANGED:
- {
- if (mDecoder->UpdateOutputBuffers()) {
- return Output(aStreamOffset, aOutData);
- }
- GVDM_LOG("Fails to update output buffers!");
- return NS_ERROR_FAILURE;
- }
- case -EAGAIN:
- {
-// GVDM_LOG("Need to try again!");
- return NS_ERROR_NOT_AVAILABLE;
- }
- case android::ERROR_END_OF_STREAM:
- {
- GVDM_LOG("Got the EOS frame!");
- RefPtr<VideoData> data;
- nsresult rv = CreateVideoData(outputBuffer, aStreamOffset, getter_AddRefs(data));
- if (rv == NS_ERROR_NOT_AVAILABLE) {
- // For EOS, no need to do any thing.
- return NS_ERROR_ABORT;
- }
- if (rv != NS_OK || data == nullptr) {
- GVDM_LOG("Failed to create video data");
- return NS_ERROR_UNEXPECTED;
- }
- aOutData = data;
- return NS_ERROR_ABORT;
- }
- case -ETIMEDOUT:
- {
- GVDM_LOG("Timeout. can try again next time");
- return NS_ERROR_UNEXPECTED;
- }
- default:
- {
- GVDM_LOG("Decoder failed, err=%d", err);
- return NS_ERROR_UNEXPECTED;
- }
- }
-
- return NS_OK;
-}
-
-void
-GonkVideoDecoderManager::codecReserved()
-{
- if (mInitPromise.IsEmpty()) {
- return;
- }
- GVDM_LOG("codecReserved");
- sp<AMessage> format = new AMessage;
- sp<Surface> surface;
- status_t rv = OK;
- // Fixed values
- GVDM_LOG("Configure video mime type: %s, width:%d, height:%d", mConfig.mMimeType.get(), mConfig.mImage.width, mConfig.mImage.height);
- format->setString("mime", mConfig.mMimeType.get());
- format->setInt32("width", mConfig.mImage.width);
- format->setInt32("height", mConfig.mImage.height);
- // Set the "moz-use-undequeued-bufs" to use the undeque buffers to accelerate
- // the video decoding.
- format->setInt32("moz-use-undequeued-bufs", 1);
- if (mNativeWindow != nullptr) {
-#if ANDROID_VERSION >= 21
- surface = new Surface(mGraphicBufferProducer);
-#else
- surface = new Surface(mNativeWindow->getBufferQueue());
-#endif
- }
- mDecoder->configure(format, surface, nullptr, 0);
- mDecoder->Prepare();
-
- if (mConfig.mMimeType.EqualsLiteral("video/mp4v-es")) {
- rv = mDecoder->Input(mConfig.mCodecSpecificConfig->Elements(),
- mConfig.mCodecSpecificConfig->Length(), 0,
- android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
- CODECCONFIG_TIMEOUT_US);
- }
-
- if (rv != OK) {
- GVDM_LOG("Failed to configure codec!!!!");
- mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- return;
- }
-
- mInitPromise.Resolve(TrackType::kVideoTrack, __func__);
-}
-
-void
-GonkVideoDecoderManager::codecCanceled()
-{
- GVDM_LOG("codecCanceled");
- mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
-}
-
-// Called on GonkDecoderManager::mTaskLooper thread.
-void
-GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
-{
- switch (aMessage->what()) {
- case kNotifyPostReleaseBuffer:
- {
- ReleaseAllPendingVideoBuffers();
- break;
- }
-
- default:
- {
- GonkDecoderManager::onMessageReceived(aMessage);
- break;
- }
- }
-}
-
-uint8_t *
-GonkVideoDecoderManager::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight)
-{
- // Allocate a temporary YUV420Planer buffer.
- size_t yuv420p_y_size = aWidth * aHeight;
- size_t yuv420p_u_size = ((aWidth + 1) / 2) * ((aHeight + 1) / 2);
- size_t yuv420p_v_size = yuv420p_u_size;
- size_t yuv420p_size = yuv420p_y_size + yuv420p_u_size + yuv420p_v_size;
- if (mColorConverterBufferSize != yuv420p_size) {
- mColorConverterBuffer = MakeUnique<uint8_t[]>(yuv420p_size);
- mColorConverterBufferSize = yuv420p_size;
- }
- return mColorConverterBuffer.get();
-}
-
-/* static */
-void
-GonkVideoDecoderManager::RecycleCallback(TextureClient* aClient, void* aClosure)
-{
- MOZ_ASSERT(aClient && !aClient->IsDead());
- GonkVideoDecoderManager* videoManager = static_cast<GonkVideoDecoderManager*>(aClosure);
- GrallocTextureData* client = static_cast<GrallocTextureData*>(aClient->GetInternalData());
- aClient->ClearRecycleCallback();
- FenceHandle handle = aClient->GetAndResetReleaseFenceHandle();
- videoManager->PostReleaseVideoBuffer(client->GetMediaBuffer(), handle);
-}
-
-void GonkVideoDecoderManager::PostReleaseVideoBuffer(
- android::MediaBuffer *aBuffer,
- FenceHandle aReleaseFence)
-{
- {
- MutexAutoLock autoLock(mPendingReleaseItemsLock);
- if (aBuffer) {
- mPendingReleaseItems.AppendElement(ReleaseItem(aBuffer, aReleaseFence));
- }
- }
- sp<AMessage> notify =
- new AMessage(kNotifyPostReleaseBuffer, id());
- notify->post();
-
-}
-
-void GonkVideoDecoderManager::ReleaseAllPendingVideoBuffers()
-{
- nsTArray<ReleaseItem> releasingItems;
- {
- MutexAutoLock autoLock(mPendingReleaseItemsLock);
- releasingItems.AppendElements(mPendingReleaseItems);
- mPendingReleaseItems.Clear();
- }
-
- // Free all pending video buffers without holding mPendingReleaseItemsLock.
- size_t size = releasingItems.Length();
- for (size_t i = 0; i < size; i++) {
- RefPtr<FenceHandle::FdObj> fdObj = releasingItems[i].mReleaseFence.GetAndResetFdObj();
- sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
- fence->waitForever("GonkVideoDecoderManager");
- mDecoder->ReleaseMediaBuffer(releasingItems[i].mBuffer);
- }
- releasingItems.Clear();
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkVideoDecoderManager.h b/dom/media/platforms/gonk/GonkVideoDecoderManager.h
deleted file mode 100644
index 343bb2a5c..000000000
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkVideoDecoderManager_h_)
-#define GonkVideoDecoderManager_h_
-
-#include "nsRect.h"
-#include "GonkMediaDataDecoder.h"
-#include "mozilla/RefPtr.h"
-#include "I420ColorConverterHelper.h"
-#include "MediaCodecProxy.h"
-#include "GonkNativeWindow.h"
-#include "mozilla/layers/FenceUtils.h"
-#include "mozilla/UniquePtr.h"
-#include <ui/Fence.h>
-
-using namespace android;
-
-namespace android {
-class MediaBuffer;
-struct MOZ_EXPORT AString;
-class GonkNativeWindow;
-} // namespace android
-
-namespace mozilla {
-
-namespace layers {
-class TextureClient;
-class TextureClientRecycleAllocator;
-} // namespace mozilla::layers
-
-class GonkVideoDecoderManager : public GonkDecoderManager {
-typedef android::MediaCodecProxy MediaCodecProxy;
-typedef mozilla::layers::TextureClient TextureClient;
-
-public:
- GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
- const VideoInfo& aConfig);
-
- virtual ~GonkVideoDecoderManager();
-
- RefPtr<InitPromise> Init() override;
-
- nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) override;
-
- nsresult Shutdown() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk video decoder";
- }
-
- static void RecycleCallback(TextureClient* aClient, void* aClosure);
-
-protected:
- // Bug 1199809: workaround to avoid sending the graphic buffer by making a
- // copy of output buffer after calling flush(). Bug 1203859 was created to
- // reimplementing Gonk PDM on top of OpenMax IL directly. Its buffer
- // management will work better with Gecko and solve problems like this.
- void ProcessFlush() override
- {
- mNeedsCopyBuffer = true;
- GonkDecoderManager::ProcessFlush();
- }
-
-private:
- struct FrameInfo
- {
- int32_t mWidth = 0;
- int32_t mHeight = 0;
- int32_t mStride = 0;
- int32_t mSliceHeight = 0;
- int32_t mColorFormat = 0;
- int32_t mCropLeft = 0;
- int32_t mCropTop = 0;
- int32_t mCropRight = 0;
- int32_t mCropBottom = 0;
- };
-
- void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
-
- bool SetVideoFormat();
-
- nsresult CreateVideoData(MediaBuffer* aBuffer, int64_t aStreamOffset, VideoData** aOutData);
- already_AddRefed<VideoData> CreateVideoDataFromGraphicBuffer(android::MediaBuffer* aSource,
- gfx::IntRect& aPicture);
- already_AddRefed<VideoData> CreateVideoDataFromDataBuffer(android::MediaBuffer* aSource,
- gfx::IntRect& aPicture);
-
- uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
-
- // For codec resource management
- void codecReserved();
- void codecCanceled();
-
- void ReleaseAllPendingVideoBuffers();
- void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer,
- layers::FenceHandle mReleaseFence);
-
- VideoInfo mConfig;
-
- RefPtr<layers::ImageContainer> mImageContainer;
- RefPtr<layers::TextureClientRecycleAllocator> mCopyAllocator;
-
- MozPromiseRequestHolder<android::MediaCodecProxy::CodecPromise> mVideoCodecRequest;
- FrameInfo mFrameInfo;
-
- // color converter
- android::I420ColorConverterHelper mColorConverter;
- UniquePtr<uint8_t[]> mColorConverterBuffer;
- size_t mColorConverterBufferSize;
-
- android::sp<android::GonkNativeWindow> mNativeWindow;
-#if ANDROID_VERSION >= 21
- android::sp<android::IGraphicBufferProducer> mGraphicBufferProducer;
-#endif
-
- enum {
- kNotifyPostReleaseBuffer = 'nprb',
- };
-
- struct ReleaseItem {
- ReleaseItem(android::MediaBuffer* aBuffer, layers::FenceHandle& aFence)
- : mBuffer(aBuffer)
- , mReleaseFence(aFence) {}
- android::MediaBuffer* mBuffer;
- layers::FenceHandle mReleaseFence;
- };
- nsTArray<ReleaseItem> mPendingReleaseItems;
-
- // The lock protects mPendingReleaseItems.
- Mutex mPendingReleaseItemsLock;
-
- // This TaskQueue should be the same one in mDecodeCallback->OnReaderTaskQueue().
- // It is for codec resource mangement, decoding task should not dispatch to it.
- RefPtr<TaskQueue> mReaderTaskQueue;
-
- // Bug 1199809: do we need to make a copy of output buffer? Used only when
- // the decoder outputs graphic buffers.
- bool mNeedsCopyBuffer;
-};
-
-} // namespace mozilla
-
-#endif // GonkVideoDecoderManager_h_
diff --git a/dom/media/platforms/gonk/moz.build b/dom/media/platforms/gonk/moz.build
deleted file mode 100644
index 014594977..000000000
--- a/dom/media/platforms/gonk/moz.build
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXPORTS += [
- 'GonkAudioDecoderManager.h',
- 'GonkDecoderModule.h',
- 'GonkMediaDataDecoder.h',
- 'GonkVideoDecoderManager.h',
-]
-UNIFIED_SOURCES += [
- 'GonkAudioDecoderManager.cpp',
- 'GonkDecoderModule.cpp',
- 'GonkMediaDataDecoder.cpp',
- 'GonkVideoDecoderManager.cpp',
-]
-LOCAL_INCLUDES += [
- '/dom/media/omx/',
-]
-include('/ipc/chromium/chromium-config.mozbuild')
-
-# Suppress some GCC/clang warnings being treated as errors:
-# - about attributes on forward declarations for types that are already
-# defined, which complains about an important MOZ_EXPORT for android::AString
-# - about multi-character constants which are used in codec-related code
-if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
- CXXFLAGS += [
- '-Wno-error=attributes',
- '-Wno-error=multichar'
- ]
-
-FINAL_LIBRARY = 'xul'
-
-LOCAL_INCLUDES += [
- '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/native/opengl/include',]
-]
diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build
index 310820c91..3fb0cc842 100644
--- a/dom/media/platforms/moz.build
+++ b/dom/media/platforms/moz.build
@@ -70,10 +70,6 @@ if CONFIG['MOZ_APPLEMEDIA']:
'-framework AudioToolbox',
]
-if CONFIG['MOZ_GONK_MEDIACODEC']:
- DEFINES['MOZ_GONK_MEDIACODEC'] = True
- DIRS += ['gonk']
-
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
diff --git a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp b/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp
deleted file mode 100644
index 870566cf5..000000000
--- a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp
+++ /dev/null
@@ -1,667 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GonkOmxPlatformLayer.h"
-
-#include <binder/MemoryDealer.h>
-#include <cutils/properties.h>
-#include <media/IOMX.h>
-#include <media/stagefright/MediaCodecList.h>
-#include <utils/List.h>
-
-#include "mozilla/Monitor.h"
-#include "mozilla/layers/TextureClient.h"
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/TextureClientRecycleAllocator.h"
-
-#include "ImageContainer.h"
-#include "MediaInfo.h"
-#include "OmxDataDecoder.h"
-
-
-#ifdef LOG
-#undef LOG
-#endif
-
-#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("GonkOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
-
-#define CHECK_ERR(err) \
- if (err != OK) { \
- LOG("error %d at %s", err, __func__); \
- return NS_ERROR_FAILURE; \
- } \
-
-// Android proprietary value.
-#define ANDROID_OMX_VIDEO_CodingVP8 (static_cast<OMX_VIDEO_CODINGTYPE>(9))
-
-using namespace android;
-
-namespace mozilla {
-
-// In Gonk, the software component name has prefix "OMX.google". It needs to
-// have a way to use hardware codec first.
-bool IsSoftwareCodec(const char* aComponentName)
-{
- nsAutoCString str(aComponentName);
- return (str.Find(NS_LITERAL_CSTRING("OMX.google.")) == -1 ? false : true);
-}
-
-bool IsInEmulator()
-{
- char propQemu[PROPERTY_VALUE_MAX];
- property_get("ro.kernel.qemu", propQemu, "");
- return !strncmp(propQemu, "1", 1);
-}
-
-class GonkOmxObserver : public BnOMXObserver {
-public:
- void onMessage(const omx_message& aMsg)
- {
- switch (aMsg.type) {
- case omx_message::EVENT:
- {
- sp<GonkOmxObserver> self = this;
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
- if (self->mClient && self->mClient->Event(aMsg.u.event_data.event,
- aMsg.u.event_data.data1,
- aMsg.u.event_data.data2))
- {
- return;
- }
- });
- mTaskQueue->Dispatch(r.forget());
- break;
- }
- case omx_message::EMPTY_BUFFER_DONE:
- {
- sp<GonkOmxObserver> self = this;
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
- if (!self->mPromiseLayer) {
- return;
- }
- BufferData::BufferID id = (BufferData::BufferID)aMsg.u.buffer_data.buffer;
- self->mPromiseLayer->EmptyFillBufferDone(OMX_DirInput, id);
- });
- mTaskQueue->Dispatch(r.forget());
- break;
- }
- case omx_message::FILL_BUFFER_DONE:
- {
- sp<GonkOmxObserver> self = this;
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
- if (!self->mPromiseLayer) {
- return;
- }
-
- // TODO: these codes look a little ugly, it'd be better to improve them.
- RefPtr<BufferData> buf;
- BufferData::BufferID id = (BufferData::BufferID)aMsg.u.extended_buffer_data.buffer;
- buf = self->mPromiseLayer->FindAndRemoveBufferHolder(OMX_DirOutput, id);
- MOZ_RELEASE_ASSERT(buf);
- GonkBufferData* gonkBuffer = static_cast<GonkBufferData*>(buf.get());
-
- // Copy the critical information to local buffer.
- if (gonkBuffer->IsLocalBuffer()) {
- gonkBuffer->mBuffer->nOffset = aMsg.u.extended_buffer_data.range_offset;
- gonkBuffer->mBuffer->nFilledLen = aMsg.u.extended_buffer_data.range_length;
- gonkBuffer->mBuffer->nFlags = aMsg.u.extended_buffer_data.flags;
- gonkBuffer->mBuffer->nTimeStamp = aMsg.u.extended_buffer_data.timestamp;
- }
- self->mPromiseLayer->EmptyFillBufferDone(OMX_DirOutput, buf);
- });
- mTaskQueue->Dispatch(r.forget());
- break;
- }
- default:
- {
- LOG("Unhandle event %d", aMsg.type);
- }
- }
- }
-
- void Shutdown()
- {
- MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
- mPromiseLayer = nullptr;
- mClient = nullptr;
- }
-
- GonkOmxObserver(TaskQueue* aTaskQueue, OmxPromiseLayer* aPromiseLayer, OmxDataDecoder* aDataDecoder)
- : mTaskQueue(aTaskQueue)
- , mPromiseLayer(aPromiseLayer)
- , mClient(aDataDecoder)
- {}
-
-protected:
- RefPtr<TaskQueue> mTaskQueue;
- // TODO:
- // we should combine both event handlers into one. And we should provide
- // an unified way for event handling in OmxPlatformLayer class.
- RefPtr<OmxPromiseLayer> mPromiseLayer;
- RefPtr<OmxDataDecoder> mClient;
-};
-
-// This class allocates Gralloc buffer and manages TextureClient's recycle.
-class GonkTextureClientRecycleHandler : public layers::ITextureClientRecycleAllocator
-{
- typedef MozPromise<layers::TextureClient*, nsresult, /* IsExclusive = */ true> TextureClientRecyclePromise;
-
-public:
- GonkTextureClientRecycleHandler(OMX_VIDEO_PORTDEFINITIONTYPE& aDef)
- : ITextureClientRecycleAllocator()
- , mMonitor("GonkTextureClientRecycleHandler")
- {
- RefPtr<layers::ImageBridgeChild> bridge = layers::ImageBridgeChild::GetSingleton();
-
- // Allocate Gralloc texture memory.
- layers::GrallocTextureData* textureData =
- layers::GrallocTextureData::Create(gfx::IntSize(aDef.nFrameWidth, aDef.nFrameHeight),
- aDef.eColorFormat,
- gfx::BackendType::NONE,
- GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_READ_OFTEN,
- bridge);
-
- mGraphBuffer = textureData->GetGraphicBuffer();
- MOZ_ASSERT(mGraphBuffer.get());
-
- mTextureClient =
- layers::TextureClient::CreateWithData(textureData,
- layers::TextureFlags::DEALLOCATE_CLIENT | layers::TextureFlags::RECYCLE,
- bridge);
- MOZ_ASSERT(mTextureClient);
-
- mPromise.SetMonitor(&mMonitor);
- }
-
- RefPtr<TextureClientRecyclePromise> WaitforRecycle()
- {
- MonitorAutoLock lock(mMonitor);
- MOZ_ASSERT(!!mGraphBuffer.get());
-
- mTextureClient->SetRecycleAllocator(this);
- return mPromise.Ensure(__func__);
- }
-
- // DO NOT use smart pointer to receive TextureClient; otherwise it will
- // distrupt the reference count.
- layers::TextureClient* GetTextureClient()
- {
- return mTextureClient;
- }
-
- GraphicBuffer* GetGraphicBuffer()
- {
- MonitorAutoLock lock(mMonitor);
- return mGraphBuffer.get();
- }
-
- // This function is called from layers thread.
- void RecycleTextureClient(layers::TextureClient* aClient) override
- {
- MOZ_ASSERT(mTextureClient == aClient);
-
- // Clearing the recycle allocator drops a reference, so make sure we stay alive
- // for the duration of this function.
- RefPtr<GonkTextureClientRecycleHandler> kungFuDeathGrip(this);
- aClient->SetRecycleAllocator(nullptr);
-
- {
- MonitorAutoLock lock(mMonitor);
- mPromise.ResolveIfExists(mTextureClient, __func__);
- }
- }
-
- void Shutdown()
- {
- MonitorAutoLock lock(mMonitor);
-
- mPromise.RejectIfExists(NS_ERROR_FAILURE, __func__);
-
- // DO NOT clear TextureClient here.
- // The ref count could be 1 and RecycleCallback will be called if we clear
- // the ref count here. That breaks the whole mechanism. (RecycleCallback
- // should be called from layers)
- mGraphBuffer = nullptr;
- }
-
-private:
- // Because TextureClient calls RecycleCallbackl when ref count is 1, so we
- // should hold only one reference here and use raw pointer when out of this
- // class.
- RefPtr<layers::TextureClient> mTextureClient;
-
- // It is protected by mMonitor.
- sp<android::GraphicBuffer> mGraphBuffer;
-
- // It is protected by mMonitor.
- MozPromiseHolder<TextureClientRecyclePromise> mPromise;
-
- Monitor mMonitor;
-};
-
-GonkBufferData::GonkBufferData(bool aLiveInLocal,
- GonkOmxPlatformLayer* aGonkPlatformLayer)
- : BufferData(nullptr)
- , mId(0)
- , mGonkPlatformLayer(aGonkPlatformLayer)
-{
- if (!aLiveInLocal) {
- mMirrorBuffer = new OMX_BUFFERHEADERTYPE;
- PodZero(mMirrorBuffer.get());
- mBuffer = mMirrorBuffer.get();
- }
-}
-
-void
-GonkBufferData::ReleaseBuffer()
-{
- if (mTextureClientRecycleHandler) {
- mTextureClientRecycleHandler->Shutdown();
- mTextureClientRecycleHandler = nullptr;
- }
-}
-
-nsresult
-GonkBufferData::InitSharedMemory(android::IMemory* aMemory)
-{
- MOZ_RELEASE_ASSERT(mMirrorBuffer.get());
-
- // aMemory is a IPC memory, it is safe to use it here.
- mBuffer->pBuffer = (OMX_U8*)aMemory->pointer();
- mBuffer->nAllocLen = aMemory->size();
- return NS_OK;
-}
-
-nsresult
-GonkBufferData::InitLocalBuffer(IOMX::buffer_id aId)
-{
- MOZ_RELEASE_ASSERT(!mMirrorBuffer.get());
-
- mBuffer = (OMX_BUFFERHEADERTYPE*)aId;
- return NS_OK;
-}
-
-nsresult
-GonkBufferData::InitGraphicBuffer(OMX_VIDEO_PORTDEFINITIONTYPE& aDef)
-{
- mTextureClientRecycleHandler = new GonkTextureClientRecycleHandler(aDef);
-
- if (!mTextureClientRecycleHandler->GetGraphicBuffer()) {
- return NS_ERROR_FAILURE;
- }
-
- return NS_OK;
-}
-
-already_AddRefed<MediaData>
-GonkBufferData::GetPlatformMediaData()
-{
- if (mGonkPlatformLayer->GetTrackInfo()->GetAsAudioInfo()) {
- // This is audio decoding.
- return nullptr;
- }
-
- if (!mTextureClientRecycleHandler) {
- // There is no GraphicBuffer, it should fallback to normal YUV420 VideoData.
- return nullptr;
- }
-
- VideoInfo info(*mGonkPlatformLayer->GetTrackInfo()->GetAsVideoInfo());
- RefPtr<VideoData> data =
- VideoData::CreateAndCopyIntoTextureClient(info,
- 0,
- mBuffer->nTimeStamp,
- 1,
- mTextureClientRecycleHandler->GetTextureClient(),
- false,
- 0,
- info.ImageRect());
- LOG("%p, disp width %d, height %d, pic width %d, height %d, time %ld",
- this, info.mDisplay.width, info.mDisplay.height,
- info.mImage.width, info.mImage.height, mBuffer->nTimeStamp);
-
- // Get TextureClient Promise here to wait for resolved.
- RefPtr<GonkBufferData> self(this);
- mTextureClientRecycleHandler->WaitforRecycle()
- ->Then(mGonkPlatformLayer->GetTaskQueue(), __func__,
- [self] () {
- self->mPromise.ResolveIfExists(self, __func__);
- },
- [self] () {
- OmxBufferFailureHolder failure(OMX_ErrorUndefined, self);
- self->mPromise.RejectIfExists(failure, __func__);
- });
-
- return data.forget();
-}
-
-GonkOmxPlatformLayer::GonkOmxPlatformLayer(OmxDataDecoder* aDataDecoder,
- OmxPromiseLayer* aPromiseLayer,
- TaskQueue* aTaskQueue,
- layers::ImageContainer* aImageContainer)
- : mTaskQueue(aTaskQueue)
- , mImageContainer(aImageContainer)
- , mNode(0)
-{
- mOmxObserver = new GonkOmxObserver(mTaskQueue, aPromiseLayer, aDataDecoder);
-}
-
-nsresult
-GonkOmxPlatformLayer::AllocateOmxBuffer(OMX_DIRTYPE aType,
- BUFFERLIST* aBufferList)
-{
- MOZ_ASSERT(!mMemoryDealer[aType].get());
-
- // Get port definition.
- OMX_PARAM_PORTDEFINITIONTYPE def;
- nsTArray<uint32_t> portindex;
- GetPortIndices(portindex);
- for (auto idx : portindex) {
- InitOmxParameter(&def);
- def.nPortIndex = idx;
-
- OMX_ERRORTYPE err = GetParameter(OMX_IndexParamPortDefinition,
- &def,
- sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
- if (err != OMX_ErrorNone) {
- return NS_ERROR_FAILURE;
- } else if (def.eDir == aType) {
- LOG("Get OMX_IndexParamPortDefinition: port: %d, type: %d", def.nPortIndex, def.eDir);
- break;
- }
- }
-
- size_t t = 0;
-
- // Configure video output GraphicBuffer for video decoding acceleration.
- bool useGralloc = false;
- if (aType == OMX_DirOutput && mQuirks.test(kRequiresAllocateBufferOnOutputPorts) &&
- (def.eDomain == OMX_PortDomainVideo)) {
- if (NS_FAILED(EnableOmxGraphicBufferPort(def))) {
- return NS_ERROR_FAILURE;
- }
-
- LOG("Enable OMX GraphicBuffer port, number %d, width %d, height %d", def.nBufferCountActual,
- def.format.video.nFrameWidth, def.format.video.nFrameHeight);
-
- useGralloc = true;
-
- t = 1024; // MemoryDealer doesn't like 0, it's just for MemoryDealer happy.
- } else {
- t = def.nBufferCountActual * def.nBufferSize;
- LOG("Buffer count %d, buffer size %d", def.nBufferCountActual, def.nBufferSize);
- }
-
- bool liveinlocal = mOmx->livesLocally(mNode, getpid());
-
- // MemoryDealer is a IPC buffer allocator in Gonk because IOMX is actually
- // lives in mediaserver.
- mMemoryDealer[aType] = new MemoryDealer(t, "Gecko-OMX");
- for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
- RefPtr<GonkBufferData> buffer;
- IOMX::buffer_id bufferID;
- status_t st;
- nsresult rv;
-
- buffer = new GonkBufferData(liveinlocal, this);
- if (useGralloc) {
- // Buffer is lived remotely. Use GraphicBuffer for decoded video frame display.
- rv = buffer->InitGraphicBuffer(def.format.video);
- NS_ENSURE_SUCCESS(rv, rv);
- st = mOmx->useGraphicBuffer(mNode,
- def.nPortIndex,
- buffer->mTextureClientRecycleHandler->GetGraphicBuffer(),
- &bufferID);
- CHECK_ERR(st);
- } else {
- sp<IMemory> mem = mMemoryDealer[aType]->allocate(def.nBufferSize);
- MOZ_ASSERT(mem.get());
-
- if ((mQuirks.test(kRequiresAllocateBufferOnInputPorts) && aType == OMX_DirInput) ||
- (mQuirks.test(kRequiresAllocateBufferOnOutputPorts) && aType == OMX_DirOutput)) {
- // Buffer is lived remotely. We allocate a local OMX_BUFFERHEADERTYPE
- // as the mirror of the remote OMX_BUFFERHEADERTYPE.
- st = mOmx->allocateBufferWithBackup(mNode, aType, mem, &bufferID);
- CHECK_ERR(st);
- rv = buffer->InitSharedMemory(mem.get());
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Buffer is lived locally, bufferID is the actually OMX_BUFFERHEADERTYPE
- // pointer.
- st = mOmx->useBuffer(mNode, aType, mem, &bufferID);
- CHECK_ERR(st);
- rv = buffer->InitLocalBuffer(bufferID);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- rv = buffer->SetBufferId(bufferID);
- NS_ENSURE_SUCCESS(rv, rv);
-
- aBufferList->AppendElement(buffer);
- }
-
- return NS_OK;
-}
-
-nsresult
-GonkOmxPlatformLayer::ReleaseOmxBuffer(OMX_DIRTYPE aType,
- BUFFERLIST* aBufferList)
-{
- status_t st;
- uint32_t len = aBufferList->Length();
- for (uint32_t i = 0; i < len; i++) {
- GonkBufferData* buffer = static_cast<GonkBufferData*>(aBufferList->ElementAt(i).get());
- IOMX::buffer_id id = (OMX_BUFFERHEADERTYPE*) buffer->ID();
- st = mOmx->freeBuffer(mNode, aType, id);
- if (st != OK) {
- return NS_ERROR_FAILURE;
- }
- buffer->ReleaseBuffer();
- }
- aBufferList->Clear();
- mMemoryDealer[aType].clear();
-
- return NS_OK;
-}
-
-nsresult
-GonkOmxPlatformLayer::EnableOmxGraphicBufferPort(OMX_PARAM_PORTDEFINITIONTYPE& aDef)
-{
- status_t st;
-
- st = mOmx->enableGraphicBuffers(mNode, aDef.nPortIndex, OMX_TRUE);
- CHECK_ERR(st);
-
- return NS_OK;
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::GetState(OMX_STATETYPE* aType)
-{
- return (OMX_ERRORTYPE)mOmx->getState(mNode, aType);
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::GetParameter(OMX_INDEXTYPE aParamIndex,
- OMX_PTR aComponentParameterStructure,
- OMX_U32 aComponentParameterSize)
-{
- return (OMX_ERRORTYPE)mOmx->getParameter(mNode,
- aParamIndex,
- aComponentParameterStructure,
- aComponentParameterSize);
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::SetParameter(OMX_INDEXTYPE aParamIndex,
- OMX_PTR aComponentParameterStructure,
- OMX_U32 aComponentParameterSize)
-{
- return (OMX_ERRORTYPE)mOmx->setParameter(mNode,
- aParamIndex,
- aComponentParameterStructure,
- aComponentParameterSize);
-}
-
-nsresult
-GonkOmxPlatformLayer::Shutdown()
-{
- mOmx->freeNode(mNode);
- mOmxObserver->Shutdown();
- mOmxObserver = nullptr;
- mOmxClient.disconnect();
-
- return NS_OK;
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::InitOmxToStateLoaded(const TrackInfo* aInfo)
-{
- mInfo = aInfo;
- status_t err = mOmxClient.connect();
- if (err != OK) {
- return OMX_ErrorUndefined;
- }
- mOmx = mOmxClient.interface();
- if (!mOmx.get()) {
- return OMX_ErrorUndefined;
- }
-
- LOG("find componenet for mime type %s", mInfo->mMimeType.Data());
-
- nsTArray<ComponentInfo> components;
- if (FindComponents(mInfo->mMimeType, &components)) {
- for (auto comp : components) {
- if (LoadComponent(comp)) {
- return OMX_ErrorNone;
- }
- }
- }
-
- LOG("no component is loaded");
- return OMX_ErrorUndefined;
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::EmptyThisBuffer(BufferData* aData)
-{
- return (OMX_ERRORTYPE)mOmx->emptyBuffer(mNode,
- (IOMX::buffer_id)aData->ID(),
- aData->mBuffer->nOffset,
- aData->mBuffer->nFilledLen,
- aData->mBuffer->nFlags,
- aData->mBuffer->nTimeStamp);
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::FillThisBuffer(BufferData* aData)
-{
- return (OMX_ERRORTYPE)mOmx->fillBuffer(mNode, (IOMX::buffer_id)aData->ID());
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::SendCommand(OMX_COMMANDTYPE aCmd,
- OMX_U32 aParam1,
- OMX_PTR aCmdData)
-{
- return (OMX_ERRORTYPE)mOmx->sendCommand(mNode, aCmd, aParam1);
-}
-
-bool
-GonkOmxPlatformLayer::LoadComponent(const ComponentInfo& aComponent)
-{
- status_t err = mOmx->allocateNode(aComponent.mName, mOmxObserver, &mNode);
- if (err == OK) {
- mQuirks = aComponent.mQuirks;
- LOG("Load OpenMax component %s, alloc input %d, alloc output %d, live locally %d",
- aComponent.mName, mQuirks.test(kRequiresAllocateBufferOnInputPorts),
- mQuirks.test(kRequiresAllocateBufferOnOutputPorts),
- mOmx->livesLocally(mNode, getpid()));
- return true;
- }
- return false;
-}
-
-layers::ImageContainer*
-GonkOmxPlatformLayer::GetImageContainer()
-{
- return mImageContainer;
-}
-
-const TrackInfo*
-GonkOmxPlatformLayer::GetTrackInfo()
-{
- return mInfo;
-}
-
-bool
-GonkOmxPlatformLayer::FindComponents(const nsACString& aMimeType,
- nsTArray<ComponentInfo>* aComponents)
-{
- static const MediaCodecList* codecs = MediaCodecList::getInstance();
-
- bool useHardwareCodecOnly = false;
-
- // H264 and H263 has different profiles, software codec doesn't support high profile.
- // So we use hardware codec only.
- if (!IsInEmulator() &&
- (aMimeType.EqualsLiteral("video/avc") ||
- aMimeType.EqualsLiteral("video/mp4") ||
- aMimeType.EqualsLiteral("video/mp4v-es") ||
- aMimeType.EqualsLiteral("video/3gp"))) {
- useHardwareCodecOnly = true;
- }
-
- const char* mime = aMimeType.Data();
- // Translate VP8 MIME type to Android format.
- if (aMimeType.EqualsLiteral("video/webm; codecs=vp8")) {
- mime = "video/x-vnd.on2.vp8";
- }
-
- size_t start = 0;
- bool found = false;
- while (true) {
- ssize_t index = codecs->findCodecByType(mime, false /* encoder */, start);
- if (index < 0) {
- break;
- }
- start = index + 1;
-
- const char* name = codecs->getCodecName(index);
- if (IsSoftwareCodec(name) && useHardwareCodecOnly) {
- continue;
- }
-
- found = true;
-
- if (!aComponents) {
- continue;
- }
- ComponentInfo* comp = aComponents->AppendElement();
- comp->mName = name;
- if (codecs->codecHasQuirk(index, "requires-allocate-on-input-ports")) {
- comp->mQuirks.set(kRequiresAllocateBufferOnInputPorts);
- }
- if (codecs->codecHasQuirk(index, "requires-allocate-on-output-ports")) {
- comp->mQuirks.set(kRequiresAllocateBufferOnOutputPorts);
- }
- }
-
- return found;
-}
-
-OMX_VIDEO_CODINGTYPE
-GonkOmxPlatformLayer::CompressionFormat()
-{
- MOZ_ASSERT(mInfo);
-
- return mInfo->mMimeType.EqualsLiteral("video/webm; codecs=vp8") ?
- ANDROID_OMX_VIDEO_CodingVP8 : OmxPlatformLayer::CompressionFormat();
-}
-
-} // mozilla
diff --git a/dom/media/platforms/omx/GonkOmxPlatformLayer.h b/dom/media/platforms/omx/GonkOmxPlatformLayer.h
deleted file mode 100644
index aaa8c654d..000000000
--- a/dom/media/platforms/omx/GonkOmxPlatformLayer.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkOmxPlatformLayer_h_)
-#define GonkOmxPlatformLayer_h_
-
-#pragma GCC visibility push(default)
-
-#include <bitset>
-
-#include <utils/RefBase.h>
-#include <media/stagefright/OMXClient.h>
-#include "nsAutoPtr.h"
-
-#include "OMX_Component.h"
-
-#include "OmxPlatformLayer.h"
-
-class nsACString;
-
-namespace android {
-class IMemory;
-class MemoryDealer;
-}
-
-namespace mozilla {
-
-class GonkOmxObserver;
-class GonkOmxPlatformLayer;
-class GonkTextureClientRecycleHandler;
-
-/*
- * Due to Android's omx node could live in local process (client) or remote
- * process (mediaserver). And there are 3 kinds of buffer in Android OMX.
- *
- * 1.
- * When buffer is in local process, the IOMX::buffer_id is OMX_BUFFERHEADERTYPE
- * pointer actually, it is safe to use it directly.
- *
- * 2.
- * When buffer is in remote process, the OMX_BUFFERHEADERTYPE pointer is 'IN' the
- * remote process. It can't be used in local process, so here it allocates a
- * local OMX_BUFFERHEADERTYPE. The raw/decoded data is in the android shared
- * memory, IMemory.
- *
- * 3.
- * When buffer is in remote process for the display output port. It uses
- * GraphicBuffer to accelerate the decoding and display.
- *
- */
-class GonkBufferData : public OmxPromiseLayer::BufferData {
-protected:
- virtual ~GonkBufferData() {}
-
-public:
- GonkBufferData(bool aLiveInLocal,
- GonkOmxPlatformLayer* aLayer);
-
- BufferID ID() override
- {
- return mId;
- }
-
- already_AddRefed<MediaData> GetPlatformMediaData() override;
-
- bool IsLocalBuffer()
- {
- return !!mMirrorBuffer.get();
- }
-
- void ReleaseBuffer();
-
- nsresult SetBufferId(android::IOMX::buffer_id aId)
- {
- mId = aId;
- return NS_OK;
- }
-
- // The mBuffer is in local process. And aId is actually the OMX_BUFFERHEADERTYPE
- // pointer. It doesn't need a mirror buffer.
- nsresult InitLocalBuffer(android::IOMX::buffer_id aId);
-
- // aMemory is an IPC based memory which will be used as the pBuffer in
- // mBuffer. And the mBuffer will be the mirror OMX_BUFFERHEADERTYPE
- // of the one in the remote process.
- nsresult InitSharedMemory(android::IMemory* aMemory);
-
- // GraphicBuffer is for video decoding acceleration on output port.
- // Then mBuffer is the mirror OMX_BUFFERHEADERTYPE of the one in the remote
- // process.
- nsresult InitGraphicBuffer(OMX_VIDEO_PORTDEFINITIONTYPE& aDef);
-
- // Android OMX uses this id to pass the buffer between OMX component and
- // client.
- android::IOMX::buffer_id mId;
-
- // mMirrorBuffer are used only when the omx node is in mediaserver.
- // Due to IPC problem, the mId is the OMX_BUFFERHEADERTYPE address in mediaserver.
- // It can't mapping to client process, so we need a local OMX_BUFFERHEADERTYPE
- // here to mirror the remote OMX_BUFFERHEADERTYPE in mediaserver.
- nsAutoPtr<OMX_BUFFERHEADERTYPE> mMirrorBuffer;
-
- // It creates GraphicBuffer and manages TextureClient.
- RefPtr<GonkTextureClientRecycleHandler> mTextureClientRecycleHandler;
-
- GonkOmxPlatformLayer* mGonkPlatformLayer;
-};
-
-class GonkOmxPlatformLayer : public OmxPlatformLayer {
-public:
- enum {
- kRequiresAllocateBufferOnInputPorts = 0,
- kRequiresAllocateBufferOnOutputPorts,
- QUIRKS,
- };
- typedef std::bitset<QUIRKS> Quirks;
-
- struct ComponentInfo {
- const char* mName;
- Quirks mQuirks;
- };
-
- GonkOmxPlatformLayer(OmxDataDecoder* aDataDecoder,
- OmxPromiseLayer* aPromiseLayer,
- TaskQueue* aTaskQueue,
- layers::ImageContainer* aImageContainer);
-
- nsresult AllocateOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBufferList) override;
-
- nsresult ReleaseOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBufferList) override;
-
- OMX_ERRORTYPE GetState(OMX_STATETYPE* aType) override;
-
- OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE aParamIndex,
- OMX_PTR aComponentParameterStructure,
- OMX_U32 aComponentParameterSize) override;
-
- OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE nIndex,
- OMX_PTR aComponentParameterStructure,
- OMX_U32 aComponentParameterSize) override;
-
- OMX_ERRORTYPE InitOmxToStateLoaded(const TrackInfo* aInfo) override;
-
- OMX_ERRORTYPE EmptyThisBuffer(BufferData* aData) override;
-
- OMX_ERRORTYPE FillThisBuffer(BufferData* aData) override;
-
- OMX_ERRORTYPE SendCommand(OMX_COMMANDTYPE aCmd,
- OMX_U32 aParam1,
- OMX_PTR aCmdData) override;
-
- nsresult Shutdown() override;
-
- static bool FindComponents(const nsACString& aMimeType,
- nsTArray<ComponentInfo>* aComponents = nullptr);
-
- // Android/QCOM decoder uses its own OMX_VIDEO_CodingVP8 definition in
- // frameworks/native/media/include/openmax/OMX_Video.h, not the one defined
- // in OpenMAX v1.1.2 OMX_VideoExt.h
- OMX_VIDEO_CODINGTYPE CompressionFormat() override;
-
-protected:
- friend GonkBufferData;
-
- layers::ImageContainer* GetImageContainer();
-
- const TrackInfo* GetTrackInfo();
-
- TaskQueue* GetTaskQueue()
- {
- return mTaskQueue;
- }
-
- nsresult EnableOmxGraphicBufferPort(OMX_PARAM_PORTDEFINITIONTYPE& aDef);
-
- bool LoadComponent(const ComponentInfo& aComponent);
-
- friend class GonkOmxObserver;
-
- RefPtr<TaskQueue> mTaskQueue;
-
- RefPtr<layers::ImageContainer> mImageContainer;
-
- // OMX_DirInput is 0, OMX_DirOutput is 1.
- android::sp<android::MemoryDealer> mMemoryDealer[2];
-
- android::sp<GonkOmxObserver> mOmxObserver;
-
- android::sp<android::IOMX> mOmx;
-
- android::IOMX::node_id mNode;
-
- android::OMXClient mOmxClient;
-
- Quirks mQuirks;
-};
-
-}
-
-#pragma GCC visibility pop
-
-#endif // GonkOmxPlatformLayer_h_
diff --git a/dom/media/platforms/omx/OmxPlatformLayer.cpp b/dom/media/platforms/omx/OmxPlatformLayer.cpp
index d1f43144d..039b4a22f 100644
--- a/dom/media/platforms/omx/OmxPlatformLayer.cpp
+++ b/dom/media/platforms/omx/OmxPlatformLayer.cpp
@@ -8,11 +8,6 @@
#include "OMX_VideoExt.h" // For VP8.
-#if defined(MOZ_WIDGET_GONK) && (ANDROID_VERSION == 20 || ANDROID_VERSION == 19)
-#define OMX_PLATFORM_GONK
-#include "GonkOmxPlatformLayer.h"
-#endif
-
#include "VPXDecoder.h"
#ifdef LOG
diff --git a/dom/media/platforms/omx/moz.build b/dom/media/platforms/omx/moz.build
index 9f641d937..661e280e0 100644
--- a/dom/media/platforms/omx/moz.build
+++ b/dom/media/platforms/omx/moz.build
@@ -21,29 +21,6 @@ LOCAL_INCLUDES += [
include('/ipc/chromium/chromium-config.mozbuild')
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and (CONFIG['ANDROID_VERSION'] == '19' or CONFIG['ANDROID_VERSION'] == '20'):
- # Suppress some GCC/clang warnings being treated as errors:
- # - about attributes on forward declarations for types that are already
- # defined, which complains about an important MOZ_EXPORT for android::AString
- # - about multi-character constants which are used in codec-related code
- if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
- CXXFLAGS += [
- '-Wno-error=attributes',
- '-Wno-error=multichar'
- ]
- CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/base/include/binder',
- 'frameworks/base/include/utils',
- ]
- ]
- UNIFIED_SOURCES += [
- 'GonkOmxPlatformLayer.cpp',
- ]
- EXTRA_DSO_LDOPTS += [
- '-libbinder',
- ]
-
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
diff --git a/dom/media/platforms/wmf/DXVA2Manager.cpp b/dom/media/platforms/wmf/DXVA2Manager.cpp
index 9fdb0fa20..0c1734c54 100644
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -21,7 +21,6 @@
#include "MFTDecoder.h"
#include "DriverCrashGuard.h"
#include "nsPrintfCString.h"
-#include "gfxCrashReporterUtils.h"
#include "VideoUtils.h"
const CLSID CLSID_VideoProcessorMFT =
@@ -271,8 +270,6 @@ D3D9DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
{
MOZ_ASSERT(NS_IsMainThread());
- ScopedGfxFeatureReporter reporter("DXVA2D3D9");
-
gfx::D3D9VideoCrashGuard crashGuard;
if (crashGuard.Crashed()) {
NS_WARNING("DXVA2D3D9 crash detected");
@@ -448,8 +445,6 @@ D3D9DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
Telemetry::Accumulate(Telemetry::MEDIA_DECODER_BACKEND_USED,
uint32_t(media::MediaDecoderBackend::WMFDXVA2D3D9));
- reporter.SetSuccessful();
-
return S_OK;
}
@@ -645,8 +640,6 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
{
HRESULT hr;
- ScopedGfxFeatureReporter reporter("DXVA2D3D11");
-
gfx::D3D11VideoCrashGuard crashGuard;
if (crashGuard.Crashed()) {
NS_WARNING("DXVA2D3D11 crash detected");
@@ -785,8 +778,6 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
Telemetry::Accumulate(Telemetry::MEDIA_DECODER_BACKEND_USED,
uint32_t(media::MediaDecoderBackend::WMFDXVA2D3D11));
- reporter.SetSuccessful();
-
return S_OK;
}
diff --git a/dom/media/standalone/moz.build b/dom/media/standalone/moz.build
index 5d2c5a6e7..959703765 100644
--- a/dom/media/standalone/moz.build
+++ b/dom/media/standalone/moz.build
@@ -4,7 +4,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-if CONFIG['OS_TARGET'] != 'WINNT' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
+if CONFIG['OS_TARGET'] != 'WINNT':
Library('media_standalone')
UNIFIED_SOURCES += [
diff --git a/dom/media/systemservices/CamerasChild.cpp b/dom/media/systemservices/CamerasChild.cpp
index 0f7d1c1df..a3fbec850 100644
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -35,7 +35,9 @@ CamerasSingleton::CamerasSingleton()
: mCamerasMutex("CamerasSingleton::mCamerasMutex"),
mCameras(nullptr),
mCamerasChildThread(nullptr),
- mFakeDeviceChangeEventThread(nullptr) {
+ mFakeDeviceChangeEventThread(nullptr),
+ mInShutdown(false)
+{
LOG(("CamerasSingleton: %p", this));
}
@@ -285,6 +287,7 @@ CamerasChild::NumberOfCapabilities(CaptureEngine aCapEngine,
LOG((__PRETTY_FUNCTION__));
LOG(("NumberOfCapabilities for %s", deviceUniqueIdUTF8));
nsCString unique_id(deviceUniqueIdUTF8);
+ RefPtr<CamerasChild> deathGrip = this;
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewNonOwningRunnableMethod<CaptureEngine, nsCString>
(this, &CamerasChild::SendNumberOfCapabilities, aCapEngine, unique_id);
@@ -321,6 +324,7 @@ int
CamerasChild::EnsureInitialized(CaptureEngine aCapEngine)
{
LOG((__PRETTY_FUNCTION__));
+ RefPtr<CamerasChild> deathGrip = this;
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewNonOwningRunnableMethod<CaptureEngine>
(this, &CamerasChild::SendEnsureInitialized, aCapEngine);
@@ -336,6 +340,7 @@ CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
webrtc::CaptureCapability& capability)
{
LOG(("GetCaptureCapability: %s %d", unique_idUTF8, capability_number));
+ RefPtr<CamerasChild> deathGrip = this;
nsCString unique_id(unique_idUTF8);
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewNonOwningRunnableMethod<CaptureEngine, nsCString, unsigned int>
@@ -374,6 +379,7 @@ CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine,
bool* scary)
{
LOG((__PRETTY_FUNCTION__));
+ RefPtr<CamerasChild> deathGrip = this;
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewNonOwningRunnableMethod<CaptureEngine, unsigned int>
(this, &CamerasChild::SendGetCaptureDevice, aCapEngine, list_number);
@@ -413,6 +419,7 @@ CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
const nsACString& aOrigin)
{
LOG((__PRETTY_FUNCTION__));
+ RefPtr<CamerasChild> deathGrip = this;
nsCString unique_id(unique_idUTF8);
nsCString origin(aOrigin);
nsCOMPtr<nsIRunnable> runnable =
@@ -444,6 +451,7 @@ CamerasChild::ReleaseCaptureDevice(CaptureEngine aCapEngine,
const int capture_id)
{
LOG((__PRETTY_FUNCTION__));
+ RefPtr<CamerasChild> deathGrip = this;
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewNonOwningRunnableMethod<CaptureEngine, int>
(this, &CamerasChild::SendReleaseCaptureDevice, aCapEngine, capture_id);
@@ -491,6 +499,7 @@ CamerasChild::StartCapture(CaptureEngine aCapEngine,
webrtcCaps.rawType,
webrtcCaps.codecType,
webrtcCaps.interlaced);
+ RefPtr<CamerasChild> deathGrip = this;
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewNonOwningRunnableMethod<CaptureEngine, int, CaptureCapability>
(this, &CamerasChild::SendStartCapture, aCapEngine, capture_id, capCap);
@@ -502,6 +511,7 @@ int
CamerasChild::StopCapture(CaptureEngine aCapEngine, const int capture_id)
{
LOG((__PRETTY_FUNCTION__));
+ RefPtr<CamerasChild> deathGrip = this;
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewNonOwningRunnableMethod<CaptureEngine, int>
(this, &CamerasChild::SendStopCapture, aCapEngine, capture_id);
@@ -567,6 +577,7 @@ CamerasChild::ShutdownParent()
// Delete the parent actor.
// CamerasChild (this) will remain alive and is only deleted by the
// IPC layer when SendAllDone returns.
+ RefPtr<CamerasChild> deathGrip = this;
nsCOMPtr<nsIRunnable> deleteRunnable =
mozilla::NewNonOwningRunnableMethod(this, &CamerasChild::SendAllDone);
CamerasSingleton::Thread()->Dispatch(deleteRunnable, NS_DISPATCH_NORMAL);
@@ -695,7 +706,7 @@ CamerasChild::~CamerasChild()
{
LOG(("~CamerasChild: %p", this));
- {
+ if (!CamerasSingleton::InShutdown()) {
OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
// In normal circumstances we've already shut down and the
// following does nothing. But on fatal IPC errors we will
diff --git a/dom/media/systemservices/CamerasChild.h b/dom/media/systemservices/CamerasChild.h
index 1530714e9..9ca125cfd 100644
--- a/dom/media/systemservices/CamerasChild.h
+++ b/dom/media/systemservices/CamerasChild.h
@@ -89,6 +89,14 @@ public:
return gTheInstance.get()->mFakeDeviceChangeEventThread;
}
+ static bool InShutdown() {
+ return gTheInstance.get()->mInShutdown;
+ }
+
+ static void StartShutdown() {
+ gTheInstance.get()->mInShutdown = true;
+ }
+
private:
static Singleton<CamerasSingleton> gTheInstance;
@@ -106,6 +114,7 @@ private:
CamerasChild* mCameras;
nsCOMPtr<nsIThread> mCamerasChildThread;
nsCOMPtr<nsIThread> mFakeDeviceChangeEventThread;
+ Atomic<bool> mInShutdown;
};
// Get a pointer to a CamerasChild object we can use to do IPC with.
@@ -145,7 +154,7 @@ class CamerasChild final : public PCamerasChild
public:
// We are owned by the PBackground thread only. CamerasSingleton
// takes a non-owning reference.
- NS_INLINE_DECL_REFCOUNTING(CamerasChild)
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CamerasChild)
// IPC messages recevied, received on the PBackground thread
// these are the actual callbacks with data
diff --git a/dom/media/systemservices/MediaSystemResourceService.cpp b/dom/media/systemservices/MediaSystemResourceService.cpp
index 0e5d6a50c..4434c54c2 100644
--- a/dom/media/systemservices/MediaSystemResourceService.cpp
+++ b/dom/media/systemservices/MediaSystemResourceService.cpp
@@ -47,23 +47,6 @@ MediaSystemResourceService::MediaSystemResourceService()
: mDestroyed(false)
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-#ifdef MOZ_WIDGET_GONK
- // The maximum number of hardware resoureces available.
- // XXX need to hange to a dynamic way.
- enum
- {
- VIDEO_DECODER_COUNT = 1,
- VIDEO_ENCODER_COUNT = 1
- };
-
- MediaSystemResource* resource;
-
- resource = new MediaSystemResource(VIDEO_DECODER_COUNT);
- mResources.Put(static_cast<uint32_t>(MediaSystemResourceType::VIDEO_DECODER), resource);
-
- resource = new MediaSystemResource(VIDEO_ENCODER_COUNT);
- mResources.Put(static_cast<uint32_t>(MediaSystemResourceType::VIDEO_ENCODER), resource);
-#endif
}
MediaSystemResourceService::~MediaSystemResourceService()
diff --git a/dom/media/systemservices/moz.build b/dom/media/systemservices/moz.build
index 33e5ed1f1..82a5c5e72 100644
--- a/dom/media/systemservices/moz.build
+++ b/dom/media/systemservices/moz.build
@@ -42,16 +42,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
UNIFIED_SOURCES += ['OSXRunLoopSingleton.cpp']
EXPORTS += ['OSXRunLoopSingleton.h']
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- if CONFIG['ANDROID_VERSION'] >= '17':
- LOCAL_INCLUDES += [
- '%' + '%s/frameworks/wilhelm/include' % CONFIG['ANDROID_SOURCE'],
- ]
- else:
- LOCAL_INCLUDES += [
- '%' + '%s/system/media/wilhelm/include' % CONFIG['ANDROID_SOURCE'],
- ]
-
if CONFIG['_MSC_VER']:
DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__'
diff --git a/dom/media/webrtc/MediaEngine.h b/dom/media/webrtc/MediaEngine.h
index ff2a6e25a..6a6988544 100644
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -54,11 +54,8 @@ public:
static const int DEFAULT_169_VIDEO_WIDTH = 1280;
static const int DEFAULT_169_VIDEO_HEIGHT = 720;
-#ifndef MOZ_B2G
static const int DEFAULT_SAMPLE_RATE = 32000;
-#else
- static const int DEFAULT_SAMPLE_RATE = 16000;
-#endif
+
// This allows using whatever rate the graph is using for the
// MediaStreamTrack. This is useful for microphone data, we know it's already
// at the correct rate for insertion in the MSG.
diff --git a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
index a0f31d937..e1e572724 100644
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
@@ -325,7 +325,7 @@ MediaEngineCameraVideoSource::SetName(nsString aName)
VideoFacingModeEnum facingMode = VideoFacingModeEnum::User;
// Set facing mode based on device name.
-#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
+#if defined(ANDROID)
// Names are generated. Example: "Camera 0, Facing back, Orientation 90"
//
// See media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/
diff --git a/dom/media/webrtc/MediaEngineDefault.cpp b/dom/media/webrtc/MediaEngineDefault.cpp
index 9c97d197f..eb0ac2b6f 100644
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -192,7 +192,7 @@ MediaEngineDefaultVideoSource::Start(SourceMediaStream* aStream, TrackID aID,
mTrackID = aID;
// Start timer for subsequent frames
-#if (defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)) && defined(DEBUG)
+#if defined(MOZ_WIDGET_ANDROID) && defined(DEBUG)
// emulator debug is very, very slow and has problems dealing with realtime audio inputs
mTimer->InitWithCallback(this, (1000 / mOpts.mFPS)*10, nsITimer::TYPE_REPEATING_SLACK);
#else
diff --git a/dom/media/webrtc/MediaEngineWebRTC.cpp b/dom/media/webrtc/MediaEngineWebRTC.cpp
index 1a2dc9a04..a77800424 100644
--- a/dom/media/webrtc/MediaEngineWebRTC.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTC.cpp
@@ -335,7 +335,7 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource,
int nDevices = 0;
mAudioInput->GetNumOfRecordingDevices(nDevices);
int i;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
i = 0; // Bug 1037025 - let the OS handle defaulting for now on android/b2g
#else
// -1 is "default communications device" depending on OS in webrtc.org code
diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
index 0b8796aa8..1e2e13d01 100644
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -741,9 +741,6 @@ MediaEngineWebRTCMicrophoneSource::AllocChannel()
// Check for availability.
if (!mAudioInput->SetRecordingDevice(mCapIndex)) {
-#ifndef MOZ_B2G
- // Because of the permission mechanism of B2G, we need to skip the status
- // check here.
bool avail = false;
mAudioInput->GetRecordingDeviceStatus(avail);
if (!avail) {
@@ -752,7 +749,6 @@ MediaEngineWebRTCMicrophoneSource::AllocChannel()
}
return false;
}
-#endif // MOZ_B2G
// Set "codec" to PCM, 32kHz on 1 channel
ScopedCustomReleasePtr<webrtc::VoECodec> ptrVoECodec(webrtc::VoECodec::GetInterface(mVoiceEngine));
diff --git a/dom/moz.build b/dom/moz.build
index 6242b4fbc..358fc6411 100644
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -105,21 +105,9 @@ DIRS += [
if CONFIG['OS_ARCH'] == 'WINNT':
DIRS += ['plugins/ipc/hangui']
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- DIRS += [
- 'speakermanager',
- 'tethering',
- 'wifi',
- ]
-
if CONFIG['MOZ_SECUREELEMENT']:
DIRS += ['secureelement']
-if CONFIG['MOZ_B2G']:
- DIRS += [
- 'downloads',
- ]
-
DIRS += ['presentation']
TEST_DIRS += [
diff --git a/dom/network/EthernetManager.js b/dom/network/EthernetManager.js
deleted file mode 100644
index 4b11e5666..000000000
--- a/dom/network/EthernetManager.js
+++ /dev/null
@@ -1,655 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const TOPIC_INTERFACE_STATE_CHANGED = "network-interface-state-changed";
-
-const ETHERNET_NETWORK_IFACE_PREFIX = "eth";
-const DEFAULT_ETHERNET_NETWORK_IFACE = "eth0";
-
-const INTERFACE_IPADDR_NULL = "0.0.0.0";
-const INTERFACE_GATEWAY_NULL = "0.0.0.0";
-const INTERFACE_PREFIX_NULL = 0;
-const INTERFACE_MACADDR_NULL = "00:00:00:00:00:00";
-
-const NETWORK_INTERFACE_UP = "up";
-const NETWORK_INTERFACE_DOWN = "down";
-
-const IP_MODE_DHCP = "dhcp";
-const IP_MODE_STATIC = "static";
-
-const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-let debug;
-function updateDebug() {
- let debugPref = false; // set default value here.
- try {
- debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
- } catch (e) {}
-
- if (debugPref) {
- debug = function(s) {
- dump("-*- EthernetManager: " + s + "\n");
- };
- } else {
- debug = function(s) {};
- }
-}
-updateDebug();
-
-// nsINetworkInterface
-
-function EthernetInterface(attr) {
- this.info.state = attr.state;
- this.info.type = attr.type;
- this.info.name = attr.name;
- this.info.ipMode = attr.ipMode;
- this.info.ips = [attr.ip];
- this.info.prefixLengths = [attr.prefixLength];
- this.info.gateways = [attr.gateway];
- this.info.dnses = attr.dnses;
- this.httpProxyHost = "";
- this.httpProxyPort = 0;
-}
-EthernetInterface.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
-
- updateConfig: function(config) {
- debug("Interface " + this.info.name + " updateConfig " + JSON.stringify(config));
- this.info.state = (config.state != undefined) ?
- config.state : this.info.state;
- this.info.ips = (config.ip != undefined) ? [config.ip] : this.info.ips;
- this.info.prefixLengths = (config.prefixLength != undefined) ?
- [config.prefixLength] : this.info.prefixLengths;
- this.info.gateways = (config.gateway != undefined) ?
- [config.gateway] : this.info.gateways;
- this.info.dnses = (config.dnses != undefined) ? config.dnses : this.info.dnses;
- this.httpProxyHost = (config.httpProxyHost != undefined) ?
- config.httpProxyHost : this.httpProxyHost;
- this.httpProxyPort = (config.httpProxyPort != undefined) ?
- config.httpProxyPort : this.httpProxyPort;
- this.info.ipMode = (config.ipMode != undefined) ?
- config.ipMode : this.info.ipMode;
- },
-
- info: {
- getAddresses: function(ips, prefixLengths) {
- ips.value = this.ips.slice();
- prefixLengths.value = this.prefixLengths.slice();
-
- return this.ips.length;
- },
-
- getGateways: function(count) {
- if (count) {
- count.value = this.gateways.length;
- }
- return this.gateways.slice();
- },
-
- getDnses: function(count) {
- if (count) {
- count.value = this.dnses.length;
- }
- return this.dnses.slice();
- }
- }
-};
-
-// nsIEthernetManager
-
-/*
- * Network state transition diagram
- *
- * ---------- enable --------- connect ----------- disconnect --------------
- * | Disabled | -----> | Enabled | -------> | Connected | <----------> | Disconnected |
- * ---------- --------- ----------- connect --------------
- * ^ | | |
- * | disable | | |
- * -----------------------------------------------------------------------
- */
-
-function EthernetManager() {
- debug("EthernetManager start");
-
- // Interface list.
- this.ethernetInterfaces = {};
-
- // Used to memorize last connection information.
- this.lastStaticConfig = {};
-
- Services.obs.addObserver(this, "xpcom-shutdown", false);
-}
-
-EthernetManager.prototype = {
- classID: Components.ID("a96441dd-36b3-4f7f-963b-2c032e28a039"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIEthernetManager]),
-
- ethernetInterfaces: null,
- lastStaticConfig: null,
-
- observer: function(subject, topic, data) {
- switch (topic) {
- case "xpcom-shutdown":
- debug("xpcom-shutdown");
-
- this._shutdown();
-
- Services.obs.removeObserver(this, "xpcom-shutdown");
- break;
- }
- },
-
- _shutdown: function() {
- debug("Shuting down");
- (function onRemove(ifnameList) {
- if (!ifnameList.length) {
- return;
- }
-
- let ifname = ifnameList.shift();
- this.removeInterface(ifname, { notify: onRemove.bind(this, ifnameList) });
- }).call(this, Object.keys(this.ethernetInterfaces));
- },
-
- get interfaceList() {
- return Object.keys(this.ethernetInterfaces);
- },
-
- scan: function(callback) {
- debug("Scan");
-
- gNetworkService.getInterfaces(function(success, list) {
- let ethList = [];
-
- if (!success) {
- if (callback) {
- callback.notify(ethList);
- }
- return;
- }
-
- for (let i = 0; i < list.length; i++) {
- debug("Found interface " + list[i]);
- if (!list[i].startsWith(ETHERNET_NETWORK_IFACE_PREFIX)) {
- continue;
- }
- ethList.push(list[i]);
- }
-
- if (callback) {
- callback.notify(ethList);
- }
- });
- },
-
- addInterface: function(ifname, callback) {
- debug("Add interface " + ifname);
-
- if (!ifname || !ifname.startsWith(ETHERNET_NETWORK_IFACE_PREFIX)) {
- if (callback) {
- callback.notify(false, "Invalid interface.");
- }
- return;
- }
-
- if (this.ethernetInterfaces[ifname]) {
- if (callback) {
- callback.notify(true, "Interface already exists.");
- }
- return;
- }
-
- gNetworkService.getInterfaceConfig(ifname, function(success, result) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd error.");
- }
- return;
- }
-
- // Since the operation may still succeed with an invalid interface name,
- // check the mac address as well.
- if (result.macAddr == INTERFACE_MACADDR_NULL) {
- if (callback) {
- callback.notify(false, "Interface not found.");
- }
- return;
- }
-
- this.ethernetInterfaces[ifname] = new EthernetInterface({
- state: result.link == NETWORK_INTERFACE_UP ?
- Ci.nsINetworkInfo.NETWORK_STATE_DISABLED :
- Ci.nsINetworkInfo.NETWORK_STATE_ENABLED,
- name: ifname,
- type: Ci.nsINetworkInfo.NETWORK_TYPE_ETHERNET,
- ip: result.ip,
- prefixLength: result.prefix,
- ipMode: IP_MODE_DHCP
- });
-
- // Register the interface to NetworkManager.
- gNetworkManager.registerNetworkInterface(this.ethernetInterfaces[ifname]);
-
- debug("Add interface " + ifname + " succeeded with " +
- JSON.stringify(this.ethernetInterfaces[ifname]));
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- },
-
- removeInterface: function(ifname, callback) {
- debug("Remove interface " + ifname);
-
- if (!ifname || !ifname.startsWith(ETHERNET_NETWORK_IFACE_PREFIX)) {
- if (callback) {
- callback.notify(false, "Invalid interface.");
- }
- return;
- }
-
- if (!this.ethernetInterfaces[ifname]) {
- if (callback) {
- callback.notify(true, "Interface does not exist.");
- }
- return;
- }
-
- // Make sure interface is disable before removing.
- this.disable(ifname, { notify: function(success, message) {
- // Unregister the interface from NetworkManager and also remove it from
- // the interface list.
- gNetworkManager.unregisterNetworkInterface(this.ethernetInterfaces[ifname]);
- delete this.ethernetInterfaces[ifname];
-
- debug("Remove interface " + ifname + " succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this)});
- },
-
- updateInterfaceConfig: function(ifname, config, callback) {
- debug("Update interface config with " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- if (!config) {
- if (callback) {
- callback.notify(false, "No config to update.");
- }
- return;
- }
-
- // Network state can not be modified externally.
- if (config.state) {
- delete config.state;
- }
-
- let currentIpMode = iface.info.ipMode;
-
- // Update config.
- this.ethernetInterfaces[iface.info.name].updateConfig(config);
-
- // Do not automatically re-connect if the interface is not in connected
- // state.
- if (iface.info.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- if (callback) {
- callback.notify(true, "ok");
- }
- return;
- }
-
- let newIpMode = this.ethernetInterfaces[iface.info.name].info.ipMode;
-
- if (newIpMode == IP_MODE_STATIC) {
- this._setStaticIP(iface.info.name, callback);
- return;
- }
- if ((currentIpMode == IP_MODE_STATIC) && (newIpMode == IP_MODE_DHCP)) {
- gNetworkService.stopDhcp(iface.info.name, function(success) {
- if (success) {
- debug("DHCP for " + iface.info.name + " stopped.");
- }
- });
-
- // Clear the current network settings before do dhcp request, otherwise
- // dhcp settings could fail.
- this.disconnect(iface.info.name, { notify: function(success, message) {
- if (!success) {
- if (callback) {
- callback.notify("Disconnect failed.");
- }
- return;
- }
- this._runDhcp(iface.info.name, callback);
- }.bind(this) });
- return;
- }
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- },
-
- enable: function(ifname, callback) {
- debug("Enable interface " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- // Interface can be only enabled in the state of disabled.
- if (iface.info.state != Ci.nsINetworkInfo.NETWORK_STATE_DISABLED) {
- if (callback) {
- callback.notify(true, "Interface already enabled.");
- }
- return;
- }
-
- let ips = {};
- let prefixLengths = {};
- iface.info.getAddresses(ips, prefixLengths);
- let config = { ifname: iface.info.name,
- ip: ips.value[0],
- prefix: prefixLengths.value[0],
- link: NETWORK_INTERFACE_UP };
- gNetworkService.setInterfaceConfig(config, function(success) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd Error.");
- }
- return;
- }
-
- this.ethernetInterfaces[iface.info.name].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_ENABLED
- });
-
- debug("Enable interface " + iface.info.name + " succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- }.bind(this));
- },
-
- disable: function(ifname, callback) {
- debug("Disable interface " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- if (iface.info.state == Ci.nsINetworkInfo.NETWORK_STATE_DISABLED) {
- if (callback) {
- callback.notify(true, "Interface already disabled.");
- }
- return;
- }
-
- if (iface.info.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- gNetworkService.stopDhcp(iface.info.name, function(success) {
- if (success) {
- debug("DHCP for " + iface.info.name + " stopped.");
- }
- });
- }
-
- let ips = {};
- let prefixLengths = {};
- iface.info.getAddresses(ips, prefixLengths);
- let config = { ifname: iface.info.name,
- ip: ips.value[0],
- prefix: prefixLengths.value[0],
- link: NETWORK_INTERFACE_DOWN };
- gNetworkService.setInterfaceConfig(config, function(success) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd Error.");
- }
- return;
- }
-
- this.ethernetInterfaces[iface.info.name].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_DISABLED
- });
-
- debug("Disable interface " + iface.info.name + " succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- }.bind(this));
- },
-
- connect: function(ifname, callback) {
- debug("Connect interface " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- // Interface can only be connected in the state of enabled or
- // disconnected.
- if (iface.info.state == Ci.nsINetworkInfo.NETWORK_STATE_DISABLED ||
- iface.info.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- if (callback) {
- callback.notify(true, "Interface " + ifname + " is not available or "
- + " already connected.");
- }
- return;
- }
-
- if (iface.info.ipMode == IP_MODE_DHCP) {
- this._runDhcp(iface.info.name, callback);
- return;
- }
-
- if (iface.info.ipMode == IP_MODE_STATIC) {
- if (this._checkConfigNull(iface) && this.lastStaticConfig[iface.info.name]) {
- debug("Connect with lastStaticConfig " +
- JSON.stringify(this.lastStaticConfig[iface.info.name]));
- this.ethernetInterfaces[iface.info.name].updateConfig(
- this.lastStaticConfig[iface.info.name]);
- }
- this._setStaticIP(iface.info.name, callback);
- return;
- }
-
- if (callback) {
- callback.notify(false, "IP mode is wrong or not set.");
- }
- }.bind(this));
- },
-
- disconnect: function(ifname, callback) {
- debug("Disconnect interface " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- // Interface can be only disconnected in the state of connected.
- if (iface.info.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- if (callback) {
- callback.notify(true, "Interface is already disconnected");
- }
- return;
- }
-
- let config = { ifname: iface.info.name,
- ip: INTERFACE_IPADDR_NULL,
- prefix: INTERFACE_PREFIX_NULL,
- link: NETWORK_INTERFACE_UP };
- gNetworkService.setInterfaceConfig(config, function(success) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd error.");
- }
- return;
- }
-
- // Stop dhcp daemon.
- gNetworkService.stopDhcp(iface.info.name, function(success) {
- if (success) {
- debug("DHCP for " + iface.info.name + " stopped.");
- }
- });
-
- this.ethernetInterfaces[iface.info.name].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
- ip: INTERFACE_IPADDR_NULL,
- prefixLength: INTERFACE_PREFIX_NULL,
- gateway: INTERFACE_GATEWAY_NULL
- });
-
- gNetworkManager.updateNetworkInterface(this.ethernetInterfaces[ifname]);
-
- debug("Disconnect interface " + iface.info.name + " succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- }.bind(this));
- },
-
- _checkConfigNull: function(iface) {
- let ips = {};
- let prefixLengths = {};
- let gateways = iface.info.getGateways();
- iface.info.getAddresses(ips, prefixLengths);
-
- if (ips.value[0] == INTERFACE_IPADDR_NULL &&
- prefixLengths.value[0] == INTERFACE_PREFIX_NULL &&
- gateways[0] == INTERFACE_GATEWAY_NULL) {
- return true;
- }
-
- return false;
- },
-
- _ensureIfname: function(ifname, callback, func) {
- // If no given ifname, use the default one.
- if (!ifname) {
- ifname = DEFAULT_ETHERNET_NETWORK_IFACE;
- }
-
- let iface = this.ethernetInterfaces[ifname];
- if (!iface) {
- if (callback) {
- callback.notify(true, "Interface " + ifname + " is not available.");
- }
- return;
- }
-
- func.call(this, iface);
- },
-
- _runDhcp: function(ifname, callback) {
- debug("runDhcp with " + ifname);
-
- if (!this.ethernetInterfaces[ifname]) {
- if (callback) {
- callback.notify(false, "Invalid interface.");
- }
- return;
- }
-
- gNetworkService.dhcpRequest(ifname, function(success, result) {
- if (!success) {
- if (callback) {
- callback.notify(false, "DHCP failed.");
- }
- return;
- }
-
- debug("DHCP succeeded with " + JSON.stringify(result));
-
- // Clear last static network information when connecting with dhcp mode.
- if (this.lastStaticConfig[ifname]) {
- this.lastStaticConfig[ifname] = null;
- }
-
- this.ethernetInterfaces[ifname].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED,
- ip: result.ipaddr_str,
- gateway: result.gateway_str,
- prefixLength: result.prefixLength,
- dnses: [result.dns1_str, result.dns2_str]
- });
-
- gNetworkManager.updateNetworkInterface(this.ethernetInterfaces[ifname]);
-
- debug("Connect interface " + ifname + " with DHCP succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- },
-
- _setStaticIP: function(ifname, callback) {
- let iface = this.ethernetInterfaces[ifname];
- if (!iface) {
- if (callback) {
- callback.notify(false, "Invalid interface.");
- }
- return;
- }
-
- let ips = {};
- let prefixLengths = {};
- iface.info.getAddresses(ips, prefixLengths);
-
- let config = { ifname: iface.info.name,
- ip: ips.value[0],
- prefix: prefixLengths.value[0],
- link: NETWORK_INTERFACE_UP };
- gNetworkService.setInterfaceConfig(config, function(success) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd Error.");
- }
- return;
- }
-
- // Keep the lastest static network information.
- let ips = {};
- let prefixLengths = {};
- let gateways = iface.info.getGateways();
- iface.info.getAddresses(ips, prefixLengths);
-
- this.lastStaticConfig[iface.info.name] = {
- ip: ips.value[0],
- prefixLength: prefixLengths.value[0],
- gateway: gateways[0]
- };
-
- this.ethernetInterfaces[ifname].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED,
- });
-
- gNetworkManager.updateNetworkInterface(this.ethernetInterfaces[ifname]);
-
- debug("Connect interface " + ifname + " with static ip succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- },
-}
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([EthernetManager]);
diff --git a/dom/network/EthernetManager.manifest b/dom/network/EthernetManager.manifest
deleted file mode 100644
index d25a069e1..000000000
--- a/dom/network/EthernetManager.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {a96441dd-36b3-4f7f-963b-2c032e28a039} EthernetManager.js
-contract @mozilla.org/ethernetManager;1 {a96441dd-36b3-4f7f-963b-2c032e28a039}
diff --git a/dom/network/NetUtils.cpp b/dom/network/NetUtils.cpp
deleted file mode 100644
index 78c5be802..000000000
--- a/dom/network/NetUtils.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NetUtils.h"
-#include <dlfcn.h>
-#include <errno.h>
-#include "prinit.h"
-#include "mozilla/Assertions.h"
-#include "nsDebug.h"
-#include "SystemProperty.h"
-
-using mozilla::system::Property;
-
-static void* sNetUtilsLib;
-static PRCallOnceType sInitNetUtilsLib;
-
-static PRStatus
-InitNetUtilsLib()
-{
- sNetUtilsLib = dlopen("/system/lib/libnetutils.so", RTLD_LAZY);
- // We might fail to open the hardware lib. That's OK.
- return PR_SUCCESS;
-}
-
-static void*
-GetNetUtilsLibHandle()
-{
- PR_CallOnce(&sInitNetUtilsLib, InitNetUtilsLib);
- return sNetUtilsLib;
-}
-
-// static
-void*
-NetUtils::GetSharedLibrary()
-{
- void* netLib = GetNetUtilsLibHandle();
- if (!netLib) {
- NS_WARNING("No /system/lib/libnetutils.so");
- }
- return netLib;
-}
-
-// static
-int32_t
-NetUtils::SdkVersion()
-{
- char propVersion[Property::VALUE_MAX_LENGTH];
- Property::Get("ro.build.version.sdk", propVersion, "0");
- int32_t version = strtol(propVersion, nullptr, 10);
- return version;
-}
-
-DEFINE_DLFUNC(ifc_enable, int32_t, const char*)
-DEFINE_DLFUNC(ifc_disable, int32_t, const char*)
-DEFINE_DLFUNC(ifc_configure, int32_t, const char*, in_addr_t, uint32_t,
- in_addr_t, in_addr_t, in_addr_t)
-DEFINE_DLFUNC(ifc_reset_connections, int32_t, const char*, const int32_t)
-DEFINE_DLFUNC(ifc_set_default_route, int32_t, const char*, in_addr_t)
-DEFINE_DLFUNC(ifc_add_route, int32_t, const char*, const char*, uint32_t, const char*)
-DEFINE_DLFUNC(ifc_remove_route, int32_t, const char*, const char*, uint32_t, const char*)
-DEFINE_DLFUNC(ifc_remove_host_routes, int32_t, const char*)
-DEFINE_DLFUNC(ifc_remove_default_route, int32_t, const char*)
-DEFINE_DLFUNC(dhcp_stop, int32_t, const char*)
-
-NetUtils::NetUtils()
-{
-}
-
-int32_t NetUtils::do_ifc_enable(const char *ifname)
-{
- USE_DLFUNC(ifc_enable)
- return ifc_enable(ifname);
-}
-
-int32_t NetUtils::do_ifc_disable(const char *ifname)
-{
- USE_DLFUNC(ifc_disable)
- return ifc_disable(ifname);
-}
-
-int32_t NetUtils::do_ifc_configure(const char *ifname,
- in_addr_t address,
- uint32_t prefixLength,
- in_addr_t gateway,
- in_addr_t dns1,
- in_addr_t dns2)
-{
- USE_DLFUNC(ifc_configure)
- int32_t ret = ifc_configure(ifname, address, prefixLength, gateway, dns1, dns2);
- return ret;
-}
-
-int32_t NetUtils::do_ifc_reset_connections(const char *ifname,
- const int32_t resetMask)
-{
- USE_DLFUNC(ifc_reset_connections)
- return ifc_reset_connections(ifname, resetMask);
-}
-
-int32_t NetUtils::do_ifc_set_default_route(const char *ifname,
- in_addr_t gateway)
-{
- USE_DLFUNC(ifc_set_default_route)
- return ifc_set_default_route(ifname, gateway);
-}
-
-int32_t NetUtils::do_ifc_add_route(const char *ifname,
- const char *dst,
- uint32_t prefixLength,
- const char *gateway)
-{
- USE_DLFUNC(ifc_add_route)
- return ifc_add_route(ifname, dst, prefixLength, gateway);
-}
-
-int32_t NetUtils::do_ifc_remove_route(const char *ifname,
- const char *dst,
- uint32_t prefixLength,
- const char *gateway)
-{
- USE_DLFUNC(ifc_remove_route)
- return ifc_remove_route(ifname, dst, prefixLength, gateway);
-}
-
-int32_t NetUtils::do_ifc_remove_host_routes(const char *ifname)
-{
- USE_DLFUNC(ifc_remove_host_routes)
- return ifc_remove_host_routes(ifname);
-}
-
-int32_t NetUtils::do_ifc_remove_default_route(const char *ifname)
-{
- USE_DLFUNC(ifc_remove_default_route)
- return ifc_remove_default_route(ifname);
-}
-
-int32_t NetUtils::do_dhcp_stop(const char *ifname)
-{
- USE_DLFUNC(dhcp_stop)
- return dhcp_stop(ifname);
-}
-
-int32_t NetUtils::do_dhcp_do_request(const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns1,
- char *dns2,
- char *server,
- uint32_t *lease,
- char* vendorinfo)
-{
- int32_t ret = -1;
- uint32_t sdkVersion = SdkVersion();
-
- if (sdkVersion == 15) {
- // ICS
- // http://androidxref.com/4.0.4/xref/system/core/libnetutils/dhcp_utils.c#149
- DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*, uint32_t*, char*, char*, char*, uint32_t*)
- USE_DLFUNC(dhcp_do_request)
- vendorinfo[0] = '\0';
-
- ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns1, dns2,
- server, lease);
- } else if (sdkVersion == 16 || sdkVersion == 17) {
- // JB 4.1 and 4.2
- // http://androidxref.com/4.1.2/xref/system/core/libnetutils/dhcp_utils.c#175
- // http://androidxref.com/4.2.2_r1/xref/system/core/include/netutils/dhcp.h#26
- DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*, uint32_t*, char*, char*, char*, uint32_t*, char*)
- USE_DLFUNC(dhcp_do_request)
- ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns1, dns2,
- server, lease, vendorinfo);
- } else if (sdkVersion == 18) {
- // JB 4.3
- // http://androidxref.com/4.3_r2.1/xref/system/core/libnetutils/dhcp_utils.c#181
- DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*, uint32_t*, char**, char*, uint32_t*, char*, char*)
- USE_DLFUNC(dhcp_do_request)
- char *dns[3] = {dns1, dns2, nullptr};
- char domains[Property::VALUE_MAX_LENGTH];
- ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns,
- server, lease, vendorinfo, domains);
- } else if (sdkVersion >= 19) {
- // KitKat 4.4.X
- // http://androidxref.com/4.4_r1/xref/system/core/libnetutils/dhcp_utils.c#18
- // Lollipop 5.0
- //http://androidxref.com/5.0.0_r2/xref/system/core/libnetutils/dhcp_utils.c#186
- DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*, uint32_t*, char**, char*, uint32_t*, char*, char*, char*)
- USE_DLFUNC(dhcp_do_request)
- char *dns[3] = {dns1, dns2, nullptr};
- char domains[Property::VALUE_MAX_LENGTH];
- char mtu[Property::VALUE_MAX_LENGTH];
- ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorinfo, domains, mtu);
- } else {
- NS_WARNING("Unable to perform do_dhcp_request: unsupported sdk version!");
- }
- return ret;
-}
diff --git a/dom/network/NetUtils.h b/dom/network/NetUtils.h
deleted file mode 100644
index 4af365406..000000000
--- a/dom/network/NetUtils.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Abstraction on top of the network support from libnetutils that we
- * use to set up network connections.
- */
-
-#ifndef NetUtils_h
-#define NetUtils_h
-
-#include "arpa/inet.h"
-
-// Copied from ifc.h
-#define RESET_IPV4_ADDRESSES 0x01
-#define RESET_IPV6_ADDRESSES 0x02
-#define RESET_ALL_ADDRESSES (RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES)
-
-// Implements netutils functions. No need for an abstract class here since we
-// only have a one sdk specific method (dhcp_do_request)
-class NetUtils
-{
-public:
- static void* GetSharedLibrary();
-
- NetUtils();
-
- int32_t do_ifc_enable(const char *ifname);
- int32_t do_ifc_disable(const char *ifname);
- int32_t do_ifc_configure(const char *ifname,
- in_addr_t address,
- uint32_t prefixLength,
- in_addr_t gateway,
- in_addr_t dns1,
- in_addr_t dns2);
- int32_t do_ifc_reset_connections(const char *ifname, const int32_t resetMask);
- int32_t do_ifc_set_default_route(const char *ifname, in_addr_t gateway);
- int32_t do_ifc_add_route(const char *ifname,
- const char *dst,
- uint32_t prefixLength,
- const char *gateway);
- int32_t do_ifc_remove_route(const char *ifname,
- const char *dst,
- uint32_t prefixLength,
- const char *gateway);
- int32_t do_ifc_remove_host_routes(const char *ifname);
- int32_t do_ifc_remove_default_route(const char *ifname);
- int32_t do_dhcp_stop(const char *ifname);
- int32_t do_dhcp_do_request(const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns1,
- char *dns2,
- char *server,
- uint32_t *lease,
- char* vendorinfo);
-
- static int32_t SdkVersion();
-};
-
-// Defines a function type with the right arguments and return type.
-#define DEFINE_DLFUNC(name, ret, args...) typedef ret (*FUNC##name)(args);
-
-// Set up a dlsymed function ready to use.
-#define USE_DLFUNC(name) \
- FUNC##name name = (FUNC##name) dlsym(GetSharedLibrary(), #name); \
- if (!name) { \
- MOZ_CRASH("Symbol not found in shared library : " #name); \
- }
-
-#endif // NetUtils_h
diff --git a/dom/network/NetworkStatsDB.jsm b/dom/network/NetworkStatsDB.jsm
deleted file mode 100644
index aa74d40ad..000000000
--- a/dom/network/NetworkStatsDB.jsm
+++ /dev/null
@@ -1,1285 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ['NetworkStatsDB'];
-
-const DEBUG = false;
-function debug(s) { dump("-*- NetworkStatsDB: " + s + "\n"); }
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
-Cu.importGlobalProperties(["indexedDB"]);
-
-XPCOMUtils.defineLazyServiceGetter(this, "appsService",
- "@mozilla.org/AppsService;1",
- "nsIAppsService");
-
-const DB_NAME = "net_stats";
-const DB_VERSION = 9;
-const DEPRECATED_STATS_STORE_NAME =
- [
- "net_stats_v2", // existed only in DB version 2
- "net_stats", // existed in DB version 1 and 3 to 5
- "net_stats_store", // existed in DB version 6 to 8
- ];
-const STATS_STORE_NAME = "net_stats_store_v3"; // since DB version 9
-const ALARMS_STORE_NAME = "net_alarm";
-
-// Constant defining the maximum values allowed per interface. If more, older
-// will be erased.
-const VALUES_MAX_LENGTH = 6 * 30;
-
-// Constant defining the rate of the samples. Daily.
-const SAMPLE_RATE = 1000 * 60 * 60 * 24;
-
-this.NetworkStatsDB = function NetworkStatsDB() {
- if (DEBUG) {
- debug("Constructor");
- }
- this.initDBHelper(DB_NAME, DB_VERSION, [STATS_STORE_NAME, ALARMS_STORE_NAME]);
-}
-
-NetworkStatsDB.prototype = {
- __proto__: IndexedDBHelper.prototype,
-
- dbNewTxn: function dbNewTxn(store_name, txn_type, callback, txnCb) {
- function successCb(result) {
- txnCb(null, result);
- }
- function errorCb(error) {
- txnCb(error, null);
- }
- return this.newTxn(txn_type, store_name, callback, successCb, errorCb);
- },
-
- /**
- * The onupgradeneeded handler of the IDBOpenDBRequest.
- * This function is called in IndexedDBHelper open() method.
- *
- * @param {IDBTransaction} aTransaction
- * {IDBDatabase} aDb
- * {64-bit integer} aOldVersion The version number on local storage.
- * {64-bit integer} aNewVersion The version number to be upgraded to.
- *
- * @note Be careful with the database upgrade pattern.
- * Because IndexedDB operations are performed asynchronously, we must
- * apply a recursive approach instead of an iterative approach while
- * upgrading versions.
- */
- upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
- if (DEBUG) {
- debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
- }
- let db = aDb;
- let objectStore;
-
- // An array of upgrade functions for each version.
- let upgradeSteps = [
- function upgrade0to1() {
- if (DEBUG) debug("Upgrade 0 to 1: Create object stores and indexes.");
-
- // Create the initial database schema.
- objectStore = db.createObjectStore(DEPRECATED_STATS_STORE_NAME[1],
- { keyPath: ["connectionType", "timestamp"] });
- objectStore.createIndex("connectionType", "connectionType", { unique: false });
- objectStore.createIndex("timestamp", "timestamp", { unique: false });
- objectStore.createIndex("rxBytes", "rxBytes", { unique: false });
- objectStore.createIndex("txBytes", "txBytes", { unique: false });
- objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
- objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
-
- upgradeNextVersion();
- },
-
- function upgrade1to2() {
- if (DEBUG) debug("Upgrade 1 to 2: Do nothing.");
- upgradeNextVersion();
- },
-
- function upgrade2to3() {
- if (DEBUG) debug("Upgrade 2 to 3: Add keyPath appId to object store.");
-
- // In order to support per-app traffic data storage, the original
- // objectStore needs to be replaced by a new objectStore with new
- // key path ("appId") and new index ("appId").
- // Also, since now networks are identified by their
- // [networkId, networkType] not just by their connectionType,
- // to modify the keyPath is mandatory to delete the object store
- // and create it again. Old data is going to be deleted because the
- // networkId for each sample can not be set.
-
- // In version 1.2 objectStore name was 'net_stats_v2', to avoid errors when
- // upgrading from 1.2 to 1.3 objectStore name should be checked.
- let stores = db.objectStoreNames;
- let deprecatedName = DEPRECATED_STATS_STORE_NAME[0];
- let storeName = DEPRECATED_STATS_STORE_NAME[1];
- if(stores.contains(deprecatedName)) {
- // Delete the obsolete stats store.
- db.deleteObjectStore(deprecatedName);
- } else {
- // Re-create stats object store without copying records.
- db.deleteObjectStore(storeName);
- }
-
- objectStore = db.createObjectStore(storeName, { keyPath: ["appId", "network", "timestamp"] });
- objectStore.createIndex("appId", "appId", { unique: false });
- objectStore.createIndex("network", "network", { unique: false });
- objectStore.createIndex("networkType", "networkType", { unique: false });
- objectStore.createIndex("timestamp", "timestamp", { unique: false });
- objectStore.createIndex("rxBytes", "rxBytes", { unique: false });
- objectStore.createIndex("txBytes", "txBytes", { unique: false });
- objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
- objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
-
- upgradeNextVersion();
- },
-
- function upgrade3to4() {
- if (DEBUG) debug("Upgrade 3 to 4: Delete redundant indexes.");
-
- // Delete redundant indexes (leave "network" only).
- objectStore = aTransaction.objectStore(DEPRECATED_STATS_STORE_NAME[1]);
- if (objectStore.indexNames.contains("appId")) {
- objectStore.deleteIndex("appId");
- }
- if (objectStore.indexNames.contains("networkType")) {
- objectStore.deleteIndex("networkType");
- }
- if (objectStore.indexNames.contains("timestamp")) {
- objectStore.deleteIndex("timestamp");
- }
- if (objectStore.indexNames.contains("rxBytes")) {
- objectStore.deleteIndex("rxBytes");
- }
- if (objectStore.indexNames.contains("txBytes")) {
- objectStore.deleteIndex("txBytes");
- }
- if (objectStore.indexNames.contains("rxTotalBytes")) {
- objectStore.deleteIndex("rxTotalBytes");
- }
- if (objectStore.indexNames.contains("txTotalBytes")) {
- objectStore.deleteIndex("txTotalBytes");
- }
-
- upgradeNextVersion();
- },
-
- function upgrade4to5() {
- if (DEBUG) debug("Upgrade 4 to 5: Create object store for alarms.");
-
- // In order to manage alarms, it is necessary to use a global counter
- // (totalBytes) that will increase regardless of the system reboot.
- objectStore = aTransaction.objectStore(DEPRECATED_STATS_STORE_NAME[1]);
-
- // Now, systemBytes will hold the old totalBytes and totalBytes will
- // keep the increasing counter. |counters| will keep the track of
- // accumulated values.
- let counters = {};
-
- objectStore.openCursor().onsuccess = function(event) {
- let cursor = event.target.result;
- if (!cursor){
- // upgrade4to5 completed now.
- upgradeNextVersion();
- return;
- }
-
- cursor.value.rxSystemBytes = cursor.value.rxTotalBytes;
- cursor.value.txSystemBytes = cursor.value.txTotalBytes;
-
- if (cursor.value.appId == 0) {
- let netId = cursor.value.network[0] + '' + cursor.value.network[1];
- if (!counters[netId]) {
- counters[netId] = {
- rxCounter: 0,
- txCounter: 0,
- lastRx: 0,
- lastTx: 0
- };
- }
-
- let rxDiff = cursor.value.rxSystemBytes - counters[netId].lastRx;
- let txDiff = cursor.value.txSystemBytes - counters[netId].lastTx;
- if (rxDiff < 0 || txDiff < 0) {
- // System reboot between samples, so take the current one.
- rxDiff = cursor.value.rxSystemBytes;
- txDiff = cursor.value.txSystemBytes;
- }
-
- counters[netId].rxCounter += rxDiff;
- counters[netId].txCounter += txDiff;
- cursor.value.rxTotalBytes = counters[netId].rxCounter;
- cursor.value.txTotalBytes = counters[netId].txCounter;
-
- counters[netId].lastRx = cursor.value.rxSystemBytes;
- counters[netId].lastTx = cursor.value.txSystemBytes;
- } else {
- cursor.value.rxTotalBytes = cursor.value.rxSystemBytes;
- cursor.value.txTotalBytes = cursor.value.txSystemBytes;
- }
-
- cursor.update(cursor.value);
- cursor.continue();
- };
-
- // Create object store for alarms.
- objectStore = db.createObjectStore(ALARMS_STORE_NAME, { keyPath: "id", autoIncrement: true });
- objectStore.createIndex("alarm", ['networkId','threshold'], { unique: false });
- objectStore.createIndex("manifestURL", "manifestURL", { unique: false });
- },
-
- function upgrade5to6() {
- if (DEBUG) debug("Upgrade 5 to 6: Add keyPath serviceType to object store.");
-
- // In contrast to "per-app" traffic data, "system-only" traffic data
- // refers to data which can not be identified by any applications.
- // To further support "system-only" data storage, the data can be
- // saved by service type (e.g., Tethering, OTA). Thus it's needed to
- // have a new key ("serviceType") for the ojectStore.
- let newObjectStore;
- let deprecatedName = DEPRECATED_STATS_STORE_NAME[1];
- newObjectStore = db.createObjectStore(DEPRECATED_STATS_STORE_NAME[2],
- { keyPath: ["appId", "serviceType", "network", "timestamp"] });
- newObjectStore.createIndex("network", "network", { unique: false });
-
- // Copy the data from the original objectStore to the new objectStore.
- objectStore = aTransaction.objectStore(deprecatedName);
- objectStore.openCursor().onsuccess = function(event) {
- let cursor = event.target.result;
- if (!cursor) {
- db.deleteObjectStore(deprecatedName);
- // upgrade5to6 completed now.
- upgradeNextVersion();
- return;
- }
-
- let newStats = cursor.value;
- newStats.serviceType = "";
- newObjectStore.put(newStats);
- cursor.continue();
- };
- },
-
- function upgrade6to7() {
- if (DEBUG) debug("Upgrade 6 to 7: Replace alarm threshold by relativeThreshold.");
-
- // Replace threshold attribute of alarm index by relativeThreshold in alarms DB.
- // Now alarms are indexed by relativeThreshold, which is the threshold relative
- // to current system stats.
- let alarmsStore = aTransaction.objectStore(ALARMS_STORE_NAME);
-
- // Delete "alarm" index.
- if (alarmsStore.indexNames.contains("alarm")) {
- alarmsStore.deleteIndex("alarm");
- }
-
- // Create new "alarm" index.
- alarmsStore.createIndex("alarm", ['networkId','relativeThreshold'], { unique: false });
-
- // Populate new "alarm" index attributes.
- alarmsStore.openCursor().onsuccess = function(event) {
- let cursor = event.target.result;
- if (!cursor) {
- upgrade6to7_updateTotalBytes();
- return;
- }
-
- cursor.value.relativeThreshold = cursor.value.threshold;
- cursor.value.absoluteThreshold = cursor.value.threshold;
- delete cursor.value.threshold;
-
- cursor.update(cursor.value);
- cursor.continue();
- }
-
- function upgrade6to7_updateTotalBytes() {
- if (DEBUG) debug("Upgrade 6 to 7: Update TotalBytes.");
- // Previous versions save accumulative totalBytes, increasing although the system
- // reboots or resets stats. But is necessary to reset the total counters when reset
- // through 'clearInterfaceStats'.
- let statsStore = aTransaction.objectStore(DEPRECATED_STATS_STORE_NAME[2]);
- let networks = [];
-
- // Find networks stored in the database.
- statsStore.index("network").openKeyCursor(null, "nextunique").onsuccess = function(event) {
- let cursor = event.target.result;
-
- // Store each network into an array.
- if (cursor) {
- networks.push(cursor.key);
- cursor.continue();
- return;
- }
-
- // Start to deal with each network.
- let pending = networks.length;
-
- if (pending === 0) {
- // Found no records of network. upgrade6to7 completed now.
- upgradeNextVersion();
- return;
- }
-
- networks.forEach(function(network) {
- let lowerFilter = [0, "", network, 0];
- let upperFilter = [0, "", network, ""];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
-
- // Find number of samples for a given network.
- statsStore.count(range).onsuccess = function(event) {
- let recordCount = event.target.result;
-
- // If there are more samples than the max allowed, there is no way to know
- // when does reset take place.
- if (recordCount === 0 || recordCount >= VALUES_MAX_LENGTH) {
- pending--;
- if (pending === 0) {
- upgradeNextVersion();
- }
- return;
- }
-
- let last = null;
- // Reset detected if the first sample totalCounters are different than bytes
- // counters. If so, the total counters should be recalculated.
- statsStore.openCursor(range).onsuccess = function(event) {
- let cursor = event.target.result;
- if (!cursor) {
- pending--;
- if (pending === 0) {
- upgradeNextVersion();
- }
- return;
- }
- if (!last) {
- if (cursor.value.rxTotalBytes == cursor.value.rxBytes &&
- cursor.value.txTotalBytes == cursor.value.txBytes) {
- pending--;
- if (pending === 0) {
- upgradeNextVersion();
- }
- return;
- }
-
- cursor.value.rxTotalBytes = cursor.value.rxBytes;
- cursor.value.txTotalBytes = cursor.value.txBytes;
- cursor.update(cursor.value);
- last = cursor.value;
- cursor.continue();
- return;
- }
-
- // Recalculate the total counter for last / current sample
- cursor.value.rxTotalBytes = last.rxTotalBytes + cursor.value.rxBytes;
- cursor.value.txTotalBytes = last.txTotalBytes + cursor.value.txBytes;
- cursor.update(cursor.value);
- last = cursor.value;
- cursor.continue();
- }
- }
- }, this); // end of networks.forEach()
- }; // end of statsStore.index("network").openKeyCursor().onsuccess callback
- } // end of function upgrade6to7_updateTotalBytes
- },
-
- function upgrade7to8() {
- if (DEBUG) debug("Upgrade 7 to 8: Create index serviceType.");
-
- // Create index for 'ServiceType' in order to make it retrievable.
- let statsStore = aTransaction.objectStore(DEPRECATED_STATS_STORE_NAME[2]);
- statsStore.createIndex("serviceType", "serviceType", { unique: false });
-
- upgradeNextVersion();
- },
-
- function upgrade8to9() {
- if (DEBUG) debug("Upgrade 8 to 9: Add keyPath isInBrowser to " +
- "network stats object store");
-
- // Since B2G v2.0, there is no stand-alone browser app anymore.
- // The browser app is a mozbrowser iframe element owned by system app.
- // In order to separate traffic generated from system and browser, we
- // have to add a new attribute |isInBrowser| as keyPath.
- // Refer to bug 1070944 for more detail.
- let newObjectStore;
- let deprecatedName = DEPRECATED_STATS_STORE_NAME[2];
- newObjectStore = db.createObjectStore(STATS_STORE_NAME,
- { keyPath: ["appId", "isInBrowser", "serviceType",
- "network", "timestamp"] });
- newObjectStore.createIndex("network", "network", { unique: false });
- newObjectStore.createIndex("serviceType", "serviceType", { unique: false });
-
- // Copy records from the current object store to the new one.
- objectStore = aTransaction.objectStore(deprecatedName);
- objectStore.openCursor().onsuccess = function (event) {
- let cursor = event.target.result;
- if (!cursor) {
- db.deleteObjectStore(deprecatedName);
- // upgrade8to9 completed now.
- return;
- }
- let newStats = cursor.value;
- // Augment records by adding the new isInBrowser attribute.
- // Notes:
- // 1. Key value cannot be boolean type. Use 1/0 instead of true/false.
- // 2. Most traffic of system app should come from its browser iframe,
- // thus assign isInBrowser as 1 for system app.
- let manifestURL = appsService.getManifestURLByLocalId(newStats.appId);
- if (manifestURL && manifestURL.search(/app:\/\/system\./) === 0) {
- newStats.isInBrowser = 1;
- } else {
- newStats.isInBrowser = 0;
- }
- newObjectStore.put(newStats);
- cursor.continue();
- };
- }
- ];
-
- let index = aOldVersion;
- let outer = this;
-
- function upgradeNextVersion() {
- if (index == aNewVersion) {
- debug("Upgrade finished.");
- return;
- }
-
- try {
- var i = index++;
- if (DEBUG) debug("Upgrade step: " + i + "\n");
- upgradeSteps[i].call(outer);
- } catch (ex) {
- dump("Caught exception " + ex);
- throw ex;
- return;
- }
- }
-
- if (aNewVersion > upgradeSteps.length) {
- debug("No migration steps for the new version!");
- aTransaction.abort();
- return;
- }
-
- upgradeNextVersion();
- },
-
- importData: function importData(aStats) {
- let stats = { appId: aStats.appId,
- isInBrowser: aStats.isInBrowser ? 1 : 0,
- serviceType: aStats.serviceType,
- network: [aStats.networkId, aStats.networkType],
- timestamp: aStats.timestamp,
- rxBytes: aStats.rxBytes,
- txBytes: aStats.txBytes,
- rxSystemBytes: aStats.rxSystemBytes,
- txSystemBytes: aStats.txSystemBytes,
- rxTotalBytes: aStats.rxTotalBytes,
- txTotalBytes: aStats.txTotalBytes };
-
- return stats;
- },
-
- exportData: function exportData(aStats) {
- let stats = { appId: aStats.appId,
- isInBrowser: aStats.isInBrowser ? true : false,
- serviceType: aStats.serviceType,
- networkId: aStats.network[0],
- networkType: aStats.network[1],
- timestamp: aStats.timestamp,
- rxBytes: aStats.rxBytes,
- txBytes: aStats.txBytes,
- rxTotalBytes: aStats.rxTotalBytes,
- txTotalBytes: aStats.txTotalBytes };
-
- return stats;
- },
-
- normalizeDate: function normalizeDate(aDate) {
- // Convert to UTC according to timezone and
- // filter timestamp to get SAMPLE_RATE precission
- let timestamp = aDate.getTime() - aDate.getTimezoneOffset() * 60 * 1000;
- timestamp = Math.floor(timestamp / SAMPLE_RATE) * SAMPLE_RATE;
- return timestamp;
- },
-
- saveStats: function saveStats(aStats, aResultCb) {
- let isAccumulative = aStats.isAccumulative;
- let timestamp = this.normalizeDate(aStats.date);
-
- let stats = { appId: aStats.appId,
- isInBrowser: aStats.isInBrowser,
- serviceType: aStats.serviceType,
- networkId: aStats.networkId,
- networkType: aStats.networkType,
- timestamp: timestamp,
- rxBytes: isAccumulative ? 0 : aStats.rxBytes,
- txBytes: isAccumulative ? 0 : aStats.txBytes,
- rxSystemBytes: isAccumulative ? aStats.rxBytes : 0,
- txSystemBytes: isAccumulative ? aStats.txBytes : 0,
- rxTotalBytes: isAccumulative ? aStats.rxBytes : 0,
- txTotalBytes: isAccumulative ? aStats.txBytes : 0 };
-
- stats = this.importData(stats);
-
- this.dbNewTxn(STATS_STORE_NAME, "readwrite", function(aTxn, aStore) {
- if (DEBUG) {
- debug("Filtered time: " + new Date(timestamp));
- debug("New stats: " + JSON.stringify(stats));
- }
-
- let lowerFilter = [stats.appId, stats.isInBrowser, stats.serviceType,
- stats.network, 0];
- let upperFilter = [stats.appId, stats.isInBrowser, stats.serviceType,
- stats.network, ""];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
-
- let request = aStore.openCursor(range, 'prev');
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (!cursor) {
- // Empty, so save first element.
-
- if (!isAccumulative) {
- this._saveStats(aTxn, aStore, stats);
- return;
- }
-
- // There could be a time delay between the point when the network
- // interface comes up and the point when the database is initialized.
- // In this short interval some traffic data are generated but are not
- // registered by the first sample.
- stats.rxBytes = stats.rxTotalBytes;
- stats.txBytes = stats.txTotalBytes;
-
- // However, if the interface is not switched on after the database is
- // initialized (dual sim use case) stats should be set to 0.
- let req = aStore.index("network").openKeyCursor(null, "nextunique");
- req.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- if (cursor.key[1] == stats.network[1]) {
- stats.rxBytes = 0;
- stats.txBytes = 0;
- this._saveStats(aTxn, aStore, stats);
- return;
- }
-
- cursor.continue();
- return;
- }
-
- this._saveStats(aTxn, aStore, stats);
- }.bind(this);
-
- return;
- }
-
- // There are old samples
- if (DEBUG) {
- debug("Last value " + JSON.stringify(cursor.value));
- }
-
- // Remove stats previous to now - VALUE_MAX_LENGTH
- this._removeOldStats(aTxn, aStore, stats.appId, stats.isInBrowser,
- stats.serviceType, stats.network, stats.timestamp);
-
- // Process stats before save
- this._processSamplesDiff(aTxn, aStore, cursor, stats, isAccumulative);
- }.bind(this);
- }.bind(this), aResultCb);
- },
-
- /*
- * This function check that stats are saved in the database following the sample rate.
- * In this way is easier to find elements when stats are requested.
- */
- _processSamplesDiff: function _processSamplesDiff(aTxn,
- aStore,
- aLastSampleCursor,
- aNewSample,
- aIsAccumulative) {
- let lastSample = aLastSampleCursor.value;
-
- // Get difference between last and new sample.
- let diff = (aNewSample.timestamp - lastSample.timestamp) / SAMPLE_RATE;
- if (diff % 1) {
- // diff is decimal, so some error happened because samples are stored as a multiple
- // of SAMPLE_RATE
- aTxn.abort();
- throw new Error("Error processing samples");
- }
-
- if (DEBUG) {
- debug("New: " + aNewSample.timestamp + " - Last: " +
- lastSample.timestamp + " - diff: " + diff);
- }
-
- // If the incoming data has a accumulation feature, the new
- // |txBytes|/|rxBytes| is assigend by differnces between the new
- // |txTotalBytes|/|rxTotalBytes| and the last |txTotalBytes|/|rxTotalBytes|.
- // Else, if incoming data is non-accumulative, the |txBytes|/|rxBytes|
- // is the new |txBytes|/|rxBytes|.
- let rxDiff = 0;
- let txDiff = 0;
- if (aIsAccumulative) {
- rxDiff = aNewSample.rxSystemBytes - lastSample.rxSystemBytes;
- txDiff = aNewSample.txSystemBytes - lastSample.txSystemBytes;
- if (rxDiff < 0 || txDiff < 0) {
- rxDiff = aNewSample.rxSystemBytes;
- txDiff = aNewSample.txSystemBytes;
- }
- aNewSample.rxBytes = rxDiff;
- aNewSample.txBytes = txDiff;
-
- aNewSample.rxTotalBytes = lastSample.rxTotalBytes + rxDiff;
- aNewSample.txTotalBytes = lastSample.txTotalBytes + txDiff;
- } else {
- rxDiff = aNewSample.rxBytes;
- txDiff = aNewSample.txBytes;
- }
-
- if (diff == 1) {
- // New element.
-
- // If the incoming data is non-accumulative, the new
- // |rxTotalBytes|/|txTotalBytes| needs to be updated by adding new
- // |rxBytes|/|txBytes| to the last |rxTotalBytes|/|txTotalBytes|.
- if (!aIsAccumulative) {
- aNewSample.rxTotalBytes = aNewSample.rxBytes + lastSample.rxTotalBytes;
- aNewSample.txTotalBytes = aNewSample.txBytes + lastSample.txTotalBytes;
- }
-
- this._saveStats(aTxn, aStore, aNewSample);
- return;
- }
- if (diff > 1) {
- // Some samples lost. Device off during one or more samplerate periods.
- // Time or timezone changed
- // Add lost samples with 0 bytes and the actual one.
- if (diff > VALUES_MAX_LENGTH) {
- diff = VALUES_MAX_LENGTH;
- }
-
- let data = [];
- for (let i = diff - 2; i >= 0; i--) {
- let time = aNewSample.timestamp - SAMPLE_RATE * (i + 1);
- let sample = { appId: aNewSample.appId,
- isInBrowser: aNewSample.isInBrowser,
- serviceType: aNewSample.serviceType,
- network: aNewSample.network,
- timestamp: time,
- rxBytes: 0,
- txBytes: 0,
- rxSystemBytes: lastSample.rxSystemBytes,
- txSystemBytes: lastSample.txSystemBytes,
- rxTotalBytes: lastSample.rxTotalBytes,
- txTotalBytes: lastSample.txTotalBytes };
-
- data.push(sample);
- }
-
- data.push(aNewSample);
- this._saveStats(aTxn, aStore, data);
- return;
- }
- if (diff == 0 || diff < 0) {
- // New element received before samplerate period. It means that device has
- // been restarted (or clock / timezone change).
- // Update element. If diff < 0, clock or timezone changed back. Place data
- // in the last sample.
-
- // Old |rxTotalBytes|/|txTotalBytes| needs to get updated by adding the
- // last |rxTotalBytes|/|txTotalBytes|.
- lastSample.rxBytes += rxDiff;
- lastSample.txBytes += txDiff;
- lastSample.rxSystemBytes = aNewSample.rxSystemBytes;
- lastSample.txSystemBytes = aNewSample.txSystemBytes;
- lastSample.rxTotalBytes += rxDiff;
- lastSample.txTotalBytes += txDiff;
-
- if (DEBUG) {
- debug("Update: " + JSON.stringify(lastSample));
- }
- let req = aLastSampleCursor.update(lastSample);
- }
- },
-
- _saveStats: function _saveStats(aTxn, aStore, aNetworkStats) {
- if (DEBUG) {
- debug("_saveStats: " + JSON.stringify(aNetworkStats));
- }
-
- if (Array.isArray(aNetworkStats)) {
- let len = aNetworkStats.length - 1;
- for (let i = 0; i <= len; i++) {
- aStore.put(aNetworkStats[i]);
- }
- } else {
- aStore.put(aNetworkStats);
- }
- },
-
- _removeOldStats: function _removeOldStats(aTxn, aStore, aAppId, aIsInBrowser,
- aServiceType, aNetwork, aDate) {
- // Callback function to remove old items when new ones are added.
- let filterDate = aDate - (SAMPLE_RATE * VALUES_MAX_LENGTH - 1);
- let lowerFilter = [aAppId, aIsInBrowser, aServiceType, aNetwork, 0];
- let upperFilter = [aAppId, aIsInBrowser, aServiceType, aNetwork, filterDate];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
- let lastSample = null;
- let self = this;
-
- aStore.openCursor(range).onsuccess = function(event) {
- var cursor = event.target.result;
- if (cursor) {
- lastSample = cursor.value;
- cursor.delete();
- cursor.continue();
- return;
- }
-
- // If all samples for a network are removed, an empty sample
- // has to be saved to keep the totalBytes in order to compute
- // future samples because system counters are not set to 0.
- // Thus, if there are no samples left, the last sample removed
- // will be saved again after setting its bytes to 0.
- let request = aStore.index("network").openCursor(aNetwork);
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (!cursor && lastSample != null) {
- let timestamp = new Date();
- timestamp = self.normalizeDate(timestamp);
- lastSample.timestamp = timestamp;
- lastSample.rxBytes = 0;
- lastSample.txBytes = 0;
- self._saveStats(aTxn, aStore, lastSample);
- }
- };
- };
- },
-
- clearInterfaceStats: function clearInterfaceStats(aNetwork, aResultCb) {
- let network = [aNetwork.network.id, aNetwork.network.type];
- let self = this;
-
- // Clear and save an empty sample to keep sync with system counters
- this.dbNewTxn(STATS_STORE_NAME, "readwrite", function(aTxn, aStore) {
- let sample = null;
- let request = aStore.index("network").openCursor(network, "prev");
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- if (!sample && cursor.value.appId == 0) {
- sample = cursor.value;
- }
-
- cursor.delete();
- cursor.continue();
- return;
- }
-
- if (sample) {
- let timestamp = new Date();
- timestamp = self.normalizeDate(timestamp);
- sample.timestamp = timestamp;
- sample.appId = 0;
- sample.isInBrowser = 0;
- sample.serviceType = "";
- sample.rxBytes = 0;
- sample.txBytes = 0;
- sample.rxTotalBytes = 0;
- sample.txTotalBytes = 0;
-
- self._saveStats(aTxn, aStore, sample);
- }
- };
- }, this._resetAlarms.bind(this, aNetwork.networkId, aResultCb));
- },
-
- clearStats: function clearStats(aNetworks, aResultCb) {
- let index = 0;
- let stats = [];
- let self = this;
-
- let callback = function(aError, aResult) {
- index++;
-
- if (!aError && index < aNetworks.length) {
- self.clearInterfaceStats(aNetworks[index], callback);
- return;
- }
-
- aResultCb(aError, aResult);
- };
-
- if (!aNetworks[index]) {
- aResultCb(null, true);
- return;
- }
- this.clearInterfaceStats(aNetworks[index], callback);
- },
-
- getCurrentStats: function getCurrentStats(aNetwork, aDate, aResultCb) {
- if (DEBUG) {
- debug("Get current stats for " + JSON.stringify(aNetwork) + " since " + aDate);
- }
-
- let network = [aNetwork.id, aNetwork.type];
- if (aDate) {
- this._getCurrentStatsFromDate(network, aDate, aResultCb);
- return;
- }
-
- this._getCurrentStats(network, aResultCb);
- },
-
- _getCurrentStats: function _getCurrentStats(aNetwork, aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(txn, store) {
- let request = null;
- let upperFilter = [0, 1, "", aNetwork, Date.now()];
- let range = IDBKeyRange.upperBound(upperFilter, false);
- let result = { rxBytes: 0, txBytes: 0,
- rxTotalBytes: 0, txTotalBytes: 0 };
-
- request = store.openCursor(range, "prev");
-
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- result.rxBytes = result.rxTotalBytes = cursor.value.rxTotalBytes;
- result.txBytes = result.txTotalBytes = cursor.value.txTotalBytes;
- }
-
- txn.result = result;
- };
- }.bind(this), aResultCb);
- },
-
- _getCurrentStatsFromDate: function _getCurrentStatsFromDate(aNetwork, aDate, aResultCb) {
- aDate = new Date(aDate);
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(txn, store) {
- let request = null;
- let start = this.normalizeDate(aDate);
- let upperFilter = [0, 1, "", aNetwork, Date.now()];
- let range = IDBKeyRange.upperBound(upperFilter, false);
- let result = { rxBytes: 0, txBytes: 0,
- rxTotalBytes: 0, txTotalBytes: 0 };
-
- request = store.openCursor(range, "prev");
-
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- result.rxBytes = result.rxTotalBytes = cursor.value.rxTotalBytes;
- result.txBytes = result.txTotalBytes = cursor.value.txTotalBytes;
- }
-
- let timestamp = cursor.value.timestamp;
- let range = IDBKeyRange.lowerBound(lowerFilter, false);
- request = store.openCursor(range);
-
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- if (cursor.value.timestamp == timestamp) {
- // There is one sample only.
- result.rxBytes = cursor.value.rxBytes;
- result.txBytes = cursor.value.txBytes;
- } else {
- result.rxBytes -= cursor.value.rxTotalBytes;
- result.txBytes -= cursor.value.txTotalBytes;
- }
- }
-
- txn.result = result;
- };
- };
- }.bind(this), aResultCb);
- },
-
- find: function find(aResultCb, aAppId, aBrowsingTrafficOnly, aServiceType,
- aNetwork, aStart, aEnd, aAppManifestURL) {
- let offset = (new Date()).getTimezoneOffset() * 60 * 1000;
- let start = this.normalizeDate(aStart);
- let end = this.normalizeDate(aEnd);
-
- if (DEBUG) {
- debug("Find samples for appId: " + aAppId +
- " browsingTrafficOnly: " + aBrowsingTrafficOnly +
- " serviceType: " + aServiceType +
- " network: " + JSON.stringify(aNetwork) + " from " + start +
- " until " + end);
- debug("Start time: " + new Date(start));
- debug("End time: " + new Date(end));
- }
-
- // Find samples of browsing traffic (isInBrowser = 1) first since they are
- // needed no matter browsingTrafficOnly is true or false.
- // We have to make two queries to database because we cannot filter correct
- // records by a single query that sets ranges for two keys (isInBrowser and
- // timestamp). We think it is because the keyPath contains an array
- // (network) so such query does not work.
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- let network = [aNetwork.id, aNetwork.type];
- let lowerFilter = [aAppId, 1, aServiceType, network, start];
- let upperFilter = [aAppId, 1, aServiceType, network, end];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
-
- let data = [];
-
- if (!aTxn.result) {
- aTxn.result = {};
- }
- aTxn.result.appManifestURL = aAppManifestURL;
- aTxn.result.browsingTrafficOnly = aBrowsingTrafficOnly;
- aTxn.result.serviceType = aServiceType;
- aTxn.result.network = aNetwork;
- aTxn.result.start = aStart;
- aTxn.result.end = aEnd;
-
- let request = aStore.openCursor(range).onsuccess = function(event) {
- var cursor = event.target.result;
- if (cursor){
- // We use rxTotalBytes/txTotalBytes instead of rxBytes/txBytes for
- // the first (oldest) sample. The rx/txTotalBytes fields record
- // accumulative usage amount, which means even if old samples were
- // expired and removed from the Database, we can still obtain the
- // correct network usage.
- if (data.length == 0) {
- data.push({ rxBytes: cursor.value.rxTotalBytes,
- txBytes: cursor.value.txTotalBytes,
- date: new Date(cursor.value.timestamp + offset) });
- } else {
- data.push({ rxBytes: cursor.value.rxBytes,
- txBytes: cursor.value.txBytes,
- date: new Date(cursor.value.timestamp + offset) });
- }
- cursor.continue();
- return;
- }
-
- if (aBrowsingTrafficOnly) {
- this.fillResultSamples(start + offset, end + offset, data);
- aTxn.result.data = data;
- return;
- }
-
- // Find samples of app traffic (isInBrowser = 0) as well if
- // browsingTrafficOnly is false.
- lowerFilter = [aAppId, 0, aServiceType, network, start];
- upperFilter = [aAppId, 0, aServiceType, network, end];
- range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
- request = aStore.openCursor(range).onsuccess = function(event) {
- cursor = event.target.result;
- if (cursor) {
- var date = new Date(cursor.value.timestamp + offset);
- var foundData = data.find(function (element, index, array) {
- if (element.date.getTime() !== date.getTime()) {
- return false;
- }
- return element;
- }, date);
-
- if (foundData) {
- foundData.rxBytes += cursor.value.rxBytes;
- foundData.txBytes += cursor.value.txBytes;
- } else {
- // We use rxTotalBytes/txTotalBytes instead of rxBytes/txBytes
- // for the first (oldest) sample. The rx/txTotalBytes fields
- // record accumulative usage amount, which means even if old
- // samples were expired and removed from the Database, we can
- // still obtain the correct network usage.
- if (data.length == 0) {
- data.push({ rxBytes: cursor.value.rxTotalBytes,
- txBytes: cursor.value.txTotalBytes,
- date: new Date(cursor.value.timestamp + offset) });
- } else {
- data.push({ rxBytes: cursor.value.rxBytes,
- txBytes: cursor.value.txBytes,
- date: new Date(cursor.value.timestamp + offset) });
- }
- }
- cursor.continue();
- return;
- }
- this.fillResultSamples(start + offset, end + offset, data);
- aTxn.result.data = data;
- }.bind(this); // openCursor(range).onsuccess() callback
- }.bind(this); // openCursor(range).onsuccess() callback
- }.bind(this), aResultCb);
- },
-
- /*
- * Fill data array (samples from database) with empty samples to match
- * requested start / end dates.
- */
- fillResultSamples: function fillResultSamples(aStart, aEnd, aData) {
- if (aData.length == 0) {
- aData.push({ rxBytes: undefined,
- txBytes: undefined,
- date: new Date(aStart) });
- }
-
- while (aStart < aData[0].date.getTime()) {
- aData.unshift({ rxBytes: undefined,
- txBytes: undefined,
- date: new Date(aData[0].date.getTime() - SAMPLE_RATE) });
- }
-
- while (aEnd > aData[aData.length - 1].date.getTime()) {
- aData.push({ rxBytes: undefined,
- txBytes: undefined,
- date: new Date(aData[aData.length - 1].date.getTime() + SAMPLE_RATE) });
- }
- },
-
- getAvailableNetworks: function getAvailableNetworks(aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- if (!aTxn.result) {
- aTxn.result = [];
- }
-
- let request = aStore.index("network").openKeyCursor(null, "nextunique");
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- aTxn.result.push({ id: cursor.key[0],
- type: cursor.key[1] });
- cursor.continue();
- return;
- }
- };
- }, aResultCb);
- },
-
- isNetworkAvailable: function isNetworkAvailable(aNetwork, aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- if (!aTxn.result) {
- aTxn.result = false;
- }
-
- let network = [aNetwork.id, aNetwork.type];
- let request = aStore.index("network").openKeyCursor(IDBKeyRange.only(network));
- request.onsuccess = function onsuccess(event) {
- if (event.target.result) {
- aTxn.result = true;
- }
- };
- }, aResultCb);
- },
-
- getAvailableServiceTypes: function getAvailableServiceTypes(aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- if (!aTxn.result) {
- aTxn.result = [];
- }
-
- let request = aStore.index("serviceType").openKeyCursor(null, "nextunique");
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor && cursor.key != "") {
- aTxn.result.push({ serviceType: cursor.key });
- cursor.continue();
- return;
- }
- };
- }, aResultCb);
- },
-
- get sampleRate () {
- return SAMPLE_RATE;
- },
-
- get maxStorageSamples () {
- return VALUES_MAX_LENGTH;
- },
-
- logAllRecords: function logAllRecords(aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- aStore.mozGetAll().onsuccess = function onsuccess(event) {
- aTxn.result = event.target.result;
- };
- }, aResultCb);
- },
-
- alarmToRecord: function alarmToRecord(aAlarm) {
- let record = { networkId: aAlarm.networkId,
- absoluteThreshold: aAlarm.absoluteThreshold,
- relativeThreshold: aAlarm.relativeThreshold,
- startTime: aAlarm.startTime,
- data: aAlarm.data,
- manifestURL: aAlarm.manifestURL,
- pageURL: aAlarm.pageURL };
-
- if (aAlarm.id) {
- record.id = aAlarm.id;
- }
-
- return record;
- },
-
- recordToAlarm: function recordToalarm(aRecord) {
- let alarm = { networkId: aRecord.networkId,
- absoluteThreshold: aRecord.absoluteThreshold,
- relativeThreshold: aRecord.relativeThreshold,
- startTime: aRecord.startTime,
- data: aRecord.data,
- manifestURL: aRecord.manifestURL,
- pageURL: aRecord.pageURL };
-
- if (aRecord.id) {
- alarm.id = aRecord.id;
- }
-
- return alarm;
- },
-
- addAlarm: function addAlarm(aAlarm, aResultCb) {
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Going to add " + JSON.stringify(aAlarm));
- }
-
- let record = this.alarmToRecord(aAlarm);
- store.put(record).onsuccess = function setResult(aEvent) {
- txn.result = aEvent.target.result;
- if (DEBUG) {
- debug("Request successful. New record ID: " + txn.result);
- }
- };
- }.bind(this), aResultCb);
- },
-
- getFirstAlarm: function getFirstAlarm(aNetworkId, aResultCb) {
- let self = this;
-
- this.dbNewTxn(ALARMS_STORE_NAME, "readonly", function(txn, store) {
- if (DEBUG) {
- debug("Get first alarm for network " + aNetworkId);
- }
-
- let lowerFilter = [aNetworkId, 0];
- let upperFilter = [aNetworkId, ""];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter);
-
- store.index("alarm").openCursor(range).onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- txn.result = null;
- if (cursor) {
- txn.result = self.recordToAlarm(cursor.value);
- }
- };
- }, aResultCb);
- },
-
- removeAlarm: function removeAlarm(aAlarmId, aManifestURL, aResultCb) {
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Remove alarm " + aAlarmId);
- }
-
- store.get(aAlarmId).onsuccess = function onsuccess(event) {
- let record = event.target.result;
- txn.result = false;
- if (!record || (aManifestURL && record.manifestURL != aManifestURL)) {
- return;
- }
-
- store.delete(aAlarmId);
- txn.result = true;
- }
- }, aResultCb);
- },
-
- removeAlarms: function removeAlarms(aManifestURL, aResultCb) {
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Remove alarms of " + aManifestURL);
- }
-
- store.index("manifestURL").openCursor(aManifestURL)
- .onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- cursor.delete();
- cursor.continue();
- }
- }
- }, aResultCb);
- },
-
- updateAlarm: function updateAlarm(aAlarm, aResultCb) {
- let self = this;
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Update alarm " + aAlarm.id);
- }
-
- let record = self.alarmToRecord(aAlarm);
- store.openCursor(record.id).onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- txn.result = false;
- if (cursor) {
- cursor.update(record);
- txn.result = true;
- }
- }
- }, aResultCb);
- },
-
- getAlarms: function getAlarms(aNetworkId, aManifestURL, aResultCb) {
- let self = this;
- this.dbNewTxn(ALARMS_STORE_NAME, "readonly", function(txn, store) {
- if (DEBUG) {
- debug("Get alarms for " + aManifestURL);
- }
-
- txn.result = [];
- store.index("manifestURL").openCursor(aManifestURL)
- .onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (!cursor) {
- return;
- }
-
- if (!aNetworkId || cursor.value.networkId == aNetworkId) {
- txn.result.push(self.recordToAlarm(cursor.value));
- }
-
- cursor.continue();
- }
- }, aResultCb);
- },
-
- _resetAlarms: function _resetAlarms(aNetworkId, aResultCb) {
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Reset alarms for network " + aNetworkId);
- }
-
- let lowerFilter = [aNetworkId, 0];
- let upperFilter = [aNetworkId, ""];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter);
-
- store.index("alarm").openCursor(range).onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- if (cursor.value.startTime) {
- cursor.value.relativeThreshold = cursor.value.threshold;
- cursor.update(cursor.value);
- }
- cursor.continue();
- return;
- }
- };
- }, aResultCb);
- }
-};
diff --git a/dom/network/NetworkStatsManager.js b/dom/network/NetworkStatsManager.js
deleted file mode 100644
index b963aba2b..000000000
--- a/dom/network/NetworkStatsManager.js
+++ /dev/null
@@ -1,388 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const DEBUG = false;
-function debug(s) { dump("-*- NetworkStatsManager: " + s + "\n"); }
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-
-// Ensure NetworkStatsService and NetworkStatsDB are loaded in the parent process
-// to receive messages from the child processes.
-var appInfo = Cc["@mozilla.org/xre/app-info;1"];
-var isParentProcess = !appInfo || appInfo.getService(Ci.nsIXULRuntime)
- .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-if (isParentProcess) {
- Cu.import("resource://gre/modules/NetworkStatsService.jsm");
-}
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsISyncMessageSender");
-
-// NetworkStatsData
-const nsIClassInfo = Ci.nsIClassInfo;
-const NETWORKSTATSDATA_CID = Components.ID("{3b16fe17-5583-483a-b486-b64a3243221c}");
-
-function NetworkStatsData(aWindow, aData) {
- this.rxBytes = aData.rxBytes;
- this.txBytes = aData.txBytes;
- this.date = new aWindow.Date(aData.date.getTime());
-}
-
-NetworkStatsData.prototype = {
- classID : NETWORKSTATSDATA_CID,
-
- QueryInterface : XPCOMUtils.generateQI([])
-};
-
-// NetworkStatsInterface
-const NETWORKSTATSINTERFACE_CONTRACTID = "@mozilla.org/networkstatsinterface;1";
-const NETWORKSTATSINTERFACE_CID = Components.ID("{f540615b-d803-43ff-8200-2a9d145a5645}");
-
-function NetworkStatsInterface() {
- if (DEBUG) {
- debug("NetworkStatsInterface Constructor");
- }
-}
-
-NetworkStatsInterface.prototype = {
- __init: function(aNetwork) {
- this.type = aNetwork.type;
- this.id = aNetwork.id;
- },
-
- classID : NETWORKSTATSINTERFACE_CID,
-
- contractID: NETWORKSTATSINTERFACE_CONTRACTID,
- QueryInterface : XPCOMUtils.generateQI([])
-}
-
-// NetworkStats
-const NETWORKSTATS_CID = Components.ID("{28904f59-8497-4ac0-904f-2af14b7fd3de}");
-
-function NetworkStats(aWindow, aStats) {
- if (DEBUG) {
- debug("NetworkStats Constructor");
- }
- this.appManifestURL = aStats.appManifestURL || null;
- this.browsingTrafficOnly = aStats.browsingTrafficOnly || false;
- this.serviceType = aStats.serviceType || null;
- this.network = new aWindow.MozNetworkStatsInterface(aStats.network);
- this.start = aStats.start ? new aWindow.Date(aStats.start.getTime()) : null;
- this.end = aStats.end ? new aWindow.Date(aStats.end.getTime()) : null;
-
- let samples = this.data = new aWindow.Array();
- for (let i = 0; i < aStats.data.length; i++) {
- samples.push(aWindow.MozNetworkStatsData._create(
- aWindow, new NetworkStatsData(aWindow, aStats.data[i])));
- }
-}
-
-NetworkStats.prototype = {
- classID : NETWORKSTATS_CID,
-
- QueryInterface : XPCOMUtils.generateQI()
-}
-
-// NetworkStatsAlarm
-const NETWORKSTATSALARM_CID = Components.ID("{a93ea13e-409c-4189-9b1e-95fff220be55}");
-
-function NetworkStatsAlarm(aWindow, aAlarm) {
- this.alarmId = aAlarm.id;
- this.network = new aWindow.MozNetworkStatsInterface(aAlarm.network);
- this.threshold = aAlarm.threshold;
- this.data = aAlarm.data;
-}
-
-NetworkStatsAlarm.prototype = {
- classID : NETWORKSTATSALARM_CID,
-
- QueryInterface : XPCOMUtils.generateQI([])
-};
-
-// NetworkStatsManager
-
-const NETWORKSTATSMANAGER_CONTRACTID = "@mozilla.org/networkStatsManager;1";
-const NETWORKSTATSMANAGER_CID = Components.ID("{ceb874cd-cc1a-4e65-b404-cc2d3e42425f}");
-
-function NetworkStatsManager() {
- if (DEBUG) {
- debug("Constructor");
- }
-}
-
-NetworkStatsManager.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
-
- getSamples: function getSamples(aNetwork, aStart, aEnd, aOptions) {
- if (aStart > aEnd) {
- throw Components.results.NS_ERROR_INVALID_ARG;
- }
-
- // appManifestURL is used to query network statistics by app;
- // serviceType is used to query network statistics by system service.
- // It is illegal to specify both of them at the same time.
- if (aOptions.appManifestURL && aOptions.serviceType) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- }
- // browsingTrafficOnly is meaningful only when querying by app.
- if (!aOptions.appManifestURL && aOptions.browsingTrafficOnly) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- }
-
- let appManifestURL = aOptions.appManifestURL;
- let serviceType = aOptions.serviceType;
- let browsingTrafficOnly = aOptions.browsingTrafficOnly;
-
- // TODO Bug 929410 Date object cannot correctly pass through cpmm/ppmm IPC
- // This is just a work-around by passing timestamp numbers.
- aStart = aStart.getTime();
- aEnd = aEnd.getTime();
-
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:Get",
- { network: aNetwork.toJSON(),
- start: aStart,
- end: aEnd,
- appManifestURL: appManifestURL,
- browsingTrafficOnly: browsingTrafficOnly,
- serviceType: serviceType,
- id: this.getRequestId(request) });
- return request;
- },
-
- clearStats: function clearStats(aNetwork) {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:Clear",
- { network: aNetwork.toJSON(),
- id: this.getRequestId(request) });
- return request;
- },
-
- clearAllStats: function clearAllStats() {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:ClearAll",
- {id: this.getRequestId(request)});
- return request;
- },
-
- addAlarm: function addAlarm(aNetwork, aThreshold, aOptions) {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:SetAlarm",
- {id: this.getRequestId(request),
- data: {network: aNetwork.toJSON(),
- threshold: aThreshold,
- startTime: aOptions.startTime,
- data: aOptions.data,
- manifestURL: this.manifestURL,
- pageURL: this.pageURL}});
- return request;
- },
-
- getAllAlarms: function getAllAlarms(aNetwork) {
- let network = null;
- if (aNetwork) {
- network = aNetwork.toJSON();
- }
-
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:GetAlarms",
- {id: this.getRequestId(request),
- data: {network: network,
- manifestURL: this.manifestURL}});
- return request;
- },
-
- removeAlarms: function removeAlarms(aAlarmId) {
- if (aAlarmId == 0) {
- aAlarmId = -1;
- }
-
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:RemoveAlarms",
- {id: this.getRequestId(request),
- data: {alarmId: aAlarmId,
- manifestURL: this.manifestURL}});
-
- return request;
- },
-
- getAvailableNetworks: function getAvailableNetworks() {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:GetAvailableNetworks",
- { id: this.getRequestId(request) });
- return request;
- },
-
- getAvailableServiceTypes: function getAvailableServiceTypes() {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:GetAvailableServiceTypes",
- { id: this.getRequestId(request) });
- return request;
- },
-
- get sampleRate() {
- return cpmm.sendSyncMessage("NetworkStats:SampleRate")[0];
- },
-
- get maxStorageAge() {
- return cpmm.sendSyncMessage("NetworkStats:MaxStorageAge")[0];
- },
-
- receiveMessage: function(aMessage) {
- if (DEBUG) {
- debug("NetworkStatsmanager::receiveMessage: " + aMessage.name);
- }
-
- let msg = aMessage.json;
- let req = this.takeRequest(msg.id);
- if (!req) {
- if (DEBUG) {
- debug("No request stored with id " + msg.id);
- }
- return;
- }
-
- switch (aMessage.name) {
- case "NetworkStats:Get:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- let result = this._window.MozNetworkStats._create(
- this._window, new NetworkStats(this._window, msg.result));
- if (DEBUG) {
- debug("result: " + JSON.stringify(result));
- }
- Services.DOMRequest.fireSuccess(req, result);
- break;
-
- case "NetworkStats:GetAvailableNetworks:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- let networks = new this._window.Array();
- for (let i = 0; i < msg.result.length; i++) {
- let network = new this._window.MozNetworkStatsInterface(msg.result[i]);
- networks.push(network);
- }
-
- Services.DOMRequest.fireSuccess(req, networks);
- break;
-
- case "NetworkStats:GetAvailableServiceTypes:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- let serviceTypes = new this._window.Array();
- for (let i = 0; i < msg.result.length; i++) {
- serviceTypes.push(msg.result[i]);
- }
-
- Services.DOMRequest.fireSuccess(req, serviceTypes);
- break;
-
- case "NetworkStats:Clear:Return":
- case "NetworkStats:ClearAll:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- Services.DOMRequest.fireSuccess(req, true);
- break;
-
- case "NetworkStats:SetAlarm:Return":
- case "NetworkStats:RemoveAlarms:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- Services.DOMRequest.fireSuccess(req, msg.result);
- break;
-
- case "NetworkStats:GetAlarms:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- let alarms = new this._window.Array();
- for (let i = 0; i < msg.result.length; i++) {
- // The WebIDL type of data is any, so we should manually clone it
- // into the content window.
- if ("data" in msg.result[i]) {
- msg.result[i].data = Cu.cloneInto(msg.result[i].data, this._window);
- }
- let alarm = new NetworkStatsAlarm(this._window, msg.result[i]);
- alarms.push(this._window.MozNetworkStatsAlarm._create(this._window, alarm));
- }
-
- Services.DOMRequest.fireSuccess(req, alarms);
- break;
-
- default:
- if (DEBUG) {
- debug("Wrong message: " + aMessage.name);
- }
- }
- },
-
- init: function(aWindow) {
- let principal = aWindow.document.nodePrincipal;
-
- this.initDOMRequestHelper(aWindow, ["NetworkStats:Get:Return",
- "NetworkStats:GetAvailableNetworks:Return",
- "NetworkStats:GetAvailableServiceTypes:Return",
- "NetworkStats:Clear:Return",
- "NetworkStats:ClearAll:Return",
- "NetworkStats:SetAlarm:Return",
- "NetworkStats:GetAlarms:Return",
- "NetworkStats:RemoveAlarms:Return"]);
-
- // Init app properties.
- let appsService = Cc["@mozilla.org/AppsService;1"]
- .getService(Ci.nsIAppsService);
-
- this.manifestURL = appsService.getManifestURLByLocalId(principal.appId);
-
- let isApp = !!this.manifestURL.length;
- if (isApp) {
- this.pageURL = principal.URI.spec;
- }
-
- this.window = aWindow;
- },
-
- // Called from DOMRequestIpcHelper
- uninit: function uninit() {
- if (DEBUG) {
- debug("uninit call");
- }
- },
-
- classID : NETWORKSTATSMANAGER_CID,
- contractID : NETWORKSTATSMANAGER_CONTRACTID,
- QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver]),
-}
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkStatsAlarm,
- NetworkStatsData,
- NetworkStatsInterface,
- NetworkStats,
- NetworkStatsManager]);
diff --git a/dom/network/NetworkStatsManager.manifest b/dom/network/NetworkStatsManager.manifest
deleted file mode 100644
index 8e8700910..000000000
--- a/dom/network/NetworkStatsManager.manifest
+++ /dev/null
@@ -1,14 +0,0 @@
-component {3b16fe17-5583-483a-b486-b64a3243221c} NetworkStatsManager.js
-contract @mozilla.org/networkStatsdata;1 {3b16fe17-5583-483a-b486-b64a3243221c}
-
-component {28904f59-8497-4ac0-904f-2af14b7fd3de} NetworkStatsManager.js
-contract @mozilla.org/networkStats;1 {28904f59-8497-4ac0-904f-2af14b7fd3de}
-
-component {f540615b-d803-43ff-8200-2a9d145a5645} NetworkStatsManager.js
-contract @mozilla.org/networkstatsinterface;1 {f540615b-d803-43ff-8200-2a9d145a5645}
-
-component {a93ea13e-409c-4189-9b1e-95fff220be55} NetworkStatsManager.js
-contract @mozilla.org/networkstatsalarm;1 {a93ea13e-409c-4189-9b1e-95fff220be55}
-
-component {ceb874cd-cc1a-4e65-b404-cc2d3e42425f} NetworkStatsManager.js
-contract @mozilla.org/networkStatsManager;1 {ceb874cd-cc1a-4e65-b404-cc2d3e42425f}
diff --git a/dom/network/NetworkStatsService.jsm b/dom/network/NetworkStatsService.jsm
deleted file mode 100644
index 4b6d69498..000000000
--- a/dom/network/NetworkStatsService.jsm
+++ /dev/null
@@ -1,1171 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const DEBUG = false;
-function debug(s) {
- if (DEBUG) {
- dump("-*- NetworkStatsService: " + s + "\n");
- }
-}
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-this.EXPORTED_SYMBOLS = ["NetworkStatsService"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/NetworkStatsDB.jsm");
-Cu.import("resource://gre/modules/Timer.jsm");
-
-const NET_NETWORKSTATSSERVICE_CONTRACTID = "@mozilla.org/network/netstatsservice;1";
-const NET_NETWORKSTATSSERVICE_CID = Components.ID("{18725604-e9ac-488a-8aa0-2471e7f6c0a4}");
-
-const TOPIC_BANDWIDTH_CONTROL = "netd-bandwidth-control"
-
-const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const NET_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
-const NET_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
-
-// Networks have different status that NetworkStats API needs to be aware of.
-// Network is present and ready, so NetworkManager provides the whole info.
-const NETWORK_STATUS_READY = 0;
-// Network is present but hasn't established a connection yet (e.g. SIM that has not
-// enabled 3G since boot).
-const NETWORK_STATUS_STANDBY = 1;
-// Network is not present, but stored in database by the previous connections.
-const NETWORK_STATUS_AWAY = 2;
-
-// The maximum traffic amount can be saved in the |cachedStats|.
-const MAX_CACHED_TRAFFIC = 500 * 1000 * 1000; // 500 MB
-
-const QUEUE_TYPE_UPDATE_STATS = 0;
-const QUEUE_TYPE_UPDATE_CACHE = 1;
-const QUEUE_TYPE_WRITE_CACHE = 2;
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageListenerManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gRil",
- "@mozilla.org/ril;1",
- "nsIRadioInterfaceLayer");
-
-XPCOMUtils.defineLazyServiceGetter(this, "networkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "appsService",
- "@mozilla.org/AppsService;1",
- "nsIAppsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "messenger",
- "@mozilla.org/system-message-internal;1",
- "nsISystemMessagesInternal");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
- "@mozilla.org/icc/iccservice;1",
- "nsIIccService");
-
-this.NetworkStatsService = {
- init: function() {
- debug("Service started");
-
- Services.obs.addObserver(this, "xpcom-shutdown", false);
- Services.obs.addObserver(this, TOPIC_CONNECTION_STATE_CHANGED, false);
- Services.obs.addObserver(this, TOPIC_BANDWIDTH_CONTROL, false);
- Services.obs.addObserver(this, "profile-after-change", false);
-
- this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- // Object to store network interfaces, each network interface is composed
- // by a network object (network type and network Id) and a interfaceName
- // that contains the name of the physical interface (wlan0, rmnet0, etc.).
- // The network type can be 0 for wifi or 1 for mobile. On the other hand,
- // the network id is '0' for wifi or the iccid for mobile (SIM).
- // Each networkInterface is placed in the _networks object by the index of
- // 'networkId + networkType'.
- //
- // _networks object allows to map available network interfaces at low level
- // (wlan0, rmnet0, etc.) to a network. It's not mandatory to have a
- // networkInterface per network but can't exist a networkInterface not
- // being mapped to a network.
-
- this._networks = Object.create(null);
-
- // There is no way to know a priori if wifi connection is available,
- // just when the wifi driver is loaded, but it is unloaded when
- // wifi is switched off. So wifi connection is hardcoded
- let netId = this.getNetworkId('0', NET_TYPE_WIFI);
- this._networks[netId] = { network: { id: '0',
- type: NET_TYPE_WIFI },
- interfaceName: null,
- status: NETWORK_STATUS_STANDBY };
-
- this.messages = ["NetworkStats:Get",
- "NetworkStats:Clear",
- "NetworkStats:ClearAll",
- "NetworkStats:SetAlarm",
- "NetworkStats:GetAlarms",
- "NetworkStats:RemoveAlarms",
- "NetworkStats:GetAvailableNetworks",
- "NetworkStats:GetAvailableServiceTypes",
- "NetworkStats:SampleRate",
- "NetworkStats:MaxStorageAge"];
-
- this.messages.forEach(function(aMsgName) {
- ppmm.addMessageListener(aMsgName, this);
- }, this);
-
- this._db = new NetworkStatsDB();
-
- // Stats for all interfaces are updated periodically
- this.timer.initWithCallback(this, this._db.sampleRate,
- Ci.nsITimer.TYPE_REPEATING_PRECISE_CAN_SKIP);
-
- // Stats not from netd are firstly stored in the cached.
- this.cachedStats = Object.create(null);
- this.cachedStatsDate = new Date();
-
- this.updateQueue = [];
- this.isQueueRunning = false;
-
- this._currentAlarms = {};
- this.initAlarms();
- },
-
- receiveMessage: function(aMessage) {
- if (!aMessage.target.assertPermission("networkstats-manage")) {
- return;
- }
-
- debug("receiveMessage " + aMessage.name);
-
- let mm = aMessage.target;
- let msg = aMessage.json;
-
- switch (aMessage.name) {
- case "NetworkStats:Get":
- this.getSamples(mm, msg);
- break;
- case "NetworkStats:Clear":
- this.clearInterfaceStats(mm, msg);
- break;
- case "NetworkStats:ClearAll":
- this.clearDB(mm, msg);
- break;
- case "NetworkStats:SetAlarm":
- this.setAlarm(mm, msg);
- break;
- case "NetworkStats:GetAlarms":
- this.getAlarms(mm, msg);
- break;
- case "NetworkStats:RemoveAlarms":
- this.removeAlarms(mm, msg);
- break;
- case "NetworkStats:GetAvailableNetworks":
- this.getAvailableNetworks(mm, msg);
- break;
- case "NetworkStats:GetAvailableServiceTypes":
- this.getAvailableServiceTypes(mm, msg);
- break;
- case "NetworkStats:SampleRate":
- // This message is sync.
- return this._db.sampleRate;
- case "NetworkStats:MaxStorageAge":
- // This message is sync.
- return this._db.maxStorageSamples * this._db.sampleRate;
- }
- },
-
- observe: function observe(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_CONNECTION_STATE_CHANGED:
-
- // If new interface is registered (notified from NetworkService),
- // the stats are updated for the new interface without waiting to
- // complete the updating period.
-
- let networkInfo = aSubject.QueryInterface(Ci.nsINetworkInfo);
- debug("Network " + networkInfo.name + " of type " + networkInfo.type + " status change");
-
- let netId = this.convertNetworkInfo(networkInfo);
- if (!netId) {
- break;
- }
-
- this._updateCurrentAlarm(netId);
-
- debug("NetId: " + netId);
- this.updateStats(netId);
- break;
-
- case TOPIC_BANDWIDTH_CONTROL:
- debug("Bandwidth message from netd: " + JSON.stringify(aData));
-
- let interfaceName = aData.substring(aData.lastIndexOf(" ") + 1);
- for (let networkId in this._networks) {
- if (interfaceName == this._networks[networkId].interfaceName) {
- let currentAlarm = this._currentAlarms[networkId];
- if (Object.getOwnPropertyNames(currentAlarm).length !== 0) {
- this._fireAlarm(currentAlarm.alarm);
- }
- break;
- }
- }
- break;
-
- case "xpcom-shutdown":
- debug("Service shutdown");
-
- this.messages.forEach(function(aMsgName) {
- ppmm.removeMessageListener(aMsgName, this);
- }, this);
-
- Services.obs.removeObserver(this, "xpcom-shutdown");
- Services.obs.removeObserver(this, "profile-after-change");
- Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED);
- Services.obs.removeObserver(this, TOPIC_BANDWIDTH_CONTROL);
-
- this.timer.cancel();
- this.timer = null;
-
- // Update stats before shutdown
- this.updateAllStats();
- break;
- }
- },
-
- /*
- * nsITimerCallback
- * Timer triggers the update of all stats
- */
- notify: function(aTimer) {
- this.updateAllStats();
- },
-
- /*
- * nsINetworkStatsService
- */
- getRilNetworks: function() {
- let networks = {};
- let numRadioInterfaces = gRil.numRadioInterfaces;
- for (let i = 0; i < numRadioInterfaces; i++) {
- let icc = gIccService.getIccByServiceId(i);
- let radioInterface = gRil.getRadioInterface(i);
- if (icc && icc.iccInfo) {
- let netId = this.getNetworkId(icc.iccInfo.iccid,
- NET_TYPE_MOBILE);
- networks[netId] = { id : icc.iccInfo.iccid,
- type: NET_TYPE_MOBILE };
- }
- }
- return networks;
- },
-
- convertNetworkInfo: function(aNetworkInfo) {
- if (aNetworkInfo.type != NET_TYPE_MOBILE &&
- aNetworkInfo.type != NET_TYPE_WIFI) {
- return null;
- }
-
- let id = '0';
- if (aNetworkInfo.type == NET_TYPE_MOBILE) {
- if (!(aNetworkInfo instanceof Ci.nsIRilNetworkInfo)) {
- debug("Error! Mobile network should be an nsIRilNetworkInfo!");
- return null;
- }
-
- let rilNetwork = aNetworkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
- id = rilNetwork.iccId;
- }
-
- let netId = this.getNetworkId(id, aNetworkInfo.type);
-
- if (!this._networks[netId]) {
- this._networks[netId] = Object.create(null);
- this._networks[netId].network = { id: id,
- type: aNetworkInfo.type };
- }
-
- this._networks[netId].status = NETWORK_STATUS_READY;
- this._networks[netId].interfaceName = aNetworkInfo.name;
- return netId;
- },
-
- getNetworkId: function getNetworkId(aIccId, aNetworkType) {
- return aIccId + '' + aNetworkType;
- },
-
- /* Function to ensure that one network is valid. The network is valid if its status is
- * NETWORK_STATUS_READY, NETWORK_STATUS_STANDBY or NETWORK_STATUS_AWAY.
- *
- * The result is |netId| or null in case of a non-valid network
- * aCallback is signatured as |function(netId)|.
- */
- validateNetwork: function validateNetwork(aNetwork, aCallback) {
- let netId = this.getNetworkId(aNetwork.id, aNetwork.type);
-
- if (this._networks[netId]) {
- aCallback(netId);
- return;
- }
-
- // Check if network is valid (RIL entry) but has not established a connection yet.
- // If so add to networks list with empty interfaceName.
- let rilNetworks = this.getRilNetworks();
- if (rilNetworks[netId]) {
- this._networks[netId] = Object.create(null);
- this._networks[netId].network = rilNetworks[netId];
- this._networks[netId].status = NETWORK_STATUS_STANDBY;
- this._currentAlarms[netId] = Object.create(null);
- aCallback(netId);
- return;
- }
-
- // Check if network is available in the DB.
- this._db.isNetworkAvailable(aNetwork, function(aError, aResult) {
- if (aResult) {
- this._networks[netId] = Object.create(null);
- this._networks[netId].network = aNetwork;
- this._networks[netId].status = NETWORK_STATUS_AWAY;
- this._currentAlarms[netId] = Object.create(null);
- aCallback(netId);
- return;
- }
-
- aCallback(null);
- }.bind(this));
- },
-
- getAvailableNetworks: function getAvailableNetworks(mm, msg) {
- let self = this;
- let rilNetworks = this.getRilNetworks();
- this._db.getAvailableNetworks(function onGetNetworks(aError, aResult) {
-
- // Also return the networks that are valid but have not
- // established connections yet.
- for (let netId in rilNetworks) {
- let found = false;
- for (let i = 0; i < aResult.length; i++) {
- if (netId == self.getNetworkId(aResult[i].id, aResult[i].type)) {
- found = true;
- break;
- }
- }
- if (!found) {
- aResult.push(rilNetworks[netId]);
- }
- }
-
- mm.sendAsyncMessage("NetworkStats:GetAvailableNetworks:Return",
- { id: msg.id, error: aError, result: aResult });
- });
- },
-
- getAvailableServiceTypes: function getAvailableServiceTypes(mm, msg) {
- this._db.getAvailableServiceTypes(function onGetServiceTypes(aError, aResult) {
- mm.sendAsyncMessage("NetworkStats:GetAvailableServiceTypes:Return",
- { id: msg.id, error: aError, result: aResult });
- });
- },
-
- initAlarms: function initAlarms() {
- debug("Init usage alarms");
- let self = this;
-
- for (let netId in this._networks) {
- this._currentAlarms[netId] = Object.create(null);
-
- this._db.getFirstAlarm(netId, function getResult(error, result) {
- if (!error && result) {
- self._setAlarm(result, function onSet(error, success) {
- if (error == "InvalidStateError") {
- self._fireAlarm(result);
- }
- });
- }
- });
- }
- },
-
- /*
- * Function called from manager to get stats from database.
- * In order to return updated stats, first is performed a call to
- * updateAllStats function, which will get last stats from netd
- * and update the database.
- * Then, depending on the request (stats per appId or total stats)
- * it retrieve them from database and return to the manager.
- */
- getSamples: function getSamples(mm, msg) {
- let network = msg.network;
- let netId = this.getNetworkId(network.id, network.type);
-
- let appId = 0;
- let appManifestURL = msg.appManifestURL;
- if (appManifestURL) {
- appId = appsService.getAppLocalIdByManifestURL(appManifestURL);
-
- if (!appId) {
- mm.sendAsyncMessage("NetworkStats:Get:Return",
- { id: msg.id,
- error: "Invalid appManifestURL", result: null });
- return;
- }
- }
-
- let browsingTrafficOnly = msg.browsingTrafficOnly || false;
- let serviceType = msg.serviceType || "";
-
- let start = new Date(msg.start);
- let end = new Date(msg.end);
-
- let callback = (function (aError, aResult) {
- this._db.find(function onStatsFound(aError, aResult) {
- mm.sendAsyncMessage("NetworkStats:Get:Return",
- { id: msg.id, error: aError, result: aResult });
- }, appId, browsingTrafficOnly, serviceType, network, start, end, appManifestURL);
- }).bind(this);
-
- this.validateNetwork(network, function onValidateNetwork(aNetId) {
- if (!aNetId) {
- mm.sendAsyncMessage("NetworkStats:Get:Return",
- { id: msg.id, error: "Invalid connectionType", result: null });
- return;
- }
-
- // If network is currently active we need to update the cached stats first before
- // retrieving stats from the DB.
- if (this._networks[aNetId].status == NETWORK_STATUS_READY) {
- debug("getstats for network " + network.id + " of type " + network.type);
- debug("appId: " + appId + " from appManifestURL: " + appManifestURL);
- debug("browsingTrafficOnly: " + browsingTrafficOnly);
- debug("serviceType: " + serviceType);
-
- if (appId || serviceType) {
- this.updateCachedStats(callback);
- return;
- }
-
- this.updateStats(aNetId, function onStatsUpdated(aResult, aMessage) {
- this.updateCachedStats(callback);
- }.bind(this));
- return;
- }
-
- // Network not active, so no need to update
- this._db.find(function onStatsFound(aError, aResult) {
- mm.sendAsyncMessage("NetworkStats:Get:Return",
- { id: msg.id, error: aError, result: aResult });
- }, appId, browsingTrafficOnly, serviceType, network, start, end, appManifestURL);
- }.bind(this));
- },
-
- clearInterfaceStats: function clearInterfaceStats(mm, msg) {
- let self = this;
- let network = msg.network;
-
- debug("clear stats for network " + network.id + " of type " + network.type);
-
- this.validateNetwork(network, function onValidateNetwork(aNetId) {
- if (!aNetId) {
- mm.sendAsyncMessage("NetworkStats:Clear:Return",
- { id: msg.id, error: "Invalid connectionType", result: null });
- return;
- }
-
- network = {network: network, networkId: aNetId};
- self.updateStats(aNetId, function onUpdate(aResult, aMessage) {
- if (!aResult) {
- mm.sendAsyncMessage("NetworkStats:Clear:Return",
- { id: msg.id, error: aMessage, result: null });
- return;
- }
-
- self._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
- self._updateCurrentAlarm(aNetId);
- mm.sendAsyncMessage("NetworkStats:Clear:Return",
- { id: msg.id, error: aError, result: aResult });
- });
- });
- });
- },
-
- clearDB: function clearDB(mm, msg) {
- let self = this;
- this._db.getAvailableNetworks(function onGetNetworks(aError, aResult) {
- if (aError) {
- mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
- { id: msg.id, error: aError, result: aResult });
- return;
- }
-
- let networks = aResult;
- networks.forEach(function(network, index) {
- networks[index] = {network: network, networkId: self.getNetworkId(network.id, network.type)};
- }, self);
-
- self.updateAllStats(function onUpdate(aResult, aMessage){
- if (!aResult) {
- mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
- { id: msg.id, error: aMessage, result: null });
- return;
- }
-
- self._db.clearStats(networks, function onDBCleared(aError, aResult) {
- networks.forEach(function(network, index) {
- self._updateCurrentAlarm(network.networkId);
- }, self);
- mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
- { id: msg.id, error: aError, result: aResult });
- });
- });
- });
- },
-
- updateAllStats: function updateAllStats(aCallback) {
- let elements = [];
- let lastElement = null;
- let callback = (function (success, message) {
- this.updateCachedStats(aCallback);
- }).bind(this);
-
- // For each connectionType create an object containning the type
- // and the 'queueIndex', the 'queueIndex' is an integer representing
- // the index of a connection type in the global queue array. So, if
- // the connection type is already in the queue it is not appended again,
- // else it is pushed in 'elements' array, which later will be pushed to
- // the queue array.
- for (let netId in this._networks) {
- if (this._networks[netId].status != NETWORK_STATUS_READY) {
- continue;
- }
-
- lastElement = { netId: netId,
- queueIndex: this.updateQueueIndex(netId) };
-
- if (lastElement.queueIndex == -1) {
- elements.push({ netId: lastElement.netId,
- callbacks: [],
- queueType: QUEUE_TYPE_UPDATE_STATS });
- }
- }
-
- if (!lastElement) {
- // No elements need to be updated, probably because status is different than
- // NETWORK_STATUS_READY.
- if (aCallback) {
- aCallback(true, "OK");
- }
- return;
- }
-
- if (elements.length > 0) {
- // If length of elements is greater than 0, callback is set to
- // the last element.
- elements[elements.length - 1].callbacks.push(callback);
- this.updateQueue = this.updateQueue.concat(elements);
- } else {
- // Else, it means that all connection types are already in the queue to
- // be updated, so callback for this request is added to
- // the element in the main queue with the index of the last 'lastElement'.
- // But before is checked that element is still in the queue because it can
- // be processed while generating 'elements' array.
- let element = this.updateQueue[lastElement.queueIndex];
- if (aCallback &&
- (!element || element.netId != lastElement.netId)) {
- aCallback();
- return;
- }
-
- this.updateQueue[lastElement.queueIndex].callbacks.push(callback);
- }
-
- // Call the function that process the elements of the queue.
- this.processQueue();
-
- if (DEBUG) {
- this.logAllRecords();
- }
- },
-
- updateStats: function updateStats(aNetId, aCallback) {
- // Check if the connection is in the main queue, push a new element
- // if it is not being processed or add a callback if it is.
- let index = this.updateQueueIndex(aNetId);
- if (index == -1) {
- this.updateQueue.push({ netId: aNetId,
- callbacks: [aCallback],
- queueType: QUEUE_TYPE_UPDATE_STATS });
- } else {
- this.updateQueue[index].callbacks.push(aCallback);
- return;
- }
-
- // Call the function that process the elements of the queue.
- this.processQueue();
- },
-
- /*
- * Find if a connection is in the main queue array and return its
- * index, if it is not in the array return -1.
- */
- updateQueueIndex: function updateQueueIndex(aNetId) {
- return this.updateQueue.map(function(e) { return e.netId; }).indexOf(aNetId);
- },
-
- /*
- * Function responsible of process all requests in the queue.
- */
- processQueue: function processQueue(aResult, aMessage) {
- // If aResult is not undefined, the caller of the function is the result
- // of processing an element, so remove that element and call the callbacks
- // it has.
- let self = this;
-
- if (aResult != undefined) {
- let item = this.updateQueue.shift();
- for (let callback of item.callbacks) {
- if (callback) {
- callback(aResult, aMessage);
- }
- }
- } else {
- // The caller is a function that has pushed new elements to the queue,
- // if isQueueRunning is false it means there is no processing currently
- // being done, so start.
- if (this.isQueueRunning) {
- return;
- } else {
- this.isQueueRunning = true;
- }
- }
-
- // Check length to determine if queue is empty and stop processing.
- if (this.updateQueue.length < 1) {
- this.isQueueRunning = false;
- return;
- }
-
- // Process the next item as soon as possible.
- setTimeout(function () {
- self.run(self.updateQueue[0]);
- }, 0);
- },
-
- run: function run(item) {
- switch (item.queueType) {
- case QUEUE_TYPE_UPDATE_STATS:
- this.update(item.netId, this.processQueue.bind(this));
- break;
- case QUEUE_TYPE_UPDATE_CACHE:
- this.updateCache(this.processQueue.bind(this));
- break;
- case QUEUE_TYPE_WRITE_CACHE:
- this.writeCache(item.stats, this.processQueue.bind(this));
- break;
- }
- },
-
- update: function update(aNetId, aCallback) {
- // Check if connection type is valid.
- if (!this._networks[aNetId]) {
- if (aCallback) {
- aCallback(false, "Invalid network " + aNetId);
- }
- return;
- }
-
- let interfaceName = this._networks[aNetId].interfaceName;
- debug("Update stats for " + interfaceName);
-
- // Request stats to NetworkService, which will get stats from netd, passing
- // 'networkStatsAvailable' as a callback.
- if (interfaceName) {
- networkService.getNetworkInterfaceStats(interfaceName,
- this.networkStatsAvailable.bind(this, aCallback, aNetId));
- return;
- }
-
- if (aCallback) {
- aCallback(true, "ok");
- }
- },
-
- /*
- * Callback of request stats. Store stats in database.
- */
- networkStatsAvailable: function networkStatsAvailable(aCallback, aNetId,
- aResult, aRxBytes,
- aTxBytes, aTimestamp) {
- if (!aResult) {
- if (aCallback) {
- aCallback(false, "Netd IPC error");
- }
- return;
- }
-
- let stats = { appId: 0,
- isInBrowser: false,
- serviceType: "",
- networkId: this._networks[aNetId].network.id,
- networkType: this._networks[aNetId].network.type,
- date: new Date(aTimestamp),
- rxBytes: aTxBytes,
- txBytes: aRxBytes,
- isAccumulative: true };
-
- debug("Update stats for: " + JSON.stringify(stats));
-
- this._db.saveStats(stats, function onSavedStats(aError, aResult) {
- if (aCallback) {
- if (aError) {
- aCallback(false, aError);
- return;
- }
-
- aCallback(true, "OK");
- }
- });
- },
-
- /*
- * Function responsible for receiving stats which are not from netd.
- */
- saveStats: function saveStats(aAppId, aIsInIsolatedMozBrowser, aServiceType,
- aNetworkInfo, aTimeStamp, aRxBytes, aTxBytes,
- aIsAccumulative, aCallback) {
- let netId = this.convertNetworkInfo(aNetworkInfo);
- if (!netId) {
- if (aCallback) {
- aCallback(false, "Invalid network type");
- }
- return;
- }
-
- // Check if |aConnectionType|, |aAppId| and |aServiceType| are valid.
- // There are two invalid cases for the combination of |aAppId| and
- // |aServiceType|:
- // a. Both |aAppId| is non-zero and |aServiceType| is non-empty.
- // b. Both |aAppId| is zero and |aServiceType| is empty.
- if (!this._networks[netId] || (aAppId && aServiceType) ||
- (!aAppId && !aServiceType)) {
- debug("Invalid network interface, appId or serviceType");
- return;
- }
-
- let stats = { appId: aAppId,
- isInBrowser: aIsInIsolatedMozBrowser,
- serviceType: aServiceType,
- networkId: this._networks[netId].network.id,
- networkType: this._networks[netId].network.type,
- date: new Date(aTimeStamp),
- rxBytes: aRxBytes,
- txBytes: aTxBytes,
- isAccumulative: aIsAccumulative };
-
- this.updateQueue.push({ stats: stats,
- callbacks: [aCallback],
- queueType: QUEUE_TYPE_WRITE_CACHE });
-
- this.processQueue();
- },
-
- /*
- *
- */
- writeCache: function writeCache(aStats, aCallback) {
- debug("saveStats: " + aStats.appId + " " + aStats.isInBrowser + " " +
- aStats.serviceType + " " + aStats.networkId + " " +
- aStats.networkType + " " + aStats.date + " " +
- aStats.rxBytes + " " + aStats.txBytes);
-
- // Generate an unique key from |appId|, |isInBrowser|, |serviceType| and
- // |netId|, which is used to retrieve data in |cachedStats|.
- let netId = this.getNetworkId(aStats.networkId, aStats.networkType);
- let key = aStats.appId + "" + aStats.isInBrowser + "" +
- aStats.serviceType + "" + netId;
-
- // |cachedStats| only keeps the data with the same date.
- // If the incoming date is different from |cachedStatsDate|,
- // both |cachedStats| and |cachedStatsDate| will get updated.
- let diff = (this._db.normalizeDate(aStats.date) -
- this._db.normalizeDate(this.cachedStatsDate)) /
- this._db.sampleRate;
- if (diff != 0) {
- this.updateCache(function onUpdated(success, message) {
- this.cachedStatsDate = aStats.date;
- this.cachedStats[key] = aStats;
-
- if (aCallback) {
- aCallback(true, "ok");
- }
- }.bind(this));
- return;
- }
-
- // Try to find the matched row in the cached by |appId| and |connectionType|.
- // If not found, save the incoming data into the cached.
- let cachedStats = this.cachedStats[key];
- if (!cachedStats) {
- this.cachedStats[key] = aStats;
- if (aCallback) {
- aCallback(true, "ok");
- }
- return;
- }
-
- // Find matched row, accumulate the traffic amount.
- cachedStats.rxBytes += aStats.rxBytes;
- cachedStats.txBytes += aStats.txBytes;
-
- // If new rxBytes or txBytes exceeds MAX_CACHED_TRAFFIC
- // the corresponding row will be saved to indexedDB.
- // Then, the row will be removed from the cached.
- if (cachedStats.rxBytes > MAX_CACHED_TRAFFIC ||
- cachedStats.txBytes > MAX_CACHED_TRAFFIC) {
- this._db.saveStats(cachedStats, function (error, result) {
- debug("Application stats inserted in indexedDB");
- if (aCallback) {
- aCallback(true, "ok");
- }
- });
- delete this.cachedStats[key];
- return;
- }
-
- if (aCallback) {
- aCallback(true, "ok");
- }
- },
-
- updateCachedStats: function updateCachedStats(aCallback) {
- this.updateQueue.push({ callbacks: [aCallback],
- queueType: QUEUE_TYPE_UPDATE_CACHE });
-
- this.processQueue();
- },
-
- updateCache: function updateCache(aCallback) {
- debug("updateCache: " + this.cachedStatsDate);
-
- let stats = Object.keys(this.cachedStats);
- if (stats.length == 0) {
- // |cachedStats| is empty, no need to update.
- if (aCallback) {
- aCallback(true, "no need to update");
- }
- return;
- }
-
- let index = 0;
- this._db.saveStats(this.cachedStats[stats[index]],
- function onSavedStats(error, result) {
- debug("Application stats inserted in indexedDB");
-
- // Clean up the |cachedStats| after updating.
- if (index == stats.length - 1) {
- this.cachedStats = Object.create(null);
-
- if (aCallback) {
- aCallback(true, "ok");
- }
- return;
- }
-
- // Update is not finished, keep updating.
- index += 1;
- this._db.saveStats(this.cachedStats[stats[index]],
- onSavedStats.bind(this, error, result));
- }.bind(this));
- },
-
- get maxCachedTraffic () {
- return MAX_CACHED_TRAFFIC;
- },
-
- logAllRecords: function logAllRecords() {
- this._db.logAllRecords(function onResult(aError, aResult) {
- if (aError) {
- debug("Error: " + aError);
- return;
- }
-
- debug("===== LOG =====");
- debug("There are " + aResult.length + " items");
- debug(JSON.stringify(aResult));
- });
- },
-
- getAlarms: function getAlarms(mm, msg) {
- let self = this;
- let network = msg.data.network;
- let manifestURL = msg.data.manifestURL;
-
- if (network) {
- this.validateNetwork(network, function onValidateNetwork(aNetId) {
- if (!aNetId) {
- mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
- { id: msg.id, error: "InvalidInterface", result: null });
- return;
- }
-
- self._getAlarms(mm, msg, aNetId, manifestURL);
- });
- return;
- }
-
- this._getAlarms(mm, msg, null, manifestURL);
- },
-
- _getAlarms: function _getAlarms(mm, msg, aNetId, aManifestURL) {
- let self = this;
- this._db.getAlarms(aNetId, aManifestURL, function onCompleted(error, result) {
- if (error) {
- mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
- { id: msg.id, error: error, result: result });
- return;
- }
-
- let alarms = []
- // NetworkStatsManager must return the network instead of the networkId.
- for (let i = 0; i < result.length; i++) {
- let alarm = result[i];
- alarms.push({ id: alarm.id,
- network: self._networks[alarm.networkId].network,
- threshold: alarm.absoluteThreshold,
- data: alarm.data });
- }
-
- mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
- { id: msg.id, error: null, result: alarms });
- });
- },
-
- removeAlarms: function removeAlarms(mm, msg) {
- let alarmId = msg.data.alarmId;
- let manifestURL = msg.data.manifestURL;
-
- let self = this;
- let callback = function onRemove(error, result) {
- if (error) {
- mm.sendAsyncMessage("NetworkStats:RemoveAlarms:Return",
- { id: msg.id, error: error, result: result });
- return;
- }
-
- for (let i in self._currentAlarms) {
- let currentAlarm = self._currentAlarms[i].alarm;
- if (currentAlarm && ((alarmId == currentAlarm.id) ||
- (alarmId == -1 && currentAlarm.manifestURL == manifestURL))) {
-
- self._updateCurrentAlarm(currentAlarm.networkId);
- }
- }
-
- mm.sendAsyncMessage("NetworkStats:RemoveAlarms:Return",
- { id: msg.id, error: error, result: true });
- };
-
- if (alarmId == -1) {
- this._db.removeAlarms(manifestURL, callback);
- } else {
- this._db.removeAlarm(alarmId, manifestURL, callback);
- }
- },
-
- /*
- * Function called from manager to set an alarm.
- */
- setAlarm: function setAlarm(mm, msg) {
- let options = msg.data;
- let network = options.network;
- let threshold = options.threshold;
-
- debug("Set alarm at " + threshold + " for " + JSON.stringify(network));
-
- if (threshold < 0) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: "InvalidThresholdValue", result: null });
- return;
- }
-
- let self = this;
- this.validateNetwork(network, function onValidateNetwork(aNetId) {
- if (!aNetId) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: "InvalidiConnectionType", result: null });
- return;
- }
-
- let newAlarm = {
- id: null,
- networkId: aNetId,
- absoluteThreshold: threshold,
- relativeThreshold: null,
- startTime: options.startTime,
- data: options.data,
- pageURL: options.pageURL,
- manifestURL: options.manifestURL
- };
-
- self._getAlarmQuota(newAlarm, function onUpdate(error, quota) {
- if (error) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: error, result: null });
- return;
- }
-
- self._db.addAlarm(newAlarm, function addSuccessCb(error, newId) {
- if (error) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: error, result: null });
- return;
- }
-
- newAlarm.id = newId;
- self._setAlarm(newAlarm, function onSet(error, success) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: error, result: newId });
-
- if (error == "InvalidStateError") {
- self._fireAlarm(newAlarm);
- }
- });
- });
- });
- });
- },
-
- _setAlarm: function _setAlarm(aAlarm, aCallback) {
- let currentAlarm = this._currentAlarms[aAlarm.networkId];
- if ((Object.getOwnPropertyNames(currentAlarm).length !== 0 &&
- aAlarm.relativeThreshold > currentAlarm.alarm.relativeThreshold) ||
- this._networks[aAlarm.networkId].status != NETWORK_STATUS_READY) {
- aCallback(null, true);
- return;
- }
-
- let self = this;
-
- this._getAlarmQuota(aAlarm, function onUpdate(aError, aQuota) {
- if (aError) {
- aCallback(aError, null);
- return;
- }
-
- let callback = function onAlarmSet(aError) {
- if (aError) {
- debug("Set alarm error: " + aError);
- aCallback("netdError", null);
- return;
- }
-
- self._currentAlarms[aAlarm.networkId].alarm = aAlarm;
-
- aCallback(null, true);
- };
-
- debug("Set alarm " + JSON.stringify(aAlarm));
- let interfaceName = self._networks[aAlarm.networkId].interfaceName;
- if (interfaceName) {
- networkService.setNetworkInterfaceAlarm(interfaceName,
- aQuota,
- callback);
- return;
- }
-
- aCallback(null, true);
- });
- },
-
- _getAlarmQuota: function _getAlarmQuota(aAlarm, aCallback) {
- let self = this;
- this.updateStats(aAlarm.networkId, function onStatsUpdated(aResult, aMessage) {
- self._db.getCurrentStats(self._networks[aAlarm.networkId].network,
- aAlarm.startTime,
- function onStatsFound(error, result) {
- if (error) {
- debug("Error getting stats for " +
- JSON.stringify(self._networks[aAlarm.networkId]) + ": " + error);
- aCallback(error, result);
- return;
- }
-
- let quota = aAlarm.absoluteThreshold - result.rxBytes - result.txBytes;
-
- // Alarm set to a threshold lower than current rx/tx bytes.
- if (quota <= 0) {
- aCallback("InvalidStateError", null);
- return;
- }
-
- aAlarm.relativeThreshold = aAlarm.startTime
- ? result.rxTotalBytes + result.txTotalBytes + quota
- : aAlarm.absoluteThreshold;
-
- aCallback(null, quota);
- });
- });
- },
-
- _fireAlarm: function _fireAlarm(aAlarm) {
- debug("Fire alarm");
-
- let self = this;
- this._db.removeAlarm(aAlarm.id, null, function onRemove(aError, aResult){
- if (!aError && !aResult) {
- return;
- }
-
- self._fireSystemMessage(aAlarm);
- self._updateCurrentAlarm(aAlarm.networkId);
- });
- },
-
- _updateCurrentAlarm: function _updateCurrentAlarm(aNetworkId) {
- this._currentAlarms[aNetworkId] = Object.create(null);
-
- let self = this;
- this._db.getFirstAlarm(aNetworkId, function onGet(error, result){
- if (error) {
- debug("Error getting the first alarm");
- return;
- }
-
- if (!result) {
- let interfaceName = self._networks[aNetworkId].interfaceName;
- networkService.setNetworkInterfaceAlarm(interfaceName, -1,
- function onComplete(){});
- return;
- }
-
- self._setAlarm(result, function onSet(error, success){
- if (error == "InvalidStateError") {
- self._fireAlarm(result);
- return;
- }
- });
- });
- },
-
- _fireSystemMessage: function _fireSystemMessage(aAlarm) {
- debug("Fire system message: " + JSON.stringify(aAlarm));
-
- let manifestURI = Services.io.newURI(aAlarm.manifestURL, null, null);
- let pageURI = Services.io.newURI(aAlarm.pageURL, null, null);
-
- let alarm = { "id": aAlarm.id,
- "threshold": aAlarm.absoluteThreshold,
- "data": aAlarm.data };
- messenger.sendMessage("networkstats-alarm", alarm, pageURI, manifestURI);
- }
-};
-
-NetworkStatsService.init();
diff --git a/dom/network/NetworkStatsServiceProxy.js b/dom/network/NetworkStatsServiceProxy.js
deleted file mode 100644
index f3df4344d..000000000
--- a/dom/network/NetworkStatsServiceProxy.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const DEBUG = false;
-function debug(s) { dump("-*- NetworkStatsServiceProxy: " + s + "\n"); }
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-this.EXPORTED_SYMBOLS = ["NetworkStatsServiceProxy"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/NetworkStatsService.jsm");
-
-const NETWORKSTATSSERVICEPROXY_CONTRACTID = "@mozilla.org/networkstatsServiceProxy;1";
-const NETWORKSTATSSERVICEPROXY_CID = Components.ID("98fd8f69-784e-4626-aa59-56d6436a3c24");
-const nsINetworkStatsServiceProxy = Ci.nsINetworkStatsServiceProxy;
-
-function NetworkStatsServiceProxy() {
- if (DEBUG) {
- debug("Proxy started");
- }
-}
-
-NetworkStatsServiceProxy.prototype = {
- /*
- * Function called in the protocol layer (HTTP, FTP, WebSocket ...etc)
- * to pass the per-app stats to NetworkStatsService.
- */
- saveAppStats: function saveAppStats(aAppId, aIsInIsolatedMozBrowser, aNetworkInfo, aTimeStamp,
- aRxBytes, aTxBytes, aIsAccumulative,
- aCallback) {
- if (!aNetworkInfo) {
- if (DEBUG) {
- debug("|aNetworkInfo| is not specified. Failed to save stats. Returning.");
- }
- return;
- }
-
- if (DEBUG) {
- debug("saveAppStats: " + aAppId + " " + aIsInIsolatedMozBrowser + " " +
- aNetworkInfo.type + " " + aTimeStamp + " " +
- aRxBytes + " " + aTxBytes + " " + aIsAccumulative);
- }
-
- if (aCallback) {
- aCallback = aCallback.notify;
- }
-
- NetworkStatsService.saveStats(aAppId, aIsInIsolatedMozBrowser, "", aNetworkInfo,
- aTimeStamp, aRxBytes, aTxBytes,
- aIsAccumulative, aCallback);
- },
-
- /*
- * Function called in the points of different system services
- * to pass the per-service stats to NetworkStatsService.
- */
- saveServiceStats: function saveServiceStats(aServiceType, aNetworkInfo,
- aTimeStamp, aRxBytes, aTxBytes,
- aIsAccumulative, aCallback) {
- if (!aNetworkInfo) {
- if (DEBUG) {
- debug("|aNetworkInfo| is not specified. Failed to save stats. Returning.");
- }
- return;
- }
-
- if (DEBUG) {
- debug("saveServiceStats: " + aServiceType + " " + aNetworkInfo.type + " " +
- aTimeStamp + " " + aRxBytes + " " + aTxBytes + " " +
- aIsAccumulative);
- }
-
- if (aCallback) {
- aCallback = aCallback.notify;
- }
-
- NetworkStatsService.saveStats(0, false, aServiceType , aNetworkInfo, aTimeStamp,
- aRxBytes, aTxBytes, aIsAccumulative,
- aCallback);
- },
-
- classID : NETWORKSTATSSERVICEPROXY_CID,
- QueryInterface : XPCOMUtils.generateQI([nsINetworkStatsServiceProxy]),
-}
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkStatsServiceProxy]);
diff --git a/dom/network/NetworkStatsServiceProxy.manifest b/dom/network/NetworkStatsServiceProxy.manifest
deleted file mode 100644
index 24f09f088..000000000
--- a/dom/network/NetworkStatsServiceProxy.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {98fd8f69-784e-4626-aa59-56d6436a3c24} NetworkStatsServiceProxy.js
-contract @mozilla.org/networkstatsServiceProxy;1 {98fd8f69-784e-4626-aa59-56d6436a3c24}
diff --git a/dom/network/TCPSocket.cpp b/dom/network/TCPSocket.cpp
index 4eb2f72f6..38827a9ac 100644
--- a/dom/network/TCPSocket.cpp
+++ b/dom/network/TCPSocket.cpp
@@ -33,11 +33,6 @@
#include "nsStringStream.h"
#include "secerr.h"
#include "sslerr.h"
-#ifdef MOZ_WIDGET_GONK
-#include "nsINetworkStatsServiceProxy.h"
-#include "nsINetworkManager.h"
-#include "nsINetworkInterface.h"
-#endif
#define BUFFER_SIZE 65536
#define NETWORK_STATS_THRESHOLD 65536
@@ -163,12 +158,6 @@ TCPSocket::TCPSocket(nsIGlobalObject* aGlobal, const nsAString& aHost, uint16_t
, mTrackingNumber(0)
, mWaitingForStartTLS(false)
, mObserversActive(false)
-#ifdef MOZ_WIDGET_GONK
- , mTxBytes(0)
- , mRxBytes(0)
- , mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
- , mInIsolatedMozBrowser(false)
-#endif
{
if (aGlobal) {
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
@@ -323,13 +312,6 @@ TCPSocket::InitWithTransport(nsISocketTransport* aTransport)
mTransport->GetPort(&port);
mPort = port;
-#ifdef MOZ_WIDGET_GONK
- nsCOMPtr<nsINetworkManager> networkManager = do_GetService("@mozilla.org/network/manager;1");
- if (networkManager) {
- networkManager->GetActiveNetworkInfo(getter_AddRefs(mActiveNetworkInfo));
- }
-#endif
-
return NS_OK;
}
@@ -651,12 +633,6 @@ TCPSocket::Resume(mozilla::ErrorResult& aRv)
nsresult
TCPSocket::MaybeReportErrorAndCloseIfOpen(nsresult status) {
-#ifdef MOZ_WIDGET_GONK
- // Save network statistics once the connection is closed.
- // For now this function is Gonk-specific.
- SaveNetworkStats(true);
-#endif
-
// If we're closed, we've already reported the error or just don't need to
// report the error.
if (mReadyState == TCPReadyState::Closed) {
@@ -941,12 +917,6 @@ TCPSocket::Send(nsIInputStream* aStream, uint32_t aByteLength)
EnsureCopying();
-#ifdef MOZ_WIDGET_GONK
- // Collect transmitted amount for network statistics.
- mTxBytes += aByteLength;
- SaveNetworkStats(false);
-#endif
-
return !bufferFull;
}
@@ -1069,12 +1039,6 @@ NS_IMETHODIMP
TCPSocket::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream,
uint64_t aOffset, uint32_t aCount)
{
-#ifdef MOZ_WIDGET_GONK
- // Collect received amount for network statistics.
- mRxBytes += aCount;
- SaveNetworkStats(false);
-#endif
-
if (mUseArrayBuffers) {
nsTArray<uint8_t> buffer;
buffer.SetCapacity(aCount);
@@ -1160,10 +1124,7 @@ TCPSocket::SetSocketBridgeParent(TCPSocketParent* aBridgeParent)
void
TCPSocket::SetAppIdAndBrowser(uint32_t aAppId, bool aInIsolatedMozBrowser)
{
-#ifdef MOZ_WIDGET_GONK
- mAppId = aAppId;
- mInIsolatedMozBrowser = aInIsolatedMozBrowser;
-#endif
+ /*** STUB ***/
}
NS_IMETHODIMP
@@ -1190,37 +1151,6 @@ TCPSocket::UpdateBufferedAmount(uint32_t aBufferedAmount, uint32_t aTrackingNumb
return NS_OK;
}
-#ifdef MOZ_WIDGET_GONK
-void
-TCPSocket::SaveNetworkStats(bool aEnforce)
-{
- if (!mTxBytes && !mRxBytes) {
- // There is no traffic at all. No need to save statistics.
- return;
- }
-
- // If "enforce" is false, the traffic amount is saved to NetworkStatsServiceProxy
- // only when the total amount exceeds the predefined threshold value.
- // The purpose is to avoid too much overhead for collecting statistics.
- uint32_t totalBytes = mTxBytes + mRxBytes;
- if (!aEnforce && totalBytes < NETWORK_STATS_THRESHOLD) {
- return;
- }
-
- nsCOMPtr<nsINetworkStatsServiceProxy> nssProxy =
- do_GetService("@mozilla.org/networkstatsServiceProxy;1");
- if (!nssProxy) {
- return;
- }
-
- nssProxy->SaveAppStats(mAppId, mInIsolatedMozBrowser, mActiveNetworkInfo,
- PR_Now(), mRxBytes, mTxBytes, false, nullptr);
-
- // Reset the counters once the statistics is saved to NetworkStatsServiceProxy.
- mTxBytes = mRxBytes = 0;
-}
-#endif
-
NS_IMETHODIMP
TCPSocket::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
{
diff --git a/dom/network/TCPSocket.h b/dom/network/TCPSocket.h
index e98c03ca5..4ad425b9e 100644
--- a/dom/network/TCPSocket.h
+++ b/dom/network/TCPSocket.h
@@ -179,10 +179,6 @@ private:
void ActivateTLS();
// Dispatch an error event if necessary, then dispatch a "close" event.
nsresult MaybeReportErrorAndCloseIfOpen(nsresult status);
-#ifdef MOZ_WIDGET_GONK
- // Store and reset any saved network stats for this socket.
- void SaveNetworkStats(bool aEnforce);
-#endif
// Helper for FireDataStringEvent/FireDataArrayEvent.
nsresult FireDataEvent(JSContext* aCx, const nsAString& aType,
@@ -246,19 +242,6 @@ private:
nsTArray<nsCOMPtr<nsIInputStream>> mPendingDataWhileCopierActive;
bool mObserversActive;
-
-#ifdef MOZ_WIDGET_GONK
- // Number of bytes sent.
- uint32_t mTxBytes;
- // Number of bytes received.
- uint32_t mRxBytes;
- // The app that owns this socket.
- uint32_t mAppId;
- // Was this socket created inside of an isolated browser frame?
- bool mInIsolatedMozBrowser;
- // The name of the active network used by this socket.
- nsCOMPtr<nsINetworkInfo> mActiveNetworkInfo;
-#endif
};
} // namespace dom
diff --git a/dom/network/interfaces/moz.build b/dom/network/interfaces/moz.build
index add687542..ad2e56bd6 100644
--- a/dom/network/interfaces/moz.build
+++ b/dom/network/interfaces/moz.build
@@ -10,10 +10,4 @@ XPIDL_SOURCES += [
'nsIUDPSocketChild.idl',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- XPIDL_SOURCES += [
- 'nsIEthernetManager.idl',
- 'nsINetworkStatsServiceProxy.idl',
- ]
-
XPIDL_MODULE = 'dom_network'
diff --git a/dom/network/interfaces/nsIEthernetManager.idl b/dom/network/interfaces/nsIEthernetManager.idl
deleted file mode 100644
index 2b92dc88f..000000000
--- a/dom/network/interfaces/nsIEthernetManager.idl
+++ /dev/null
@@ -1,137 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, function, uuid(2a3ad56c-edc0-439f-8aae-900b331ddf49)]
-interface nsIEthernetManagerCallback : nsISupports
-{
- /**
- * Callback function used to report the success of different operations.
- *
- * @param success
- * Boolean value indicates the success of an operation.
- * @prarm message
- * Message reported in the end of operation.
- */
- void notify(in boolean success, in DOMString message);
-};
-
-[scriptable, function, uuid(1746e7dd-92d4-43fa-8ef4-bc13d0b60353)]
-interface nsIEthernetManagerScanCallback : nsISupports
-{
- /**
- * Callback function used to report the result of scan function.
- *
- * @param list
- * List of available ethernet interfaces.
- */
- void notify(in jsval list);
-};
-
-/**
- * An internal idl provides control to ethernet interfaces.
- */
-[scriptable, uuid(81750c87-bb3b-4724-b955-834eafa53fd1)]
-interface nsIEthernetManager : nsISupports
-{
- /**
- * List of exisiting interface name.
- */
- readonly attribute jsval interfaceList;
-
- /**
- * Scan available ethernet interfaces on device.
- *
- * @param callback
- * Callback function.
- */
- void scan(in nsIEthernetManagerScanCallback callback);
-
- /**
- * Add a new interface to the interface list.
- *
- * @param ifname
- * Interface name. Should be the form of "eth*".
- * @param callback
- * Callback function.
- */
- void addInterface(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Remove an existing interface from the interface list.
- *
- * @param ifname
- * Interface name.
- * @param Callback
- * Callback function.
- */
- void removeInterface(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Update a conifg of an existing interface in the interface list.
- *
- * @param ifname
- * Interface name.
- * @param config
- * .ip: IP address.
- * .prefixLength: Mask length.
- * .gateway: Gateway.
- * .dnses: DNS addresses.
- * .httpProxyHost: HTTP proxy host.
- * .httpProxyPort: HTTP proxy port.
- * .ipMode: IP mode, can be 'dhcp' or 'static'.
- * @param callback
- * Callback function.
- */
- void updateInterfaceConfig(in DOMString ifname,
- in jsval config,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Enable networking of an existing interface in the interface list.
- *
- * @param ifname
- * Interface name.
- * @param callback
- * Callback function.
- */
- void enable(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Disable networking of an existing interface in the interface list.
- *
- * @param ifname
- * Interface name.
- * @param callback
- * Callback function.
- */
- void disable(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Make an existing interface connect to network.
- *
- * @param ifname
- * Interface name.
- * @param callback
- * Callback function.
- */
- void connect(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Disconnect a connected interface in the interface list.
- *
- * @param ifname
- * Interface name.
- * @param callback
- * Callback function.
- */
- void disconnect(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-};
diff --git a/dom/network/interfaces/nsINetworkStatsServiceProxy.idl b/dom/network/interfaces/nsINetworkStatsServiceProxy.idl
deleted file mode 100644
index cd6765c68..000000000
--- a/dom/network/interfaces/nsINetworkStatsServiceProxy.idl
+++ /dev/null
@@ -1,64 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
-* License, v. 2.0. If a copy of the MPL was not distributed with this file,
-* You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsINetworkInfo;
-
-[scriptable, function, uuid(5f821529-1d80-4ab5-a933-4e1b3585b6bc)]
-interface nsINetworkStatsServiceProxyCallback : nsISupports
-{
- /*
- * @param aResult callback result with boolean value
- * @param aMessage message
- */
- void notify(in boolean aResult, in jsval aMessage);
-};
-
-[scriptable, uuid(f4f3e901-e102-499d-9d37-dc9951f52df7)]
-interface nsINetworkStatsServiceProxy : nsISupports
-{
- /*
- * An interface used to record per-app traffic data.
- * @param aAppId app id
- * @param aIsInIsolatedMozBrowser
- * true if the frame is an isolated mozbrowser element. <iframe
- * mozbrowser mozapp> and <xul:browser> are not considered to be
- * mozbrowser elements. <iframe mozbrowser noisolation> does not count
- * as isolated since isolation is disabled. Isolation can only be
- * disabled if the containing document is chrome.
- * @param aNetworkInterface network
- * @param aTimeStamp time stamp
- * @param aRxBytes received data amount
- * @param aTxBytes transmitted data amount
- * @param aIsAccumulative is stats accumulative
- * @param aCallback an optional callback
- */
- void saveAppStats(in unsigned long aAppId,
- in boolean aIsInIsolatedMozBrowser,
- in nsINetworkInfo aNetworkInfo,
- in unsigned long long aTimeStamp,
- in unsigned long long aRxBytes,
- in unsigned long long aTxBytes,
- in boolean aIsAccumulative,
- [optional] in nsINetworkStatsServiceProxyCallback aCallback);
-
- /*
- * An interface used to record per-system service traffic data.
- * @param aServiceType system service type
- * @param aNetworkInterface network
- * @param aTimeStamp time stamp
- * @param aRxBytes received data amount
- * @param aTxBytes transmitted data amount
- * @param aIsAccumulative is stats accumulative
- * @param aCallback an optional callback
- */
- void saveServiceStats(in string aServiceType,
- in nsINetworkInfo aNetworkInfo,
- in unsigned long long aTimeStamp,
- in unsigned long long aRxBytes,
- in unsigned long long aTxBytes,
- in boolean aIsAccumulative,
- [optional] in nsINetworkStatsServiceProxyCallback aCallback);
-};
diff --git a/dom/network/moz.build b/dom/network/moz.build
index 63e5c75c0..ffb90d116 100644
--- a/dom/network/moz.build
+++ b/dom/network/moz.build
@@ -40,28 +40,6 @@ UNIFIED_SOURCES += [
'UDPSocketParent.cpp',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- EXTRA_JS_MODULES += [
- 'NetworkStatsDB.jsm',
- 'NetworkStatsService.jsm',
- ]
-
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- EXTRA_COMPONENTS += [
- 'EthernetManager.js',
- 'EthernetManager.manifest',
- 'NetworkStatsManager.js',
- 'NetworkStatsManager.manifest',
- 'NetworkStatsServiceProxy.js',
- 'NetworkStatsServiceProxy.manifest',
- ]
- EXPORTS.mozilla.dom.network += [
- 'NetUtils.h',
- ]
- UNIFIED_SOURCES += [
- 'NetUtils.cpp',
- ]
-
IPDL_SOURCES += [
'PTCPServerSocket.ipdl',
'PTCPSocket.ipdl',
diff --git a/dom/notification/DesktopNotification.h b/dom/notification/DesktopNotification.h
index e1cb2efbc..5fd5e4c03 100644
--- a/dom/notification/DesktopNotification.h
+++ b/dom/notification/DesktopNotification.h
@@ -159,10 +159,6 @@ class AlertServiceObserver: public nsIObserver
// forward to parent
if (mNotification) {
-#ifdef MOZ_B2G
- if (NS_FAILED(mNotification->CheckInnerWindowCorrectness()))
- return NS_ERROR_NOT_AVAILABLE;
-#endif
mNotification->HandleAlertServiceNotification(aTopic);
}
return NS_OK;
diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp
index 9c0ce2f18..1dd5724e4 100644
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -1881,7 +1881,7 @@ Notification::GetPermission(nsIGlobalObject* aGlobal, ErrorResult& aRv)
MOZ_ASSERT(worker);
RefPtr<GetPermissionRunnable> r =
new GetPermissionRunnable(worker);
- r->Dispatch(aRv);
+ r->Dispatch(Terminating, aRv);
if (aRv.Failed()) {
return NotificationPermission::Denied;
}
@@ -2484,7 +2484,7 @@ NotificationWorkerHolder::Notify(Status aStatus)
RefPtr<CloseNotificationRunnable> r =
new CloseNotificationRunnable(kungFuDeathGrip);
ErrorResult rv;
- r->Dispatch(rv);
+ r->Dispatch(Killing, rv);
// XXXbz I'm told throwing and returning false from here is pointless (and
// also that doing sync stuff from here is really weird), so I guess we just
// suppress the exception on rv, if any.
@@ -2627,7 +2627,7 @@ Notification::ShowPersistentNotification(JSContext* aCx,
worker->AssertIsOnWorkerThread();
RefPtr<CheckLoadRunnable> loadChecker =
new CheckLoadRunnable(worker, NS_ConvertUTF16toUTF8(aScope));
- loadChecker->Dispatch(aRv);
+ loadChecker->Dispatch(Terminating, aRv);
if (aRv.Failed()) {
return nullptr;
}
diff --git a/dom/performance/Performance.cpp b/dom/performance/Performance.cpp
index 8dc239b05..a1e28bc55 100755
--- a/dom/performance/Performance.cpp
+++ b/dom/performance/Performance.cpp
@@ -13,23 +13,21 @@
#include "PerformanceMeasure.h"
#include "PerformanceObserver.h"
#include "PerformanceResourceTiming.h"
+#include "PerformanceService.h"
#include "PerformanceWorker.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/PerformanceBinding.h"
#include "mozilla/dom/PerformanceEntryEvent.h"
#include "mozilla/dom/PerformanceNavigationBinding.h"
#include "mozilla/dom/PerformanceObserverBinding.h"
+#include "mozilla/dom/PerformanceNavigationTiming.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h"
#include "mozilla/TimerClamping.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
-#ifdef MOZ_WIDGET_GONK
-#define PERFLOG(msg, ...) __android_log_print(ANDROID_LOG_INFO, "PerformanceTiming", msg, ##__VA_ARGS__)
-#else
#define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__)
-#endif
namespace mozilla {
namespace dom {
@@ -38,27 +36,6 @@ using namespace workers;
namespace {
-// Helper classes
-class MOZ_STACK_CLASS PerformanceEntryComparator final
-{
-public:
- bool Equals(const PerformanceEntry* aElem1,
- const PerformanceEntry* aElem2) const
- {
- MOZ_ASSERT(aElem1 && aElem2,
- "Trying to compare null performance entries");
- return aElem1->StartTime() == aElem2->StartTime();
- }
-
- bool LessThan(const PerformanceEntry* aElem1,
- const PerformanceEntry* aElem2) const
- {
- MOZ_ASSERT(aElem1 && aElem2,
- "Trying to compare null performance entries");
- return aElem1->StartTime() < aElem2->StartTime();
- }
-};
-
class PrefEnabledRunnable final
: public WorkerCheckAPIExposureOnMainThreadRunnable
{
@@ -103,14 +80,12 @@ NS_IMPL_RELEASE_INHERITED(Performance, DOMEventTargetHelper)
/* static */ already_AddRefed<Performance>
Performance::CreateForMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
- nsITimedChannel* aChannel,
- Performance* aParentPerformance)
+ nsITimedChannel* aChannel)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<Performance> performance =
- new PerformanceMainThread(aWindow, aDOMTiming, aChannel,
- aParentPerformance);
+ new PerformanceMainThread(aWindow, aDOMTiming, aChannel);
return performance.forget();
}
@@ -142,6 +117,24 @@ Performance::Performance(nsPIDOMWindowInner* aWindow)
Performance::~Performance()
{}
+DOMHighResTimeStamp
+Performance::Now() const
+{
+ TimeDuration duration = TimeStamp::Now() - CreationTimeStamp();
+ return RoundTime(duration.ToMilliseconds());
+}
+
+DOMHighResTimeStamp
+Performance::TimeOrigin()
+{
+ if (!mPerformanceService) {
+ mPerformanceService = PerformanceService::GetOrCreate();
+ }
+
+ MOZ_ASSERT(mPerformanceService);
+ return mPerformanceService->TimeOrigin(CreationTimeStamp());
+}
+
JSObject*
Performance::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
@@ -266,7 +259,7 @@ Performance::ClearMarks(const Optional<nsAString>& aName)
DOMHighResTimeStamp
Performance::ResolveTimestampFromName(const nsAString& aName,
- ErrorResult& aRv)
+ ErrorResult& aRv)
{
AutoTArray<RefPtr<PerformanceEntry>, 1> arr;
DOMHighResTimeStamp ts;
diff --git a/dom/performance/Performance.h b/dom/performance/Performance.h
index bc70589a5..4debecc90 100644
--- a/dom/performance/Performance.h
+++ b/dom/performance/Performance.h
@@ -24,6 +24,7 @@ namespace dom {
class PerformanceEntry;
class PerformanceNavigation;
class PerformanceObserver;
+class PerformanceService;
class PerformanceTiming;
namespace workers {
@@ -45,8 +46,7 @@ public:
static already_AddRefed<Performance>
CreateForMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
- nsITimedChannel* aChannel,
- Performance* aParentPerformance);
+ nsITimedChannel* aChannel);
static already_AddRefed<Performance>
CreateForWorker(workers::WorkerPrivate* aWorkerPrivate);
@@ -54,21 +54,23 @@ public:
JSObject* WrapObject(JSContext *cx,
JS::Handle<JSObject*> aGivenProto) override;
- void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval);
+ virtual void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval);
- void GetEntriesByType(const nsAString& aEntryType,
- nsTArray<RefPtr<PerformanceEntry>>& aRetval);
+ virtual void GetEntriesByType(const nsAString& aEntryType,
+ nsTArray<RefPtr<PerformanceEntry>>& aRetval);
- void GetEntriesByName(const nsAString& aName,
- const Optional<nsAString>& aEntryType,
- nsTArray<RefPtr<PerformanceEntry>>& aRetval);
+ virtual void GetEntriesByName(const nsAString& aName,
+ const Optional<nsAString>& aEntryType,
+ nsTArray<RefPtr<PerformanceEntry>>& aRetval);
virtual void AddEntry(nsIHttpChannel* channel,
nsITimedChannel* timedChannel) = 0;
void ClearResourceTimings();
- virtual DOMHighResTimeStamp Now() const = 0;
+ DOMHighResTimeStamp Now() const;
+
+ DOMHighResTimeStamp TimeOrigin();
void Mark(const nsAString& aName, ErrorResult& aRv);
@@ -101,8 +103,6 @@ public:
virtual nsITimedChannel* GetChannel() const = 0;
- virtual Performance* GetParentPerformance() const = 0;
-
protected:
Performance();
explicit Performance(nsPIDOMWindowInner* aWindow);
@@ -126,10 +126,16 @@ protected:
virtual DOMHighResTimeStamp CreationTime() const = 0;
- virtual bool IsPerformanceTimingAttribute(const nsAString& aName) = 0;
+ virtual bool IsPerformanceTimingAttribute(const nsAString& aName)
+ {
+ return false;
+ }
virtual DOMHighResTimeStamp
- GetPerformanceTimingFromString(const nsAString& aTimingName) = 0;
+ GetPerformanceTimingFromString(const nsAString& aTimingName)
+ {
+ return 0;
+ }
bool IsResourceEntryLimitReached() const
{
@@ -147,13 +153,15 @@ protected:
nsTObserverArray<PerformanceObserver*> mObservers;
-private:
+protected:
nsTArray<RefPtr<PerformanceEntry>> mUserEntries;
nsTArray<RefPtr<PerformanceEntry>> mResourceEntries;
uint64_t mResourceTimingBufferSize;
static const uint64_t kDefaultResourceTimingBufferSize = 150;
bool mPendingNotificationObserversTask;
+
+ RefPtr<PerformanceService> mPerformanceService;
};
} // namespace dom
diff --git a/dom/performance/PerformanceEntry.h b/dom/performance/PerformanceEntry.h
index bc4f84f1c..0af9f669e 100644
--- a/dom/performance/PerformanceEntry.h
+++ b/dom/performance/PerformanceEntry.h
@@ -90,6 +90,27 @@ protected:
nsString mEntryType;
};
+// Helper classes
+class MOZ_STACK_CLASS PerformanceEntryComparator final
+{
+public:
+ bool Equals(const PerformanceEntry* aElem1,
+ const PerformanceEntry* aElem2) const
+ {
+ MOZ_ASSERT(aElem1 && aElem2,
+ "Trying to compare null performance entries");
+ return aElem1->StartTime() == aElem2->StartTime();
+ }
+
+ bool LessThan(const PerformanceEntry* aElem1,
+ const PerformanceEntry* aElem2) const
+ {
+ MOZ_ASSERT(aElem1 && aElem2,
+ "Trying to compare null performance entries");
+ return aElem1->StartTime() < aElem2->StartTime();
+ }
+};
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/performance/PerformanceMainThread.cpp b/dom/performance/PerformanceMainThread.cpp
index 86d42c5f8..64c06d3ea 100644
--- a/dom/performance/PerformanceMainThread.cpp
+++ b/dom/performance/PerformanceMainThread.cpp
@@ -6,6 +6,7 @@
#include "PerformanceMainThread.h"
#include "PerformanceNavigation.h"
+#include "nsICacheInfoChannel.h"
namespace mozilla {
namespace dom {
@@ -16,7 +17,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMainThread,
Performance)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming,
mNavigation,
- mParentPerformance)
+ mDocEntry)
tmp->mMozMemory = nullptr;
mozilla::DropJSObjects(this);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -25,7 +26,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMainThread,
Performance)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming,
mNavigation,
- mParentPerformance)
+ mDocEntry)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -45,12 +46,10 @@ NS_INTERFACE_MAP_END_INHERITING(Performance)
PerformanceMainThread::PerformanceMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
- nsITimedChannel* aChannel,
- Performance* aParentPerformance)
+ nsITimedChannel* aChannel)
: Performance(aWindow)
, mDOMTiming(aDOMTiming)
, mChannel(aChannel)
- , mParentPerformance(aParentPerformance)
{
MOZ_ASSERT(aWindow, "Parent window object should be provided");
}
@@ -78,7 +77,7 @@ PerformanceTiming*
PerformanceMainThread::Timing()
{
if (!mTiming) {
- // For navigation timing, the third argument (an nsIHtttpChannel) is null
+ // For navigation timing, the third argument (an nsIHttpChannel) is null
// since the cross-domain redirect were already checked. The last argument
// (zero time) for performance.timing is the navigation start value.
mTiming = new PerformanceTiming(this, mChannel, nullptr,
@@ -108,12 +107,6 @@ PerformanceMainThread::Navigation()
return mNavigation;
}
-DOMHighResTimeStamp
-PerformanceMainThread::Now() const
-{
- return RoundTime(GetDOMTiming()->TimeStampToDOMHighRes(TimeStamp::Now()));
-}
-
/**
* An entry should be added only after the resource is loaded.
* This method is not thread safe and can only be called on the main thread.
@@ -161,27 +154,7 @@ PerformanceMainThread::AddEntry(nsIHttpChannel* channel,
// The PerformanceResourceTiming object will use the PerformanceTiming
// object to get all the required timings.
RefPtr<PerformanceResourceTiming> performanceEntry =
- new PerformanceResourceTiming(performanceTiming, this, entryName);
-
- nsAutoCString protocol;
- channel->GetProtocolVersion(protocol);
- performanceEntry->SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol));
-
- uint64_t encodedBodySize = 0;
- channel->GetEncodedBodySize(&encodedBodySize);
- performanceEntry->SetEncodedBodySize(encodedBodySize);
-
- uint64_t transferSize = 0;
- channel->GetTransferSize(&transferSize);
- performanceEntry->SetTransferSize(transferSize);
-
- uint64_t decodedBodySize = 0;
- channel->GetDecodedBodySize(&decodedBodySize);
- if (decodedBodySize == 0) {
- decodedBodySize = encodedBodySize;
- }
- performanceEntry->SetDecodedBodySize(decodedBodySize);
-
+ new PerformanceResourceTiming(performanceTiming, this, entryName, channel);
// If the initiator type had no valid value, then set it to the default
// ("other") value.
if (initiatorType.IsEmpty()) {
@@ -335,5 +308,65 @@ PerformanceMainThread::CreationTime() const
return GetDOMTiming()->GetNavigationStart();
}
+void
+PerformanceMainThread::EnsureDocEntry()
+{
+ if (!mDocEntry && nsContentUtils::IsPerformanceNavigationTimingEnabled()) {
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
+ RefPtr<PerformanceTiming> timing =
+ new PerformanceTiming(this, mChannel, nullptr, 0);
+ mDocEntry = new PerformanceNavigationTiming(timing, this,
+ httpChannel);
+ }
+}
+
+
+void
+PerformanceMainThread::GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval)
+{
+ aRetval = mResourceEntries;
+ aRetval.AppendElements(mUserEntries);
+
+ EnsureDocEntry();
+ if (mDocEntry) {
+ aRetval.AppendElement(mDocEntry);
+ }
+
+ aRetval.Sort(PerformanceEntryComparator());
+}
+
+void
+PerformanceMainThread::GetEntriesByType(const nsAString& aEntryType,
+ nsTArray<RefPtr<PerformanceEntry>>& aRetval)
+{
+ if (aEntryType.EqualsLiteral("navigation")) {
+ aRetval.Clear();
+ EnsureDocEntry();
+ if (mDocEntry) {
+ aRetval.AppendElement(mDocEntry);
+ }
+ return;
+ }
+
+ Performance::GetEntriesByType(aEntryType, aRetval);
+}
+
+void
+PerformanceMainThread::GetEntriesByName(const nsAString& aName,
+ const Optional<nsAString>& aEntryType,
+ nsTArray<RefPtr<PerformanceEntry>>& aRetval)
+{
+ if (aName.EqualsLiteral("document")) {
+ aRetval.Clear();
+ EnsureDocEntry();
+ if (mDocEntry) {
+ aRetval.AppendElement(mDocEntry);
+ }
+ return;
+ }
+
+ Performance::GetEntriesByName(aName, aEntryType, aRetval);
+}
+
} // dom namespace
} // mozilla namespace
diff --git a/dom/performance/PerformanceMainThread.h b/dom/performance/PerformanceMainThread.h
index 84773f29b..9f0e185fc 100644
--- a/dom/performance/PerformanceMainThread.h
+++ b/dom/performance/PerformanceMainThread.h
@@ -17,16 +17,12 @@ class PerformanceMainThread final : public Performance
public:
PerformanceMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
- nsITimedChannel* aChannel,
- Performance* aParentPerformance);
+ nsITimedChannel* aChannel);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMainThread,
Performance)
- // Performance WebIDL methods
- DOMHighResTimeStamp Now() const override;
-
virtual PerformanceTiming* Timing() override;
virtual PerformanceNavigation* Navigation() override;
@@ -51,10 +47,14 @@ public:
return mChannel;
}
- virtual Performance* GetParentPerformance() const override
- {
- return mParentPerformance;
- }
+ // The GetEntries* methods need to be overriden in order to add the
+ // the document entry of type navigation.
+ virtual void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval) override;
+ virtual void GetEntriesByType(const nsAString& aEntryType,
+ nsTArray<RefPtr<PerformanceEntry>>& aRetval) override;
+ virtual void GetEntriesByName(const nsAString& aName,
+ const Optional<nsAString>& aEntryType,
+ nsTArray<RefPtr<PerformanceEntry>>& aRetval) override;
protected:
~PerformanceMainThread();
@@ -72,12 +72,13 @@ protected:
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
void DispatchBufferFullEvent() override;
+ void EnsureDocEntry();
+ RefPtr<PerformanceEntry> mDocEntry;
RefPtr<nsDOMNavigationTiming> mDOMTiming;
nsCOMPtr<nsITimedChannel> mChannel;
RefPtr<PerformanceTiming> mTiming;
RefPtr<PerformanceNavigation> mNavigation;
- RefPtr<Performance> mParentPerformance;
JS::Heap<JSObject*> mMozMemory;
};
diff --git a/dom/performance/PerformanceNavigationTiming.cpp b/dom/performance/PerformanceNavigationTiming.cpp
new file mode 100644
index 000000000..d7e16725a
--- /dev/null
+++ b/dom/performance/PerformanceNavigationTiming.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/PerformanceNavigationTiming.h"
+#include "mozilla/dom/PerformanceNavigationTimingBinding.h"
+#include "mozilla/TimerClamping.h"
+
+using namespace mozilla::dom;
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceNavigationTiming)
+NS_INTERFACE_MAP_END_INHERITING(PerformanceResourceTiming)
+
+NS_IMPL_ADDREF_INHERITED(PerformanceNavigationTiming, PerformanceResourceTiming)
+NS_IMPL_RELEASE_INHERITED(PerformanceNavigationTiming, PerformanceResourceTiming)
+
+JSObject*
+PerformanceNavigationTiming::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ return PerformanceNavigationTimingBinding::Wrap(aCx, this, aGivenProto);
+}
+
+DOMHighResTimeStamp
+PerformanceNavigationTiming::UnloadEventStart() const
+{
+ return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetUnloadEventStartHighRes());
+}
+
+DOMHighResTimeStamp
+PerformanceNavigationTiming::UnloadEventEnd() const
+{
+ return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetUnloadEventEndHighRes());
+}
+
+DOMHighResTimeStamp
+PerformanceNavigationTiming::DomInteractive() const
+{
+ return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomInteractiveHighRes());
+}
+
+DOMHighResTimeStamp
+PerformanceNavigationTiming::DomContentLoadedEventStart() const
+{
+ return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomContentLoadedEventStartHighRes());
+}
+
+DOMHighResTimeStamp
+PerformanceNavigationTiming::DomContentLoadedEventEnd() const
+{
+ return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomContentLoadedEventEndHighRes());
+}
+
+DOMHighResTimeStamp
+PerformanceNavigationTiming::DomComplete() const
+{
+ return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomCompleteHighRes());
+}
+
+DOMHighResTimeStamp
+PerformanceNavigationTiming::LoadEventStart() const
+{
+ return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetLoadEventStartHighRes());
+}
+
+DOMHighResTimeStamp
+PerformanceNavigationTiming::LoadEventEnd() const
+{
+ return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetLoadEventEndHighRes());
+}
+
+NavigationType
+PerformanceNavigationTiming::Type() const
+{
+ switch(mTiming->GetDOMTiming()->GetType()) {
+ case nsDOMNavigationTiming::TYPE_NAVIGATE:
+ return NavigationType::Navigate;
+ break;
+ case nsDOMNavigationTiming::TYPE_RELOAD:
+ return NavigationType::Reload;
+ break;
+ case nsDOMNavigationTiming::TYPE_BACK_FORWARD:
+ return NavigationType::Back_forward;
+ break;
+ default:
+ // The type is TYPE_RESERVED or some other value that was later added.
+ // We fallback to the default of Navigate.
+ return NavigationType::Navigate;
+ }
+}
+
+uint16_t
+PerformanceNavigationTiming::RedirectCount() const
+{
+ return mTiming->GetRedirectCount();
+}
diff --git a/dom/performance/PerformanceNavigationTiming.h b/dom/performance/PerformanceNavigationTiming.h
new file mode 100644
index 000000000..8555f1987
--- /dev/null
+++ b/dom/performance/PerformanceNavigationTiming.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_PerformanceNavigationTiming_h___
+#define mozilla_dom_PerformanceNavigationTiming_h___
+
+#include "nsCOMPtr.h"
+#include "nsIChannel.h"
+#include "nsITimedChannel.h"
+#include "mozilla/dom/PerformanceResourceTiming.h"
+#include "mozilla/dom/PerformanceNavigationTimingBinding.h"
+#include "nsIHttpChannel.h"
+
+namespace mozilla {
+namespace dom {
+
+// https://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming
+class PerformanceNavigationTiming final
+ : public PerformanceResourceTiming
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // Note that aPerformanceTiming must be initalized with zeroTime = 0
+ // so that timestamps are relative to startTime, as opposed to the
+ // performance.timing object for which timestamps are absolute and has a
+ // zeroTime initialized to navigationStart
+ explicit PerformanceNavigationTiming(PerformanceTiming* aPerformanceTiming,
+ Performance* aPerformance,
+ nsIHttpChannel* aChannel)
+ : PerformanceResourceTiming(aPerformanceTiming, aPerformance,
+ NS_LITERAL_STRING("document"), aChannel) {
+ SetEntryType(NS_LITERAL_STRING("navigation"));
+ SetInitiatorType(NS_LITERAL_STRING("navigation"));
+ }
+
+ DOMHighResTimeStamp Duration() const override
+ {
+ return LoadEventEnd() - StartTime();
+ }
+
+ DOMHighResTimeStamp StartTime() const override
+ {
+ return 0;
+ }
+
+ JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+ DOMHighResTimeStamp UnloadEventStart() const;
+ DOMHighResTimeStamp UnloadEventEnd() const;
+
+ DOMHighResTimeStamp DomInteractive() const;
+ DOMHighResTimeStamp DomContentLoadedEventStart() const;
+ DOMHighResTimeStamp DomContentLoadedEventEnd() const;
+ DOMHighResTimeStamp DomComplete() const;
+ DOMHighResTimeStamp LoadEventStart() const;
+ DOMHighResTimeStamp LoadEventEnd() const;
+ NavigationType Type() const;
+ uint16_t RedirectCount() const;
+
+private:
+ ~PerformanceNavigationTiming() {}
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_PerformanceNavigationTiming_h___
diff --git a/dom/performance/PerformanceObserver.cpp b/dom/performance/PerformanceObserver.cpp
index 11dd30ac2..d02acfb09 100644
--- a/dom/performance/PerformanceObserver.cpp
+++ b/dom/performance/PerformanceObserver.cpp
@@ -114,12 +114,13 @@ PerformanceObserver::Notify()
RefPtr<PerformanceObserverEntryList> list =
new PerformanceObserverEntryList(this, mQueuedEntries);
+ mQueuedEntries.Clear();
+
ErrorResult rv;
mCallback->Call(this, *list, *this, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
}
- mQueuedEntries.Clear();
}
void
@@ -170,6 +171,17 @@ PerformanceObserver::Observe(const PerformanceObserverInit& aOptions,
mEntryTypes.SwapElements(validEntryTypes);
mPerformance->AddObserver(this);
+
+ if (aOptions.mBuffered) {
+ for (auto entryType : mEntryTypes) {
+ nsTArray<RefPtr<PerformanceEntry>> existingEntries;
+ mPerformance->GetEntriesByType(entryType, existingEntries);
+ if (!existingEntries.IsEmpty()) {
+ mQueuedEntries.AppendElements(existingEntries);
+ }
+ }
+ }
+
mConnected = true;
}
diff --git a/dom/performance/PerformanceObserverEntryList.cpp b/dom/performance/PerformanceObserverEntryList.cpp
index 349103f08..20e818f3d 100644
--- a/dom/performance/PerformanceObserverEntryList.cpp
+++ b/dom/performance/PerformanceObserverEntryList.cpp
@@ -66,6 +66,7 @@ PerformanceObserverEntryList::GetEntries(
aRetval.AppendElement(entry);
}
+ aRetval.Sort(PerformanceEntryComparator());
}
void
@@ -79,6 +80,7 @@ PerformanceObserverEntryList::GetEntriesByType(
aRetval.AppendElement(entry);
}
}
+ aRetval.Sort(PerformanceEntryComparator());
}
void
@@ -88,9 +90,18 @@ PerformanceObserverEntryList::GetEntriesByName(
nsTArray<RefPtr<PerformanceEntry>>& aRetval)
{
aRetval.Clear();
+ const bool typePassed = aEntryType.WasPassed();
for (const RefPtr<PerformanceEntry>& entry : mEntries) {
- if (entry->GetName().Equals(aName)) {
- aRetval.AppendElement(entry);
+ if (!entry->GetName().Equals(aName)) {
+ continue;
}
+
+ if (typePassed &&
+ !entry->GetEntryType().Equals(aEntryType.Value())) {
+ continue;
+ }
+
+ aRetval.AppendElement(entry);
}
+ aRetval.Sort(PerformanceEntryComparator());
}
diff --git a/dom/performance/PerformanceResourceTiming.cpp b/dom/performance/PerformanceResourceTiming.cpp
index 60a20ca28..9c5475041 100644
--- a/dom/performance/PerformanceResourceTiming.cpp
+++ b/dom/performance/PerformanceResourceTiming.cpp
@@ -6,6 +6,7 @@
#include "PerformanceResourceTiming.h"
#include "mozilla/dom/PerformanceResourceTimingBinding.h"
+#include "mozilla/Unused.h"
using namespace mozilla::dom;
@@ -25,7 +26,8 @@ NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry)
PerformanceResourceTiming::PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
Performance* aPerformance,
- const nsAString& aName)
+ const nsAString& aName,
+ nsIHttpChannel* aChannel)
: PerformanceEntry(aPerformance, aName, NS_LITERAL_STRING("resource")),
mTiming(aPerformanceTiming),
mEncodedBodySize(0),
@@ -33,6 +35,34 @@ PerformanceResourceTiming::PerformanceResourceTiming(PerformanceTiming* aPerform
mDecodedBodySize(0)
{
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
+ SetPropertiesFromChannel(aChannel);
+}
+
+void
+PerformanceResourceTiming::SetPropertiesFromChannel(nsIHttpChannel* aChannel)
+{
+ if (!aChannel) {
+ return;
+ }
+
+ nsAutoCString protocol;
+ Unused << aChannel->GetProtocolVersion(protocol);
+ SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol));
+
+ uint64_t encodedBodySize = 0;
+ Unused << aChannel->GetEncodedBodySize(&encodedBodySize);
+ SetEncodedBodySize(encodedBodySize);
+
+ uint64_t transferSize = 0;
+ Unused << aChannel->GetTransferSize(&transferSize);
+ SetTransferSize(transferSize);
+
+ uint64_t decodedBodySize = 0;
+ Unused << aChannel->GetDecodedBodySize(&decodedBodySize);
+ if (decodedBodySize == 0) {
+ decodedBodySize = encodedBodySize;
+ }
+ SetDecodedBodySize(decodedBodySize);
}
PerformanceResourceTiming::~PerformanceResourceTiming()
@@ -42,8 +72,22 @@ PerformanceResourceTiming::~PerformanceResourceTiming()
DOMHighResTimeStamp
PerformanceResourceTiming::StartTime() const
{
- DOMHighResTimeStamp startTime = mTiming->RedirectStartHighRes();
- return startTime ? startTime : mTiming->FetchStartHighRes();
+ // Force the start time to be the earliest of:
+ // - RedirectStart
+ // - WorkerStart
+ // - AsyncOpen
+ // Ignore zero values. The RedirectStart and WorkerStart values
+ // can come from earlier redirected channels prior to the AsyncOpen
+ // time being recorded.
+ DOMHighResTimeStamp redirect = mTiming->RedirectStartHighRes();
+ redirect = redirect ? redirect : DBL_MAX;
+
+ DOMHighResTimeStamp worker = mTiming->WorkerStartHighRes();
+ worker = worker ? worker : DBL_MAX;
+
+ DOMHighResTimeStamp asyncOpen = mTiming->AsyncOpenHighRes();
+
+ return std::min(asyncOpen, std::min(redirect, worker));
}
JSObject*
diff --git a/dom/performance/PerformanceResourceTiming.h b/dom/performance/PerformanceResourceTiming.h
index 2dd6b4a06..98a03327e 100644
--- a/dom/performance/PerformanceResourceTiming.h
+++ b/dom/performance/PerformanceResourceTiming.h
@@ -18,7 +18,7 @@ namespace mozilla {
namespace dom {
// http://www.w3.org/TR/resource-timing/#performanceresourcetiming
-class PerformanceResourceTiming final : public PerformanceEntry
+class PerformanceResourceTiming : public PerformanceEntry
{
public:
typedef mozilla::TimeStamp TimeStamp;
@@ -30,7 +30,8 @@ public:
PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
Performance* aPerformance,
- const nsAString& aName);
+ const nsAString& aName,
+ nsIHttpChannel* aChannel = nullptr);
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
@@ -62,6 +63,12 @@ public:
mNextHopProtocol = aNextHopProtocol;
}
+ DOMHighResTimeStamp WorkerStart() const {
+ return mTiming && mTiming->TimingAllowed()
+ ? mTiming->WorkerStartHighRes()
+ : 0;
+ }
+
DOMHighResTimeStamp FetchStart() const {
return mTiming
? mTiming->FetchStartHighRes()
@@ -170,6 +177,7 @@ public:
protected:
virtual ~PerformanceResourceTiming();
+ void SetPropertiesFromChannel(nsIHttpChannel* aChannel);
nsString mInitiatorType;
nsString mNextHopProtocol;
diff --git a/dom/performance/PerformanceService.cpp b/dom/performance/PerformanceService.cpp
new file mode 100644
index 000000000..cf119af89
--- /dev/null
+++ b/dom/performance/PerformanceService.cpp
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PerformanceService.h"
+
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/StaticPtr.h"
+
+namespace mozilla {
+namespace dom {
+
+static StaticRefPtr<PerformanceService> gPerformanceService;
+static StaticMutex gPerformanceServiceMutex;
+
+/* static */ PerformanceService*
+PerformanceService::GetOrCreate()
+{
+ StaticMutexAutoLock al(gPerformanceServiceMutex);
+
+ if (!gPerformanceService) {
+ gPerformanceService = new PerformanceService();
+ ClearOnShutdown(&gPerformanceService);
+ }
+
+ return gPerformanceService;
+}
+
+DOMHighResTimeStamp
+PerformanceService::TimeOrigin(const TimeStamp& aCreationTimeStamp) const
+{
+ return (aCreationTimeStamp - mCreationTimeStamp).ToMilliseconds() +
+ (mCreationEpochTime / PR_USEC_PER_MSEC);
+}
+
+PerformanceService::PerformanceService()
+{
+ mCreationTimeStamp = TimeStamp::Now();
+ mCreationEpochTime = PR_Now();
+}
+
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/performance/PerformanceService.h b/dom/performance/PerformanceService.h
new file mode 100644
index 000000000..9abbd674d
--- /dev/null
+++ b/dom/performance/PerformanceService.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef dom_performance_PerformanceService_h
+#define dom_performance_PerformanceService_h
+
+#include "mozilla/TimeStamp.h"
+#include "nsCOMPtr.h"
+#include "nsDOMNavigationTiming.h"
+
+namespace mozilla {
+namespace dom {
+
+// This class is thread-safe.
+
+// We use this singleton for having the correct value of performance.timeOrigin.
+// This value must be calculated on top of the pair:
+// - mCreationTimeStamp (monotonic clock)
+// - mCreationEpochTime (unix epoch time)
+// These 2 values must be taken "at the same time" in order to be used
+// correctly.
+
+class PerformanceService
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PerformanceService)
+
+ static PerformanceService*
+ GetOrCreate();
+
+ DOMHighResTimeStamp
+ TimeOrigin(const TimeStamp& aCreationTimeStamp) const;
+
+private:
+ PerformanceService();
+ ~PerformanceService() = default;
+
+ TimeStamp mCreationTimeStamp;
+ PRTime mCreationEpochTime;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // dom_performance_PerformanceService_h
diff --git a/dom/performance/PerformanceTiming.cpp b/dom/performance/PerformanceTiming.cpp
index e2f76a21f..887a23938 100755
--- a/dom/performance/PerformanceTiming.cpp
+++ b/dom/performance/PerformanceTiming.cpp
@@ -73,6 +73,7 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
{
if (aChannel) {
aChannel->GetAsyncOpen(&mAsyncOpen);
+ aChannel->GetDispatchFetchEventStart(&mWorkerStart);
aChannel->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin);
aChannel->GetRedirectCount(&mRedirectCount);
aChannel->GetRedirectStart(&mRedirectStart);
@@ -88,31 +89,39 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
aChannel->GetResponseEnd(&mResponseEnd);
aChannel->GetCacheReadEnd(&mCacheReadEnd);
- // the performance timing api essentially requires that the event timestamps
- // are >= asyncOpen().. but in truth the browser engages in a number of
- // speculative activities that sometimes mean connections and lookups begin
- // earlier. Workaround that here by just using asyncOpen as the minimum
- // timestamp for dns and connection info.
+ // The performance timing api essentially requires that the event timestamps
+ // have a strict relation with each other. The truth, however, is the browser
+ // engages in a number of speculative activities that sometimes mean connections
+ // and lookups begin at different times. Workaround that here by clamping
+ // these values to what we expect FetchStart to be. This means the later of
+ // AsyncOpen or WorkerStart times.
if (!mAsyncOpen.IsNull()) {
- if (!mDomainLookupStart.IsNull() && mDomainLookupStart < mAsyncOpen) {
- mDomainLookupStart = mAsyncOpen;
+ // We want to clamp to the expected FetchStart value. This is later of
+ // the AsyncOpen and WorkerStart values.
+ const TimeStamp* clampTime = &mAsyncOpen;
+ if (!mWorkerStart.IsNull() && mWorkerStart > mAsyncOpen) {
+ clampTime = &mWorkerStart;
}
- if (!mDomainLookupEnd.IsNull() && mDomainLookupEnd < mAsyncOpen) {
- mDomainLookupEnd = mAsyncOpen;
+ if (!mDomainLookupStart.IsNull() && mDomainLookupStart < *clampTime) {
+ mDomainLookupStart = *clampTime;
}
- if (!mConnectStart.IsNull() && mConnectStart < mAsyncOpen) {
- mConnectStart = mAsyncOpen;
+ if (!mDomainLookupEnd.IsNull() && mDomainLookupEnd < *clampTime) {
+ mDomainLookupEnd = *clampTime;
+ }
+
+ if (!mConnectStart.IsNull() && mConnectStart < *clampTime) {
+ mConnectStart = *clampTime;
}
if (mSecureConnection && !mSecureConnectionStart.IsNull() &&
- mSecureConnectionStart < mAsyncOpen) {
- mSecureConnectionStart = mAsyncOpen;
+ mSecureConnectionStart < *clampTime) {
+ mSecureConnectionStart = *clampTime;
}
- if (!mConnectEnd.IsNull() && mConnectEnd < mAsyncOpen) {
- mConnectEnd = mAsyncOpen;
+ if (!mConnectEnd.IsNull() && mConnectEnd < *clampTime) {
+ mConnectEnd = *clampTime;
}
}
}
@@ -131,9 +140,13 @@ PerformanceTiming::FetchStartHighRes()
}
MOZ_ASSERT(!mAsyncOpen.IsNull(), "The fetch start time stamp should always be "
"valid if the performance timing is enabled");
- mFetchStart = (!mAsyncOpen.IsNull())
- ? TimeStampToDOMHighRes(mAsyncOpen)
- : 0.0;
+ if (!mAsyncOpen.IsNull()) {
+ if (!mWorkerStart.IsNull() && mWorkerStart > mAsyncOpen) {
+ mFetchStart = TimeStampToDOMHighRes(mWorkerStart);
+ } else {
+ mFetchStart = TimeStampToDOMHighRes(mAsyncOpen);
+ }
+ }
}
return TimerClamping::ReduceMsTimeValue(mFetchStart);
}
@@ -180,7 +193,7 @@ PerformanceTiming::TimingAllowed() const
return mTimingAllowed;
}
-uint16_t
+uint8_t
PerformanceTiming::GetRedirectCount() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
@@ -205,6 +218,26 @@ PerformanceTiming::ShouldReportCrossOriginRedirect() const
return (mRedirectCount != 0) && mReportCrossOriginRedirect;
}
+DOMHighResTimeStamp
+PerformanceTiming::AsyncOpenHighRes()
+{
+ if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
+ mAsyncOpen.IsNull()) {
+ return mZeroTime;
+ }
+ return TimeStampToReducedDOMHighResOrFetchStart(mAsyncOpen);
+}
+
+DOMHighResTimeStamp
+PerformanceTiming::WorkerStartHighRes()
+{
+ if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
+ mWorkerStart.IsNull()) {
+ return mZeroTime;
+ }
+ return TimeStampToReducedDOMHighResOrFetchStart(mWorkerStart);
+}
+
/**
* RedirectStartHighRes() is used by both the navigation timing and the
* resource timing. Since, navigation timing and resource timing check and
diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h
index fc7e7d5bd..435e1bca1 100755
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -139,7 +139,7 @@ public:
return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventEnd());
}
- uint16_t GetRedirectCount() const;
+ uint8_t GetRedirectCount() const;
// Checks if the resource is either same origin as the page that started
// the load, or if the response contains the Timing-Allow-Origin header
@@ -155,7 +155,12 @@ public:
// the timing-allow-origin check in HttpBaseChannel::TimingAllowCheck
bool ShouldReportCrossOriginRedirect() const;
+ // The last channel's AsyncOpen time. This may occur before the FetchStart
+ // in some cases.
+ DOMHighResTimeStamp AsyncOpenHighRes();
+
// High resolution (used by resource timing)
+ DOMHighResTimeStamp WorkerStartHighRes();
DOMHighResTimeStamp FetchStartHighRes();
DOMHighResTimeStamp RedirectStartHighRes();
DOMHighResTimeStamp RedirectEndHighRes();
@@ -237,6 +242,14 @@ public:
return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetLoadEventEnd());
}
+ DOMTimeMilliSec TimeToNonBlankPaint() const
+ {
+ if (!nsContentUtils::IsPerformanceTimingEnabled()) {
+ return 0;
+ }
+ return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetTimeToNonBlankPaint());
+ }
+
private:
~PerformanceTiming();
@@ -253,6 +266,7 @@ private:
DOMHighResTimeStamp mZeroTime;
TimeStamp mAsyncOpen;
+ TimeStamp mWorkerStart;
TimeStamp mRedirectStart;
TimeStamp mRedirectEnd;
TimeStamp mDomainLookupStart;
@@ -265,7 +279,7 @@ private:
TimeStamp mCacheReadStart;
TimeStamp mResponseEnd;
TimeStamp mCacheReadEnd;
- uint16_t mRedirectCount;
+ uint8_t mRedirectCount;
bool mTimingAllowed;
bool mAllRedirectsSameOrigin;
bool mInitialized;
diff --git a/dom/performance/PerformanceWorker.cpp b/dom/performance/PerformanceWorker.cpp
index 85ca2ccd8..f10c58446 100644
--- a/dom/performance/PerformanceWorker.cpp
+++ b/dom/performance/PerformanceWorker.cpp
@@ -23,37 +23,6 @@ PerformanceWorker::~PerformanceWorker()
mWorkerPrivate->AssertIsOnWorkerThread();
}
-DOMHighResTimeStamp
-PerformanceWorker::Now() const
-{
- TimeDuration duration =
- TimeStamp::Now() - mWorkerPrivate->NowBaseTimeStamp();
- return RoundTime(duration.ToMilliseconds());
-}
-
-// To be removed once bug 1124165 lands
-bool
-PerformanceWorker::IsPerformanceTimingAttribute(const nsAString& aName)
-{
- // In workers we just support navigationStart.
- return aName.EqualsASCII("navigationStart");
-}
-
-DOMHighResTimeStamp
-PerformanceWorker::GetPerformanceTimingFromString(const nsAString& aProperty)
-{
- if (!IsPerformanceTimingAttribute(aProperty)) {
- return 0;
- }
-
- if (aProperty.EqualsLiteral("navigationStart")) {
- return mWorkerPrivate->NowBaseTime();
- }
-
- MOZ_CRASH("IsPerformanceTimingAttribute and GetPerformanceTimingFromString are out of sync");
- return 0;
-}
-
void
PerformanceWorker::InsertUserEntry(PerformanceEntry* aEntry)
{
@@ -72,13 +41,13 @@ PerformanceWorker::InsertUserEntry(PerformanceEntry* aEntry)
TimeStamp
PerformanceWorker::CreationTimeStamp() const
{
- return mWorkerPrivate->NowBaseTimeStamp();
+ return mWorkerPrivate->CreationTimeStamp();
}
DOMHighResTimeStamp
PerformanceWorker::CreationTime() const
{
- return mWorkerPrivate->NowBaseTime();
+ return mWorkerPrivate->CreationTime();
}
} // dom namespace
diff --git a/dom/performance/PerformanceWorker.h b/dom/performance/PerformanceWorker.h
index 7eef0d974..346bdd026 100644
--- a/dom/performance/PerformanceWorker.h
+++ b/dom/performance/PerformanceWorker.h
@@ -21,9 +21,6 @@ class PerformanceWorker final : public Performance
public:
explicit PerformanceWorker(workers::WorkerPrivate* aWorkerPrivate);
- // Performance WebIDL methods
- DOMHighResTimeStamp Now() const override;
-
virtual PerformanceTiming* Timing() override
{
MOZ_CRASH("This should not be called on workers.");
@@ -64,12 +61,6 @@ public:
return nullptr;
}
- virtual Performance* GetParentPerformance() const override
- {
- MOZ_CRASH("This should not be called on workers.");
- return nullptr;
- }
-
protected:
~PerformanceWorker();
@@ -80,11 +71,6 @@ protected:
void InsertUserEntry(PerformanceEntry* aEntry) override;
- bool IsPerformanceTimingAttribute(const nsAString& aName) override;
-
- DOMHighResTimeStamp
- GetPerformanceTimingFromString(const nsAString& aTimingName) override;
-
void DispatchBufferFullEvent() override
{
MOZ_CRASH("This should not be called on workers.");
diff --git a/dom/performance/moz.build b/dom/performance/moz.build
index 3286a0a4c..e1f96fec8 100644
--- a/dom/performance/moz.build
+++ b/dom/performance/moz.build
@@ -10,9 +10,11 @@ EXPORTS.mozilla.dom += [
'PerformanceMark.h',
'PerformanceMeasure.h',
'PerformanceNavigation.h',
+ 'PerformanceNavigationTiming.h',
'PerformanceObserver.h',
'PerformanceObserverEntryList.h',
'PerformanceResourceTiming.h',
+ 'PerformanceService.h',
'PerformanceTiming.h',
]
@@ -23,9 +25,11 @@ UNIFIED_SOURCES += [
'PerformanceMark.cpp',
'PerformanceMeasure.cpp',
'PerformanceNavigation.cpp',
+ 'PerformanceNavigationTiming.cpp',
'PerformanceObserver.cpp',
'PerformanceObserverEntryList.cpp',
'PerformanceResourceTiming.cpp',
+ 'PerformanceService.cpp',
'PerformanceTiming.cpp',
'PerformanceWorker.cpp',
]
diff --git a/dom/performance/tests/mochitest.ini b/dom/performance/tests/mochitest.ini
index 18f7f0e45..bee0b2e70 100644
--- a/dom/performance/tests/mochitest.ini
+++ b/dom/performance/tests/mochitest.ini
@@ -1,13 +1,11 @@
[DEFAULT]
support-files =
- performance_observer.html
test_performance_observer.js
test_performance_user_timing.js
test_worker_performance_now.js
worker_performance_user_timing.js
worker_performance_observer.js
sharedworker_performance_user_timing.js
- worker_performance_observer.html
[test_performance_observer.html]
[test_performance_user_timing.html]
@@ -15,3 +13,4 @@ support-files =
[test_worker_observer.html]
[test_sharedWorker_performance_user_timing.html]
[test_worker_performance_now.html]
+[test_timeOrigin.html]
diff --git a/dom/performance/tests/performance_observer.html b/dom/performance/tests/performance_observer.html
deleted file mode 100644
index b8ced9296..000000000
--- a/dom/performance/tests/performance_observer.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!--
- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/
--->
-<!DOCTYPE html>
-<meta charset=utf-8>
-<html>
-<head>
-<title>Test for performance observer</title>
-<script>
-'use strict';
-[
- "promise_test", "test", "setup",
- "assert_true", "assert_equals", "assert_array_equals",
- "assert_throws", "assert_unreached"
-].forEach(func => {
- window[func] = opener[func].bind(opener);
-});
-function done() {
- opener.add_completion_callback(() => {
- self.close();
- });
- opener.done();
-}
-
-</script>
-<script src="test_performance_observer.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-function makeXHR(aUrl) {
- var xmlhttp = new XMLHttpRequest();
- xmlhttp.open("get", aUrl, true);
- xmlhttp.send();
-}
-
-promise_test(t => {
- var promise = new Promise(resolve => {
- performance.clearResourceTimings();
-
- var observer = new PerformanceObserver(list => resolve(list));
- observer.observe({entryTypes: ['resource']});
- t.add_cleanup(() => observer.disconnect());
- });
-
- makeXHR("test-data.json");
-
- return promise.then(list => {
- assert_equals(list.getEntries().length, 1);
- assert_array_equals(list.getEntries(),
- performance.getEntriesByType("resource"),
- "Observed 'resource' entries should equal to entries obtained by getEntriesByType.");
-
- // getEntries filtering tests
- assert_array_equals(list.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
- performance.getEntriesByName("http://mochi.test:8888/tests/dom/base/test/test-data.json"),
- "getEntries with name filter should return correct results.");
- assert_array_equals(list.getEntries({entryType: "resource"}),
- performance.getEntriesByType("resource"),
- "getEntries with entryType filter should return correct results.");
- assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
- performance.getEntriesByType("resource"),
- "getEntries with initiatorType filter should return correct results.");
- assert_array_equals(list.getEntries({initiatorType: "link"}),
- [],
- "getEntries with non-existent initiatorType filter should return an empty array.");
- });
-}, "resource-timing test");
-
-done();
-
-</script>
-</body>
diff --git a/dom/performance/tests/test_performance_observer.html b/dom/performance/tests/test_performance_observer.html
index d36878315..7df881bd4 100644
--- a/dom/performance/tests/test_performance_observer.html
+++ b/dom/performance/tests/test_performance_observer.html
@@ -3,15 +3,55 @@
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE html>
+<html>
+<head>
<meta charset=utf-8>
<title>Test for performance observer</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<div id=log></div>
+</head>
+<body>
+<div id="log"></div>
+<script src="test_performance_observer.js"></script>
<script>
-'use strict';
-SpecialPowers.pushPrefEnv({"set": [["dom.enable_performance_observer", true]]},
- function() {
- window.open("performance_observer.html");
- });
+function makeXHR(aUrl) {
+ var xmlhttp = new XMLHttpRequest();
+ xmlhttp.open("get", aUrl, true);
+ xmlhttp.send();
+}
+
+promise_test(t => {
+ var promise = new Promise(resolve => {
+ performance.clearResourceTimings();
+
+ var observer = new PerformanceObserver(list => resolve(list));
+ observer.observe({entryTypes: ['resource']});
+ t.add_cleanup(() => observer.disconnect());
+ });
+
+ makeXHR("test-data.json");
+
+ return promise.then(list => {
+ assert_equals(list.getEntries().length, 1);
+ assert_array_equals(list.getEntries(),
+ performance.getEntriesByType("resource"),
+ "Observed 'resource' entries should equal to entries obtained by getEntriesByType.");
+
+ // getEntries filtering tests
+ assert_array_equals(list.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
+ performance.getEntriesByName("http://mochi.test:8888/tests/dom/base/test/test-data.json"),
+ "getEntries with name filter should return correct results.");
+ assert_array_equals(list.getEntries({entryType: "resource"}),
+ performance.getEntriesByType("resource"),
+ "getEntries with entryType filter should return correct results.");
+ assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
+ performance.getEntriesByType("resource"),
+ "getEntries with initiatorType filter should return correct results.");
+ assert_array_equals(list.getEntries({initiatorType: "link"}),
+ [],
+ "getEntries with non-existent initiatorType filter should return an empty array.");
+ });
+}, "resource-timing test");
+
</script>
+</body>
diff --git a/dom/performance/tests/test_performance_user_timing.js b/dom/performance/tests/test_performance_user_timing.js
index cd8261bbd..a15dbebb6 100644
--- a/dom/performance/tests/test_performance_user_timing.js
+++ b/dom/performance/tests/test_performance_user_timing.js
@@ -126,15 +126,18 @@ var steps = [
},
// Test measure
function () {
- ok(true, "Running measure addition with no start/end time test");
- performance.measure("test");
- var measures = performance.getEntriesByType("measure");
- is(measures.length, 1, "number of measures should be 1");
- var measure = measures[0];
- is(measure.name, "test", "measure name should be 'test'");
- is(measure.entryType, "measure", "measure type should be 'measure'");
- is(measure.startTime, 0, "measure start time should be zero");
- ok(measure.duration >= 0, "measure duration should not be negative");
+ // We don't have navigationStart in workers.
+ if ("window" in self) {
+ ok(true, "Running measure addition with no start/end time test");
+ performance.measure("test", "navigationStart");
+ var measures = performance.getEntriesByType("measure");
+ is(measures.length, 1, "number of measures should be 1");
+ var measure = measures[0];
+ is(measure.name, "test", "measure name should be 'test'");
+ is(measure.entryType, "measure", "measure type should be 'measure'");
+ is(measure.startTime, 0, "measure start time should be zero");
+ ok(measure.duration >= 0, "measure duration should not be negative");
+ }
},
function () {
ok(true, "Running measure addition with only start time test");
diff --git a/dom/performance/tests/test_timeOrigin.html b/dom/performance/tests/test_timeOrigin.html
new file mode 100644
index 000000000..5a8a461f3
--- /dev/null
+++ b/dom/performance/tests/test_timeOrigin.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Test for performance.timeOrigin</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="test_performance_user_timing.js"></script>
+ </head>
+ <body>
+ <script type="text/js-worker" id="worker-src">
+ postMessage({ now: performance.now(), timeOrigin: performance.timeOrigin });
+ </script>
+
+ <script type="text/js-worker" id="shared-worker-src">
+ onconnect = function(evt) {
+ evt.ports[0].postMessage({ now: performance.now(), timeOrigin: performance.timeOrigin });
+ };
+ </script>
+
+ <script class="testbody" type="text/javascript">
+
+function testBasic() {
+ ok("timeOrigin" in performance, "Performance.timeOrigin exists.");
+ ok(performance.timeOrigin > 0, "TimeOrigin must be greater than 0.");
+ next();
+}
+
+function testWorker() {
+ var now = performance.now();
+
+ var blob = new Blob([ document.getElementById("worker-src").textContent ],
+ { type: "text/javascript" });
+ var w = new Worker(URL.createObjectURL(blob));
+ w.onmessage = function(e) {
+ ok (e.now + e.timeOrigin > now + performance.now, "Comparing worker.now and window.now");
+ next();
+ }
+}
+
+function testSharedWorker() {
+ var now = performance.now();
+
+ var blob = new Blob([ document.getElementById("shared-worker-src").textContent ],
+ { type: "text/javascript" });
+ var w = new SharedWorker(URL.createObjectURL(blob));
+ w.port.onmessage = function(e) {
+ ok (e.now + e.timeOrigin > now + performance.now, "Comparing worker.now and window.now");
+ next();
+ }
+}
+
+var tests = [ testBasic, testWorker, testSharedWorker ];
+function next() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(next);
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/dom/performance/tests/test_worker_observer.html b/dom/performance/tests/test_worker_observer.html
index b9ed0c964..9a55ef1d5 100644
--- a/dom/performance/tests/test_worker_observer.html
+++ b/dom/performance/tests/test_worker_observer.html
@@ -3,15 +3,16 @@
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE html>
+<html>
+<head>
<meta charset=utf-8>
<title>Test for performance observer in worker</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<div id=log></div>
+</head>
+<body>
+<div id="log"></div>
<script>
-'use strict';
-SpecialPowers.pushPrefEnv({"set": [["dom.enable_performance_observer", true]]},
- function() {
- window.open("worker_performance_observer.html");
- });
+fetch_tests_from_worker(new Worker("worker_performance_observer.js"));
</script>
+</body>
diff --git a/dom/performance/tests/worker_performance_observer.html b/dom/performance/tests/worker_performance_observer.html
deleted file mode 100644
index 613762f52..000000000
--- a/dom/performance/tests/worker_performance_observer.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/
--->
-<!DOCTYPE html>
-<meta charset=utf-8>
-<html>
-<head>
-<title>Test for performance observer in worker</title>
-</head>
-<body>
-<div id="log"></div>
-<script>
-[
- "async_test", "test", "setup",
- "assert_true", "assert_equals", "assert_array_equals",
- "assert_throws", "fetch_tests_from_worker"
-].forEach(func => {
- window[func] = opener[func].bind(opener);
-});
-
-function done() {
- opener.add_completion_callback(() => {
- self.close();
- });
- opener.done();
-}
-
-fetch_tests_from_worker(new Worker("worker_performance_observer.js"));
-done();
-</script>
-</body>
diff --git a/dom/permission/tests/mochitest.ini b/dom/permission/tests/mochitest.ini
index 58fd048ca..2d4208e1f 100644
--- a/dom/permission/tests/mochitest.ini
+++ b/dom/permission/tests/mochitest.ini
@@ -7,7 +7,6 @@ support-files =
[test_browser.html]
skip-if = true
[test_idle.html]
-# skip-if = (toolkit == 'gonk' && debug) #debug-only failure
skip-if = true
[test_permissions.html]
skip-if = true
diff --git a/dom/plugins/base/PluginPRLibrary.cpp b/dom/plugins/base/PluginPRLibrary.cpp
index a7ad76ea4..ecc55d455 100644
--- a/dom/plugins/base/PluginPRLibrary.cpp
+++ b/dom/plugins/base/PluginPRLibrary.cpp
@@ -57,12 +57,6 @@ PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
mNPP_GetSitesWithData = pFuncs->getsiteswithdata;
return NS_OK;
}
-#elif defined(MOZ_WIDGET_GONK)
-nsresult
-PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
-{
- return NS_OK;
-}
#elif defined(XP_UNIX) && !defined(XP_MACOSX)
nsresult
PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
diff --git a/dom/plugins/base/PluginPRLibrary.h b/dom/plugins/base/PluginPRLibrary.h
index 602ad8cf8..ffd3de934 100644
--- a/dom/plugins/base/PluginPRLibrary.h
+++ b/dom/plugins/base/PluginPRLibrary.h
@@ -81,7 +81,7 @@ public:
return true;
}
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
virtual nsresult NP_Initialize(NPNetscapeFuncs* aNetscapeFuncs,
NPPluginFuncs* aFuncs, NPError* aError) override;
#else
diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp
index 1bea269cd..697bfacd4 100644
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -320,7 +320,6 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult)
if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
return NS_ERROR_FAILURE;
}
-#elif defined(MOZ_WIDGET_GONK)
#else
NPError pluginCallError;
nsresult rv = pluginLib->NP_Initialize(&sBrowserFuncs, &plugin->mPluginFuncs, &pluginCallError);
diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp
index b7651be1a..d5b1eb9ea 100644
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -535,16 +535,6 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- if (aDoCheckLoadURIChecks) {
- nsCOMPtr<nsIScriptSecurityManager> secMan(
- do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
- NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
-
- rv = secMan->CheckLoadURIWithPrincipal(content->NodePrincipal(), uri,
- nsIScriptSecurityManager::STANDARD);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
nsCOMPtr<nsIInputStream> headersDataStream;
if (aPostStream && aHeadersData) {
if (!aHeadersDataLen)
@@ -563,8 +553,21 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
Preferences::GetInt("privacy.popups.disable_from_plugins");
nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
+
+ // if security checks (in particular CheckLoadURIWithPrincipal) needs
+ // to be skipped we are creating a codebasePrincipal to make sure
+ // that security check succeeds. Please note that we do not want to
+ // fall back to using the systemPrincipal, because that would also
+ // bypass ContentPolicy checks which should still be enforced.
+ nsCOMPtr<nsIPrincipal> triggeringPrincipal;
+ if (!aDoCheckLoadURIChecks) {
+ mozilla::PrincipalOriginAttributes attrs =
+ BasePrincipal::Cast(content->NodePrincipal())->OriginAttributesRef();
+ triggeringPrincipal = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
+ }
+
rv = lh->OnLinkClick(content, uri, unitarget.get(), NullString(),
- aPostStream, headersDataStream, true);
+ aPostStream, headersDataStream, true, triggeringPrincipal);
return rv;
}
@@ -2532,6 +2535,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
NS_ASSERTION(anEvent.mMessage == eMouseDown ||
anEvent.mMessage == eMouseUp ||
anEvent.mMessage == eMouseDoubleClick ||
+ anEvent.mMessage == eMouseAuxClick ||
anEvent.mMessage == eMouseOver ||
anEvent.mMessage == eMouseOut ||
anEvent.mMessage == eMouseMove ||
@@ -2594,6 +2598,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
switch (anEvent.mMessage) {
case eMouseClick:
case eMouseDoubleClick:
+ case eMouseAuxClick:
// Button up/down events sent instead.
return rv;
default:
@@ -2797,6 +2802,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
switch (anEvent.mMessage) {
case eMouseClick:
case eMouseDoubleClick:
+ case eMouseAuxClick:
// Button up/down events sent instead.
return rv;
default:
diff --git a/dom/plugins/base/nsPluginStreamListenerPeer.cpp b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
index 26e0318e3..665e11ec1 100644
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -1381,15 +1381,6 @@ nsPluginStreamListenerPeer::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsICh
return NS_ERROR_FAILURE;
}
- nsCOMPtr<nsIAsyncVerifyRedirectCallback> proxyCallback =
- new ChannelRedirectProxyCallback(this, callback, oldChannel, newChannel);
-
- // Give NPAPI a chance to control redirects.
- bool notificationHandled = mPStreamListener->HandleRedirectNotification(oldChannel, newChannel, proxyCallback);
- if (notificationHandled) {
- return NS_OK;
- }
-
// Don't allow cross-origin 307 POST redirects.
nsCOMPtr<nsIHttpChannel> oldHttpChannel(do_QueryInterface(oldChannel));
if (oldHttpChannel) {
@@ -1413,6 +1404,15 @@ nsPluginStreamListenerPeer::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsICh
}
}
+ nsCOMPtr<nsIAsyncVerifyRedirectCallback> proxyCallback =
+ new ChannelRedirectProxyCallback(this, callback, oldChannel, newChannel);
+
+ // Give NPAPI a chance to control redirects.
+ bool notificationHandled = mPStreamListener->HandleRedirectNotification(oldChannel, newChannel, proxyCallback);
+ if (notificationHandled) {
+ return NS_OK;
+ }
+
// Fall back to channel event sink for window.
nsCOMPtr<nsIChannelEventSink> channelEventSink;
nsresult rv = GetInterfaceGlobal(NS_GET_IID(nsIChannelEventSink), getter_AddRefs(channelEventSink));
diff --git a/dom/plugins/base/nsPluginTags.cpp b/dom/plugins/base/nsPluginTags.cpp
index ddc3968fd..a794c416c 100644
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -248,7 +248,6 @@ nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo,
aPluginInfo->fMimeDescriptionArray,
aPluginInfo->fExtensionArray,
aPluginInfo->fVariantCount);
- InitSandboxLevel();
EnsureMembersAreUTF8();
FixupVersion();
}
@@ -283,7 +282,6 @@ nsPluginTag::nsPluginTag(const char* aName,
{
InitMime(aMimeTypes, aMimeDescriptions, aExtensions,
static_cast<uint32_t>(aVariants));
- InitSandboxLevel();
if (!aArgsAreUTF8)
EnsureMembersAreUTF8();
FixupVersion();
@@ -424,29 +422,6 @@ void nsPluginTag::InitMime(const char* const* aMimeTypes,
}
}
-void
-nsPluginTag::InitSandboxLevel()
-{
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
- nsAutoCString sandboxPref("dom.ipc.plugins.sandbox-level.");
- sandboxPref.Append(GetNiceFileName());
- if (NS_FAILED(Preferences::GetInt(sandboxPref.get(), &mSandboxLevel))) {
- mSandboxLevel = Preferences::GetInt("dom.ipc.plugins.sandbox-level.default"
-);
- }
-
-#if defined(_AMD64_)
- // As level 2 is now the default NPAPI sandbox level for 64-bit flash, we
- // don't want to allow a lower setting unless this environment variable is
- // set. This should be changed if the firefox.js pref file is changed.
- if (mIsFlashPlugin &&
- !PR_GetEnv("MOZ_ALLOW_WEAKER_SANDBOX") && mSandboxLevel < 2) {
- mSandboxLevel = 2;
- }
-#endif
-#endif
-}
-
#if !defined(XP_WIN) && !defined(XP_MACOSX)
static nsresult ConvertToUTF8(nsIUnicodeDecoder *aUnicodeDecoder,
nsAFlatCString& aString)
diff --git a/dom/plugins/base/nsPluginTags.h b/dom/plugins/base/nsPluginTags.h
index f1f03169b..9686d7e7a 100644
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -190,7 +190,6 @@ private:
const char* const* aMimeDescriptions,
const char* const* aExtensions,
uint32_t aVariantCount);
- void InitSandboxLevel();
nsresult EnsureMembersAreUTF8();
void FixupVersion();
diff --git a/dom/plugins/ipc/PPluginModule.ipdl b/dom/plugins/ipc/PPluginModule.ipdl
index ecde41b63..6797b49a7 100644
--- a/dom/plugins/ipc/PPluginModule.ipdl
+++ b/dom/plugins/ipc/PPluginModule.ipdl
@@ -5,7 +5,6 @@
include protocol PPluginInstance;
include protocol PPluginScriptableObject;
-include protocol PCrashReporter;
include protocol PContent;
include ProfilerTypes;
@@ -39,7 +38,6 @@ intr protocol PPluginModule
bridges PContent, PPluginModule;
manages PPluginInstance;
- manages PCrashReporter;
both:
// Window-specific message which instructs the interrupt mechanism to enter
@@ -94,17 +92,6 @@ child:
async SetParentHangTimeout(uint32_t seconds);
- intr PCrashReporter()
- returns (NativeThreadId tid, uint32_t processType);
-
- /**
- * Control the Gecko Profiler in the plugin process.
- */
- async StartProfiler(ProfilerInitParams params);
- async StopProfiler();
-
- async GatherProfile();
-
async SettingChanged(PluginSettings settings);
async NPP_SetValue_NPNVaudioDeviceChangeDetails(NPAudioDeviceChangeDetailsIPC changeDetails);
@@ -153,8 +140,6 @@ parent:
// down the plugin process in response.
async NotifyContentModuleDestroyed();
- async Profile(nsCString aProfile);
-
// Answers to request about site data
async ReturnClearSiteData(NPError aRv, uint64_t aCallbackId);
diff --git a/dom/plugins/ipc/PluginLibrary.h b/dom/plugins/ipc/PluginLibrary.h
index c9499ee0d..2f9a3f81b 100644
--- a/dom/plugins/ipc/PluginLibrary.h
+++ b/dom/plugins/ipc/PluginLibrary.h
@@ -57,7 +57,7 @@ public:
virtual bool HasRequiredFunctions() = 0;
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) = 0;
#else
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) = 0;
diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp
index 7350a7fa7..cbf6e509f 100644
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -32,7 +32,6 @@
#include "mozilla/plugins/StreamNotifyChild.h"
#include "mozilla/plugins/BrowserStreamChild.h"
#include "mozilla/plugins/PluginStreamChild.h"
-#include "mozilla/dom/CrashReporterChild.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Unused.h"
@@ -56,8 +55,6 @@ using namespace mozilla;
using namespace mozilla::ipc;
using namespace mozilla::plugins;
using namespace mozilla::widget;
-using mozilla::dom::CrashReporterChild;
-using mozilla::dom::PCrashReporterChild;
#if defined(XP_WIN)
const wchar_t * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
@@ -733,29 +730,6 @@ PluginModuleChild::AllocPPluginModuleChild(mozilla::ipc::Transport* aTransport,
return PluginModuleChild::CreateForContentProcess(aTransport, aOtherPid);
}
-PCrashReporterChild*
-PluginModuleChild::AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
- uint32_t* processType)
-{
- return new CrashReporterChild();
-}
-
-bool
-PluginModuleChild::DeallocPCrashReporterChild(PCrashReporterChild* actor)
-{
- delete actor;
- return true;
-}
-
-bool
-PluginModuleChild::AnswerPCrashReporterConstructor(
- PCrashReporterChild* actor,
- mozilla::dom::NativeThreadId* id,
- uint32_t* processType)
-{
- return true;
-}
-
void
PluginModuleChild::ActorDestroy(ActorDestroyReason why)
{
@@ -2575,48 +2549,6 @@ PluginModuleChild::ProcessNativeEvents() {
}
#endif
-bool
-PluginModuleChild::RecvStartProfiler(const ProfilerInitParams& params)
-{
- nsTArray<const char*> featureArray;
- for (size_t i = 0; i < params.features().Length(); ++i) {
- featureArray.AppendElement(params.features()[i].get());
- }
-
- nsTArray<const char*> threadNameFilterArray;
- for (size_t i = 0; i < params.threadFilters().Length(); ++i) {
- threadNameFilterArray.AppendElement(params.threadFilters()[i].get());
- }
-
- profiler_start(params.entries(), params.interval(),
- featureArray.Elements(), featureArray.Length(),
- threadNameFilterArray.Elements(), threadNameFilterArray.Length());
-
- return true;
-}
-
-bool
-PluginModuleChild::RecvStopProfiler()
-{
- profiler_stop();
- return true;
-}
-
-bool
-PluginModuleChild::RecvGatherProfile()
-{
- nsCString profileCString;
- UniquePtr<char[]> profile = profiler_get_profile();
- if (profile != nullptr) {
- profileCString = nsCString(profile.get(), strlen(profile.get()));
- } else {
- profileCString = nsCString("", 0);
- }
-
- Unused << SendProfile(profileCString);
- return true;
-}
-
NPError
PluginModuleChild::PluginRequiresAudioDeviceChanges(
PluginInstanceChild* aInstance,
diff --git a/dom/plugins/ipc/PluginModuleChild.h b/dom/plugins/ipc/PluginModuleChild.h
index 233a95369..681743582 100644
--- a/dom/plugins/ipc/PluginModuleChild.h
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -46,17 +46,12 @@ typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFun
typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
namespace mozilla {
-namespace dom {
-class PCrashReporterChild;
-} // namespace dom
-
namespace plugins {
class PluginInstanceChild;
class PluginModuleChild : public PPluginModuleChild
{
- typedef mozilla::dom::PCrashReporterChild PCrashReporterChild;
protected:
virtual mozilla::ipc::RacyInterruptPolicy
MediateInterruptRace(const MessageInfo& parent,
@@ -124,26 +119,12 @@ protected:
virtual bool
RecvSetParentHangTimeout(const uint32_t& aSeconds) override;
- virtual PCrashReporterChild*
- AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
- uint32_t* processType) override;
- virtual bool
- DeallocPCrashReporterChild(PCrashReporterChild* actor) override;
- virtual bool
- AnswerPCrashReporterConstructor(PCrashReporterChild* actor,
- mozilla::dom::NativeThreadId* id,
- uint32_t* processType) override;
-
virtual void
ActorDestroy(ActorDestroyReason why) override;
virtual bool
RecvProcessNativeEventsInInterruptCall() override;
- virtual bool RecvStartProfiler(const ProfilerInitParams& params) override;
- virtual bool RecvStopProfiler() override;
- virtual bool RecvGatherProfile() override;
-
virtual bool
AnswerModuleSupportsAsyncRender(bool* aResult) override;
public:
diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp
index 73f9c1025..2489baf16 100755
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -10,7 +10,6 @@
#include "mozilla/Attributes.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/PCrashReporterParent.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/MessageChannel.h"
#include "mozilla/ipc/ProtocolUtils.h"
@@ -19,9 +18,6 @@
#include "mozilla/plugins/PluginBridge.h"
#include "mozilla/plugins/PluginInstanceParent.h"
#include "mozilla/Preferences.h"
-#ifdef MOZ_ENABLE_PROFILER_SPS
-#include "mozilla/ProfileGatherer.h"
-#endif
#include "mozilla/ProcessHangMonitor.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
@@ -47,11 +43,6 @@
#include "PluginUtilsWin.h"
#endif
-#ifdef MOZ_ENABLE_PROFILER_SPS
-#include "nsIProfiler.h"
-#include "nsIProfileSaveEvent.h"
-#endif
-
#ifdef MOZ_WIDGET_GTK
#include <glib.h>
#elif XP_MACOSX
@@ -62,13 +53,8 @@
using base::KillProcess;
using mozilla::PluginLibrary;
-#ifdef MOZ_ENABLE_PROFILER_SPS
-using mozilla::ProfileGatherer;
-#endif
using mozilla::ipc::MessageChannel;
using mozilla::ipc::GeckoChildProcessHost;
-using mozilla::dom::PCrashReporterParent;
-using mozilla::dom::CrashReporterParent;
using namespace mozilla;
using namespace mozilla::plugins;
@@ -529,7 +515,7 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
if (NS_SUCCEEDED(mAsyncInitRv))
#endif
{
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
mAsyncInitRv = NP_Initialize(mNPNIface,
mNPPIface,
&mAsyncInitError);
@@ -546,25 +532,6 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
}
#endif
}
-
-#ifdef MOZ_ENABLE_PROFILER_SPS
- nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
- bool profilerActive = false;
- DebugOnly<nsresult> rv = profiler->IsActive(&profilerActive);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- if (profilerActive) {
- nsCOMPtr<nsIProfilerStartParams> currentProfilerParams;
- rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-
- nsCOMPtr<nsISupports> gatherer;
- rv = profiler->GetProfileGatherer(getter_AddRefs(gatherer));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
-
- StartProfiler(currentProfilerParams);
- }
-#endif
}
bool
@@ -650,10 +617,6 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath,
mSandboxLevel = aSandboxLevel;
mRunID = GeckoChildProcessHost::GetUniqueID();
-#ifdef MOZ_ENABLE_PROFILER_SPS
- InitPluginProfiling();
-#endif
-
mozilla::HangMonitor::RegisterAnnotator(*this);
}
@@ -663,10 +626,6 @@ PluginModuleChromeParent::~PluginModuleChromeParent()
NS_RUNTIMEABORT("unsafe destruction");
}
-#ifdef MOZ_ENABLE_PROFILER_SPS
- ShutdownPluginProfiling();
-#endif
-
#ifdef XP_WIN
// If we registered for audio notifications, stop.
mozilla::plugins::PluginUtilsWin::RegisterForAudioDeviceChanges(this,
@@ -1745,7 +1704,7 @@ PluginModuleChromeParent::CachedSettingChanged(const char* aPref, void* aModule)
module->CachedSettingChanged();
}
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
nsresult
PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error)
{
@@ -2525,33 +2484,6 @@ PluginModuleParent::RecvPluginHideWindow(const uint32_t& aWindowId)
#endif
}
-PCrashReporterParent*
-PluginModuleParent::AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
- uint32_t* processType)
-{
- MOZ_CRASH("unreachable");
-}
-
-bool
-PluginModuleParent::DeallocPCrashReporterParent(PCrashReporterParent* actor)
-{
- MOZ_CRASH("unreachable");
-}
-
-PCrashReporterParent*
-PluginModuleChromeParent::AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
- uint32_t* processType)
-{
- return nullptr;
-}
-
-bool
-PluginModuleChromeParent::DeallocPCrashReporterParent(PCrashReporterParent* actor)
-{
- delete actor;
- return true;
-}
-
bool
PluginModuleParent::RecvSetCursor(const NSCursorInfo& aCursorInfo)
{
@@ -2709,136 +2641,6 @@ PluginModuleParent::AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
return true;
}
-#ifdef MOZ_ENABLE_PROFILER_SPS
-class PluginProfilerObserver final : public nsIObserver,
- public nsSupportsWeakReference
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- explicit PluginProfilerObserver(PluginModuleChromeParent* pmp)
- : mPmp(pmp)
- {}
-
-private:
- ~PluginProfilerObserver() {}
- PluginModuleChromeParent* mPmp;
-};
-
-NS_IMPL_ISUPPORTS(PluginProfilerObserver, nsIObserver, nsISupportsWeakReference)
-
-NS_IMETHODIMP
-PluginProfilerObserver::Observe(nsISupports *aSubject,
- const char *aTopic,
- const char16_t *aData)
-{
- if (!strcmp(aTopic, "profiler-started")) {
- nsCOMPtr<nsIProfilerStartParams> params(do_QueryInterface(aSubject));
- mPmp->StartProfiler(params);
- } else if (!strcmp(aTopic, "profiler-stopped")) {
- mPmp->StopProfiler();
- } else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
- mPmp->GatherAsyncProfile();
- } else if (!strcmp(aTopic, "profiler-subprocess")) {
- nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
- mPmp->GatheredAsyncProfile(pse);
- }
- return NS_OK;
-}
-
-void
-PluginModuleChromeParent::InitPluginProfiling()
-{
- nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
- if (observerService) {
- mProfilerObserver = new PluginProfilerObserver(this);
- observerService->AddObserver(mProfilerObserver, "profiler-started", false);
- observerService->AddObserver(mProfilerObserver, "profiler-stopped", false);
- observerService->AddObserver(mProfilerObserver, "profiler-subprocess-gather", false);
- observerService->AddObserver(mProfilerObserver, "profiler-subprocess", false);
- }
-}
-
-void
-PluginModuleChromeParent::ShutdownPluginProfiling()
-{
- nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
- if (observerService) {
- observerService->RemoveObserver(mProfilerObserver, "profiler-started");
- observerService->RemoveObserver(mProfilerObserver, "profiler-stopped");
- observerService->RemoveObserver(mProfilerObserver, "profiler-subprocess-gather");
- observerService->RemoveObserver(mProfilerObserver, "profiler-subprocess");
- }
-}
-
-void
-PluginModuleChromeParent::StartProfiler(nsIProfilerStartParams* aParams)
-{
- if (NS_WARN_IF(!aParams)) {
- return;
- }
-
- ProfilerInitParams ipcParams;
-
- ipcParams.enabled() = true;
- aParams->GetEntries(&ipcParams.entries());
- aParams->GetInterval(&ipcParams.interval());
- ipcParams.features() = aParams->GetFeatures();
- ipcParams.threadFilters() = aParams->GetThreadFilterNames();
-
- Unused << SendStartProfiler(ipcParams);
-
- nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
- if (NS_WARN_IF(!profiler)) {
- return;
- }
- nsCOMPtr<nsISupports> gatherer;
- profiler->GetProfileGatherer(getter_AddRefs(gatherer));
- mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
-}
-
-void
-PluginModuleChromeParent::StopProfiler()
-{
- mGatherer = nullptr;
- Unused << SendStopProfiler();
-}
-
-void
-PluginModuleChromeParent::GatherAsyncProfile()
-{
- if (NS_WARN_IF(!mGatherer)) {
- return;
- }
- mGatherer->WillGatherOOPProfile();
- Unused << SendGatherProfile();
-}
-
-void
-PluginModuleChromeParent::GatheredAsyncProfile(nsIProfileSaveEvent* aSaveEvent)
-{
- if (aSaveEvent && !mProfile.IsEmpty()) {
- aSaveEvent->AddSubProfile(mProfile.get());
- mProfile.Truncate();
- }
-}
-#endif // MOZ_ENABLE_PROFILER_SPS
-
-bool
-PluginModuleChromeParent::RecvProfile(const nsCString& aProfile)
-{
-#ifdef MOZ_ENABLE_PROFILER_SPS
- if (NS_WARN_IF(!mGatherer)) {
- return true;
- }
-
- mProfile = aProfile;
- mGatherer->GatheredOOPProfile();
-#endif
- return true;
-}
-
bool
PluginModuleParent::AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet)
{
diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h
index 946d4c236..0ceed6efd 100644
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -30,14 +30,6 @@ class nsIProfileSaveEvent;
class nsPluginTag;
namespace mozilla {
-#ifdef MOZ_ENABLE_PROFILER_SPS
-class ProfileGatherer;
-#endif
-namespace dom {
-class PCrashReporterParent;
-class CrashReporterParent;
-} // namespace dom
-
namespace layers {
class TextureClientRecycleAllocator;
} // namespace layers
@@ -76,8 +68,6 @@ class PluginModuleParent
{
protected:
typedef mozilla::PluginLibrary PluginLibrary;
- typedef mozilla::dom::PCrashReporterParent PCrashReporterParent;
- typedef mozilla::dom::CrashReporterParent CrashReporterParent;
PPluginInstanceParent*
AllocPPluginInstanceParent(const nsCString& aMimeType,
@@ -158,12 +148,6 @@ protected:
virtual bool
RecvPluginHideWindow(const uint32_t& aWindowId) override;
- virtual PCrashReporterParent*
- AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
- uint32_t* processType) override;
- virtual bool
- DeallocPCrashReporterParent(PCrashReporterParent* actor) override;
-
virtual bool
RecvSetCursor(const NSCursorInfo& aCursorInfo) override;
@@ -201,8 +185,6 @@ protected:
virtual bool RecvNotifyContentModuleDestroyed() override { return true; }
- virtual bool RecvProfile(const nsCString& aProfile) override { return true; }
-
virtual bool AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
virtual bool RecvReturnClearSiteData(const NPError& aRv,
@@ -267,7 +249,7 @@ protected:
const mozilla::NativeEventData& aNativeKeyData,
bool aIsConsumed) override;
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) override;
#else
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override;
@@ -348,7 +330,6 @@ protected:
bool
GetPluginDetails();
- friend class mozilla::dom::CrashReporterParent;
friend class mozilla::plugins::PluginAsyncSurrogate;
bool mIsStartingAsync;
@@ -480,16 +461,6 @@ class PluginModuleChromeParent
void CachedSettingChanged();
-#ifdef MOZ_ENABLE_PROFILER_SPS
- void GatherAsyncProfile();
- void GatheredAsyncProfile(nsIProfileSaveEvent* aSaveEvent);
- void StartProfiler(nsIProfilerStartParams* aParams);
- void StopProfiler();
-#endif
-
- virtual bool
- RecvProfile(const nsCString& aProfile) override;
-
virtual bool
AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
@@ -508,16 +479,10 @@ private:
virtual bool ShouldContinueFromReplyTimeout() override;
- virtual PCrashReporterParent*
- AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
- uint32_t* processType) override;
- virtual bool
- DeallocPCrashReporterParent(PCrashReporterParent* actor) override;
-
PluginProcessParent* Process() const { return mSubprocess; }
base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) override;
#else
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override;
@@ -534,17 +499,10 @@ private:
int32_t aSandboxLevel,
bool aAllowAsyncInit);
- CrashReporterParent* CrashReporter();
-
void CleanupFromTimeout(const bool aByHangUI);
virtual void UpdatePluginTimeout() override;
-#ifdef MOZ_ENABLE_PROFILER_SPS
- void InitPluginProfiling();
- void ShutdownPluginProfiling();
-#endif
-
void RegisterSettingsCallbacks();
void UnregisterSettingsCallbacks();
@@ -593,7 +551,6 @@ private:
FinishHangUI();
#endif
- friend class mozilla::dom::CrashReporterParent;
friend class mozilla::plugins::PluginAsyncSurrogate;
void OnProcessLaunched(const bool aSucceeded);
@@ -628,9 +585,6 @@ private:
// processes in existence!
dom::ContentParent* mContentParent;
nsCOMPtr<nsIObserver> mPluginOfflineObserver;
-#ifdef MOZ_ENABLE_PROFILER_SPS
- RefPtr<mozilla::ProfileGatherer> mGatherer;
-#endif
nsCString mProfile;
bool mIsBlocklisted;
static bool sInstantiated;
diff --git a/dom/plugins/ipc/PluginProcessChild.cpp b/dom/plugins/ipc/PluginProcessChild.cpp
index eb698e8af..32bf06215 100644
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -22,10 +22,6 @@ extern "C" CGError CGSSetDebugOptions(int options);
#ifdef XP_WIN
bool ShouldProtectPluginCurrentDirectory(char16ptr_t pluginFilePath);
-#if defined(MOZ_SANDBOX)
-#define TARGET_SANDBOX_EXPORTS
-#include "mozilla/sandboxTarget.h"
-#endif
#endif
using mozilla::ipc::IOThreadChild;
@@ -107,12 +103,6 @@ PluginProcessChild::Init()
pluginFilename = WideToUTF8(values[0]);
-#if defined(MOZ_SANDBOX)
- // This is probably the earliest we would want to start the sandbox.
- // As we attempt to tighten the sandbox, we may need to consider moving this
- // to later in the plugin initialization.
- mozilla::SandboxTarget::Instance()->StartSandbox();
-#endif
#else
# error Sorry
#endif
diff --git a/dom/plugins/ipc/PluginProcessParent.cpp b/dom/plugins/ipc/PluginProcessParent.cpp
index 2a73bce51..fb0e18246 100644
--- a/dom/plugins/ipc/PluginProcessParent.cpp
+++ b/dom/plugins/ipc/PluginProcessParent.cpp
@@ -14,10 +14,6 @@
#include "mozilla/Telemetry.h"
#include "nsThreadUtils.h"
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-#include "nsDirectoryServiceDefs.h"
-#endif
-
using std::vector;
using std::string;
@@ -40,95 +36,14 @@ PluginProcessParent::~PluginProcessParent()
{
}
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-static void
-AddSandboxAllowedFile(vector<std::wstring>& aAllowedFiles, nsIProperties* aDirSvc,
- const char* aDir, const nsAString& aSuffix = EmptyString())
-{
- nsCOMPtr<nsIFile> userDir;
- nsresult rv = aDirSvc->Get(aDir, NS_GET_IID(nsIFile), getter_AddRefs(userDir));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- nsAutoString userDirPath;
- rv = userDir->GetPath(userDirPath);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- if (!aSuffix.IsEmpty()) {
- userDirPath.Append(aSuffix);
- }
- aAllowedFiles.push_back(std::wstring(userDirPath.get()));
- return;
-}
-
-static void
-AddSandboxAllowedFiles(int32_t aSandboxLevel,
- vector<std::wstring>& aAllowedFilesRead,
- vector<std::wstring>& aAllowedFilesReadWrite,
- vector<std::wstring>& aAllowedDirectories)
-{
- if (aSandboxLevel < 2) {
- return;
- }
-
- nsresult rv;
- nsCOMPtr<nsIProperties> dirSvc =
- do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- // Higher than level 2 currently removes the users own rights.
- if (aSandboxLevel > 2) {
- AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR);
- AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR,
- NS_LITERAL_STRING("\\*"));
- }
-
- // Level 2 and above is now using low integrity, so we need to give write
- // access to the Flash directories.
- // This should be made Flash specific (Bug 1171396).
- AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR,
- NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*"));
- AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_LOCAL_APPDATA_DIR,
- NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*"));
- AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR,
- NS_LITERAL_STRING("\\Adobe\\Flash Player\\*"));
-
- // Access also has to be given to create the parent directories as they may
- // not exist.
- AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
- NS_LITERAL_STRING("\\Macromedia"));
- AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
- NS_LITERAL_STRING("\\Macromedia\\Flash Player"));
- AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_LOCAL_APPDATA_DIR,
- NS_LITERAL_STRING("\\Macromedia"));
- AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_LOCAL_APPDATA_DIR,
- NS_LITERAL_STRING("\\Macromedia\\Flash Player"));
- AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
- NS_LITERAL_STRING("\\Adobe"));
- AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
- NS_LITERAL_STRING("\\Adobe\\Flash Player"));
-}
-#endif
-
bool
PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask,
int32_t aSandboxLevel)
{
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
- mSandboxLevel = aSandboxLevel;
- AddSandboxAllowedFiles(mSandboxLevel, mAllowedFilesRead,
- mAllowedFilesReadWrite, mAllowedDirectories);
-#else
if (aSandboxLevel != 0) {
MOZ_ASSERT(false,
"Can't enable an NPAPI process sandbox for platform/build.");
}
-#endif
ProcessArchitecture currentArchitecture = base::GetCurrentProcessArchitecture();
uint32_t containerArchitectures = GetSupportedArchitecturesForProcessType(GeckoProcessType_Plugin);
diff --git a/dom/plugins/ipc/moz.build b/dom/plugins/ipc/moz.build
index b569aeb4c..15ed6410d 100644
--- a/dom/plugins/ipc/moz.build
+++ b/dom/plugins/ipc/moz.build
@@ -125,12 +125,6 @@ LOCAL_INCLUDES += [
'/xpcom/base/',
]
-if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
- LOCAL_INCLUDES += [
- '/security/sandbox/chromium',
- '/security/sandbox/chromium-shim',
- ]
-
DEFINES['FORCE_PR_LOG'] = True
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gtk3':
diff --git a/dom/plugins/test/mochitest/test_bug813906.html b/dom/plugins/test/mochitest/test_bug813906.html
index 04c34daaf..d18dbbff2 100644
--- a/dom/plugins/test/mochitest/test_bug813906.html
+++ b/dom/plugins/test/mochitest/test_bug813906.html
@@ -18,21 +18,35 @@ function f() {
</script>
<script type="application/javascript">
+SimpleTest.requestFlakyTimeout(
+ "Blocking an iframe does not cause the onerror event to be fired");
+
SimpleTest.waitForExplicitFinish();
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
var frameLoadCount = 0;
+
+function frameNavBlocked() {
+ isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'),
+ 0, 'plugin shouldnt be able to cause navigation to chrome URLs');
+ SimpleTest.finish();
+}
+
function frameLoaded() {
frameLoadCount++;
if (frameLoadCount == 1) {
document.getElementsByTagName("object")[0].type = "application/x-test";
document.getElementsByTagName("use")[0].setAttributeNS("http://www.w3.org/1999/xlink", "href", location.href + "#a");
- } else if (frameLoadCount == 2) {
- isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'),
- 0, 'plugin shouldnt be able to cause navigation to chrome URLs');
- SimpleTest.finish();
+
+ // wait two seconds and verify that frame navigation did not succeed
+ setTimeout(frameNavBlocked, 2000);
+ return;
}
+ // we should never get here, but just in case, make sure the test fails in that case.
+ ok(false, "onload() event should not fire for blocked navigation");
+ SimpleTest.finish();
}
+
</script>
<!-- Note that <svg:use> ends up creating an anonymous subtree, which means that the plugin
diff --git a/dom/plugins/test/mochitest/test_pluginstream_err.html b/dom/plugins/test/mochitest/test_pluginstream_err.html
index 0ac2a5efc..79f06154c 100644
--- a/dom/plugins/test/mochitest/test_pluginstream_err.html
+++ b/dom/plugins/test/mochitest/test_pluginstream_err.html
@@ -13,7 +13,7 @@ Tests for plugin stream error conditions.
<link rel="stylesheet" type="text/css"
href="/tests/SimpleTest/test.css" />
</head>
-<body onload="runNextTest()">
+<body onload="startTests()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=517078">
Mozilla Bug 517078</a> - Plugin Stream Error Tests
<p id="display"></p>
@@ -158,6 +158,12 @@ function continueTest() {
index++;
}
+function startTests() {
+ SpecialPowers.pushPrefEnv({"set": [
+ ["security.data_uri.block_toplevel_data_uri_navigations", false],
+ ]}, runNextTest);
+}
+
</script>
</div>
</body>
diff --git a/dom/plugins/test/unit/xpcshell.ini b/dom/plugins/test/unit/xpcshell.ini
index 69b6731b2..2665c82b5 100644
--- a/dom/plugins/test/unit/xpcshell.ini
+++ b/dom/plugins/test/unit/xpcshell.ini
@@ -5,7 +5,6 @@ tail =
tags = addons
firefox-appdir = browser
support-files =
- !/toolkit/mozapps/webextensions/test/xpcshell/head_addons.js
[test_allowed_types.js]
skip-if = appname == "thunderbird"
diff --git a/dom/presentation/PresentationSessionInfo.cpp b/dom/presentation/PresentationSessionInfo.cpp
index f93909864..1dd92ab69 100644
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -31,11 +31,6 @@
#include "nsIPresentationNetworkHelper.h"
#endif // MOZ_WIDGET_ANDROID
-#ifdef MOZ_WIDGET_GONK
-#include "nsINetworkInterface.h"
-#include "nsINetworkManager.h"
-#endif
-
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::services;
@@ -647,49 +642,7 @@ PresentationControllingInfo::Shutdown(nsresult aReason)
nsresult
PresentationControllingInfo::GetAddress()
{
-#if defined(MOZ_WIDGET_GONK)
- nsCOMPtr<nsINetworkManager> networkManager =
- do_GetService("@mozilla.org/network/manager;1");
- if (NS_WARN_IF(!networkManager)) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- nsCOMPtr<nsINetworkInfo> activeNetworkInfo;
- networkManager->GetActiveNetworkInfo(getter_AddRefs(activeNetworkInfo));
- if (NS_WARN_IF(!activeNetworkInfo)) {
- return NS_ERROR_FAILURE;
- }
-
- char16_t** ips = nullptr;
- uint32_t* prefixes = nullptr;
- uint32_t count = 0;
- activeNetworkInfo->GetAddresses(&ips, &prefixes, &count);
- if (NS_WARN_IF(!count)) {
- NS_Free(prefixes);
- NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, ips);
- return NS_ERROR_FAILURE;
- }
-
- // TODO bug 1228504 Take all IP addresses in PresentationChannelDescription
- // into account. And at the first stage Presentation API is only exposed on
- // Firefox OS where the first IP appears enough for most scenarios.
-
- nsAutoString ip;
- ip.Assign(ips[0]);
-
- // On Android platform, the IP address is retrieved from a callback function.
- // To make consistent code sequence, following function call is dispatched
- // into main thread instead of calling it directly.
- NS_DispatchToMainThread(
- NewRunnableMethod<nsCString>(
- this,
- &PresentationControllingInfo::OnGetAddress,
- NS_ConvertUTF16toUTF8(ip)));
-
- NS_Free(prefixes);
- NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, ips);
-
-#elif defined(MOZ_WIDGET_ANDROID)
+#if defined(MOZ_WIDGET_ANDROID)
RefPtr<PresentationNetworkHelper> networkHelper =
new PresentationNetworkHelper(this,
&PresentationControllingInfo::OnGetAddress);
diff --git a/dom/presentation/provider/PresentationDeviceProviderModule.cpp b/dom/presentation/provider/PresentationDeviceProviderModule.cpp
index 9100fa49b..9c084e7db 100644
--- a/dom/presentation/provider/PresentationDeviceProviderModule.cpp
+++ b/dom/presentation/provider/PresentationDeviceProviderModule.cpp
@@ -68,12 +68,9 @@ static const mozilla::Module::ContractIDEntry kPresentationDeviceProviderContrac
};
static const mozilla::Module::CategoryEntry kPresentationDeviceProviderCategories[] = {
-#if defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_ANDROID) || (defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 16)
+#if defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_ANDROID)
{ PRESENTATION_DEVICE_PROVIDER_CATEGORY, "MulticastDNSDeviceProvider", MULTICAST_DNS_PROVIDER_CONTRACT_ID },
#endif
-#if defined(MOZ_WIDGET_GONK)
- { PRESENTATION_DEVICE_PROVIDER_CATEGORY, "DisplayDeviceProvider", DISPLAY_DEVICE_PROVIDER_CONTRACT_ID },
-#endif
#ifdef MOZ_WIDGET_ANDROID
{ PRESENTATION_DEVICE_PROVIDER_CATEGORY, "LegacyMDNSDeviceProvider", LEGACY_MDNS_PROVIDER_CONTRACT_ID },
#endif //MOZ_WIDGET_ANDROID
diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp
index 00b78143e..557f3a1f9 100644
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -561,37 +561,40 @@ Promise::Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
// static
already_AddRefed<Promise>
-Promise::All(const GlobalObject& aGlobal,
+Promise::All(JSContext* aCx,
const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv)
{
- nsCOMPtr<nsIGlobalObject> global;
- global = do_QueryInterface(aGlobal.GetAsSupports());
- if (!global) {
+ JS::Rooted<JSObject*> globalObj(aCx, JS::CurrentGlobalOrNull(aCx));
+ if (!globalObj) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
- JSContext* cx = aGlobal.Context();
+ nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(globalObj);
+ if (!global) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
- JS::AutoObjectVector promises(cx);
+ JS::AutoObjectVector promises(aCx);
if (!promises.reserve(aPromiseList.Length())) {
- aRv.NoteJSContextException(cx);
+ aRv.NoteJSContextException(aCx);
return nullptr;
}
for (auto& promise : aPromiseList) {
- JS::Rooted<JSObject*> promiseObj(cx, promise->PromiseObj());
+ JS::Rooted<JSObject*> promiseObj(aCx, promise->PromiseObj());
// Just in case, make sure these are all in the context compartment.
- if (!JS_WrapObject(cx, &promiseObj)) {
- aRv.NoteJSContextException(cx);
+ if (!JS_WrapObject(aCx, &promiseObj)) {
+ aRv.NoteJSContextException(aCx);
return nullptr;
}
promises.infallibleAppend(promiseObj);
}
- JS::Rooted<JSObject*> result(cx, JS::GetWaitForAllPromise(cx, promises));
+ JS::Rooted<JSObject*> result(aCx, JS::GetWaitForAllPromise(aCx, promises));
if (!result) {
- aRv.NoteJSContextException(cx);
+ aRv.NoteJSContextException(aCx);
return nullptr;
}
diff --git a/dom/promise/Promise.h b/dom/promise/Promise.h
index f2ad3bd6c..642603a11 100644
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -188,23 +188,26 @@ public:
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aWrapper);
- // Do the equivalent of Promise.resolve in the current compartment of aCx.
- // Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this
- // function MUST return a non-null value.
+ // Do the equivalent of Promise.resolve in the compartment of aGlobal. The
+ // compartment of aCx is ignored. Errors are reported on the ErrorResult; if
+ // aRv comes back !Failed(), this function MUST return a non-null value.
static already_AddRefed<Promise>
Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
- // Do the equivalent of Promise.reject in the current compartment of aCx.
- // Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this
- // function MUST return a non-null value.
+ // Do the equivalent of Promise.reject in the compartment of aGlobal. The
+ // compartment of aCx is ignored. Errors are reported on the ErrorResult; if
+ // aRv comes back !Failed(), this function MUST return a non-null value.
static already_AddRefed<Promise>
Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
+ // Do the equivalent of Promise.all in the current compartment of aCx. Errors
+ // are reported on the ErrorResult; if aRv comes back !Failed(), this function
+ // MUST return a non-null value.
static already_AddRefed<Promise>
- All(const GlobalObject& aGlobal,
- const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv);
+ All(JSContext* aCx, const nsTArray<RefPtr<Promise>>& aPromiseList,
+ ErrorResult& aRv);
void
Then(JSContext* aCx,
diff --git a/dom/quota/StorageManager.cpp b/dom/quota/StorageManager.cpp
index c8455f0fe..4e9f0cf8c 100644
--- a/dom/quota/StorageManager.cpp
+++ b/dom/quota/StorageManager.cpp
@@ -335,7 +335,7 @@ StorageManager::Estimate(ErrorResult& aRv)
new EstimateWorkerMainThreadRunnable(promiseProxy->GetWorkerPrivate(),
promiseProxy);
- runnnable->Dispatch(aRv);
+ runnnable->Dispatch(Terminating, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
diff --git a/dom/secureelement/SEUtils.jsm b/dom/secureelement/SEUtils.jsm
deleted file mode 100644
index d5980b19c..000000000
--- a/dom/secureelement/SEUtils.jsm
+++ /dev/null
@@ -1,116 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-"use strict";
-
-this.SEUtils = {
- byteArrayToHexString: function byteArrayToHexString(array) {
- let hexStr = "";
-
- let len = array ? array.length : 0;
- for (let i = 0; i < len; i++) {
- let hex = (array[i] & 0xff).toString(16);
- hex = (hex.length === 1) ? "0" + hex : hex;
- hexStr += hex;
- }
-
- return hexStr.toUpperCase();
- },
-
- hexStringToByteArray: function hexStringToByteArray(hexStr) {
- if (typeof hexStr !== "string" || hexStr.length % 2 !== 0) {
- return [];
- }
-
- let array = [];
- for (let i = 0, len = hexStr.length; i < len; i += 2) {
- array.push(parseInt(hexStr.substr(i, 2), 16));
- }
-
- return array;
- },
-
- arraysEqual: function arraysEqual(a1, a2) {
- if (!a1 || !a2) {
- return false;
- }
-
- if (a1.length !== a2.length) {
- return false;
- }
-
- for (let i = 0, len = a1.length; i < len; i++) {
- if (a1[i] !== a2[i]) {
- return false;
- }
- }
-
- return true;
- },
-
- ensureIsArray: function ensureIsArray(obj) {
- return Array.isArray(obj) ? obj : [obj];
- },
-
- /**
- * parseTLV is intended primarily to be used to parse Global Platform Device
- * Technology secure element access control data.
- *
- * The parsed result value is an internal format only.
- *
- * All tags will be treated as simple Tag Length Values (TLV), (i.e. with a
- * plain value, not subject to further unpacking), unless those tags are
- * listed in the containerTags array.
- *
- * @param bytes - byte array
- * @param containerTags - byte array of tags
- */
- parseTLV: function parseTLV(bytes, containerTags) {
- let result = {};
-
- if (typeof bytes === "string") {
- bytes = this.hexStringToByteArray(bytes);
- }
-
- if (!Array.isArray(bytes)) {
- debug("Passed value is not an array nor a string.");
- return null;
- }
-
- for (let pos = 0; pos < bytes.length; ) {
- let tag = bytes[pos],
- length = bytes[pos + 1],
- value = bytes.slice(pos + 2, pos + 2 + length),
- parsed = null;
-
- // Support for 0xFF padded files (GPD 7.1.2)
- if (tag === 0xFF) {
- break;
- }
-
- if (containerTags.indexOf(tag) >= 0) {
- parsed = this.parseTLV(value, containerTags);
- } else {
- parsed = value;
- }
-
- // Internal parsed format.
- if (!result[tag]) {
- result[tag] = parsed;
- } else if (Array.isArray(result[tag])) {
- result[tag].push(parsed);
- } else {
- result[tag] = [result[tag], parsed];
- }
-
- pos = pos + 2 + length;
- }
-
- return result;
- }
-};
-
-this.EXPORTED_SYMBOLS = ["SEUtils"];
diff --git a/dom/secureelement/gonk/ACEService.js b/dom/secureelement/gonk/ACEService.js
deleted file mode 100644
index b52ba5fab..000000000
--- a/dom/secureelement/gonk/ACEService.js
+++ /dev/null
@@ -1,139 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-"use strict";
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
- "resource://gre/modules/SEUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "SE", function() {
- let obj = {};
- Cu.import("resource://gre/modules/se_consts.js", obj);
- return obj;
-});
-
-var DEBUG = SE.DEBUG_ACE;
-function debug(msg) {
- if (DEBUG) {
- dump("ACEservice: " + msg + "\n");
- }
-}
-
-/**
- * Implements decision making algorithm as described in GPD specification,
- * mostly in 3.1, 3.2 and 4.2.3.
- *
- * TODO: Bug 1137533: Implement GPAccessRulesManager APDU filters
- */
-function GPAccessDecision(rules, certHash, aid) {
- this.rules = rules;
- this.certHash = certHash;
- this.aid = aid;
-}
-
-GPAccessDecision.prototype = {
- isAccessAllowed: function isAccessAllowed() {
- // GPD SE Access Control v1.1, 3.4.1, Table 3-2: (Conflict resolution)
- // If a specific rule allows, all other non-specific access is denied.
- // Conflicting specific rules will resolve to the first Allowed == "true"
- // match. Given no specific rule, the global "All" rules will determine
- // access. "Some", skips further processing if access Allowed == "true".
- //
- // Access must be decided before the SE connector openChannel, and the
- // exchangeAPDU call.
- //
- // NOTE: This implementation may change with the introduction of APDU
- // filters.
- let decision = this.rules.some(this._decideAppAccess.bind(this));
- return decision;
- },
-
- _decideAppAccess: function _decideAppAccess(rule) {
- let appMatched, appletMatched;
-
- // GPD SE AC 4.2.3: Algorithm for Applying Rules
- // Specific rule overrides global rule.
- //
- // DeviceAppID is the application hash, and the AID is SE Applet ID:
- //
- // GPD SE AC 4.2.3 A:
- // SearchRuleFor(DeviceAppID, AID)
- // GPD SE AC 4.2.3 B: If no rule fits A:
- // SearchRuleFor(<AllDeviceApplications>, AID)
- // GPD SE AC 4.2.3 C: If no rule fits A or B:
- // SearchRuleFor(DeviceAppID, <AllSEApplications>)
- // GPD SE AC 4.2.3 D: If no rule fits A, B, or C:
- // SearchRuleFor(<AllDeviceApplications>, <AllSEApplications>)
-
- // Device App
- appMatched = Array.isArray(rule.application) ?
- // GPD SE AC 4.2.3 A and 4.2.3 C (DeviceAppID rule)
- this._appCertHashMatches(rule.application) :
- // GPD SE AC 4.2.3 B and 4.2.3 D (All Device Applications)
- rule.application === Ci.nsIAccessRulesManager.ALLOW_ALL;
-
- if (!appMatched) {
- return false; // bail out early.
- }
-
- // SE Applet
- appletMatched = Array.isArray(rule.applet) ?
- // GPD SE AC 4.2.3 A and 4.2.3 B (AID rule)
- SEUtils.arraysEqual(rule.applet, this.aid) :
- // GPD SE AC 4.2.3 C and 4.2.3 D (All AID)
- rule.applet === Ci.nsIAccessRulesManager.ALL_APPLET;
-
- return appletMatched;
- },
-
- _appCertHashMatches: function _appCertHashMatches(hashArray) {
- if (!Array.isArray(hashArray)) {
- return false;
- }
-
- return !!(hashArray.find((hash) => {
- return SEUtils.arraysEqual(hash, this.certHash);
- }));
- }
-};
-
-function ACEService() {
- this._rulesManagers = new Map();
-
- this._rulesManagers.set(
- SE.TYPE_UICC,
- Cc["@mozilla.org/secureelement/access-control/rules-manager;1"]
- .createInstance(Ci.nsIAccessRulesManager));
-}
-
-ACEService.prototype = {
- _rulesManagers: null,
-
- isAccessAllowed: function isAccessAllowed(localId, seType, aid) {
- if(!Services.prefs.getBoolPref("devtools.debugger.forbid-certified-apps")) {
- debug("Certified apps debug enabled, allowing access");
- return Promise.resolve(true);
- }
-
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- _getDevCertHashForApp: function getDevCertHashForApp(manifestURL) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- classID: Components.ID("{882a7463-2ca7-4d61-a89a-10eb6fd70478}"),
- contractID: "@mozilla.org/secureelement/access-control/ace;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessControlEnforcer])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ACEService]);
-
diff --git a/dom/secureelement/gonk/ACEService.manifest b/dom/secureelement/gonk/ACEService.manifest
deleted file mode 100644
index 40949c83d..000000000
--- a/dom/secureelement/gonk/ACEService.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {882a7463-2ca7-4d61-a89a-10eb6fd70478} ACEService.js
-contract @mozilla.org/secureelement/access-control/ace;1 {882a7463-2ca7-4d61-a89a-10eb6fd70478} \ No newline at end of file
diff --git a/dom/secureelement/gonk/GPAccessRulesManager.js b/dom/secureelement/gonk/GPAccessRulesManager.js
deleted file mode 100644
index dce11ec09..000000000
--- a/dom/secureelement/gonk/GPAccessRulesManager.js
+++ /dev/null
@@ -1,436 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-"use strict";
-
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyServiceGetter(this, "UiccConnector",
- "@mozilla.org/secureelement/connector/uicc;1",
- "nsISecureElementConnector");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
- "resource://gre/modules/SEUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "SE", function() {
- let obj = {};
- Cu.import("resource://gre/modules/se_consts.js", obj);
- return obj;
-});
-
-XPCOMUtils.defineLazyGetter(this, "GP", function() {
- let obj = {};
- Cu.import("resource://gre/modules/gp_consts.js", obj);
- return obj;
-});
-
-var DEBUG = SE.DEBUG_ACE;
-function debug(msg) {
- if (DEBUG) {
- dump("-*- GPAccessRulesManager " + msg);
- }
-}
-
-/**
- * Based on [1] - "GlobalPlatform Device Technology
- * Secure Element Access Control Version 1.0".
- * GPAccessRulesManager reads and parses access rules from SE file system
- * as defined in section #7 of [1]: "Structure of Access Rule Files (ARF)".
- * Rules retrieval from ARA-M applet is not implmented due to lack of
- * commercial implemenations of ARA-M.
- * @todo Bug 1137537: Implement ARA-M support according to section #4 of [1]
- */
-function GPAccessRulesManager() {}
-
-GPAccessRulesManager.prototype = {
- // source [1] section 7.1.3 PKCS#15 Selection
- PKCS_AID: "a000000063504b43532d3135",
-
- // APDUs (ISO 7816-4) for accessing rules on SE file system
- // see for more details: http://www.cardwerk.com/smartcards/
- // smartcard_standard_ISO7816-4_6_basic_interindustry_commands.aspx
- READ_BINARY: [GP.CLA_SM, GP.INS_RB, GP.P1_RB, GP.P2_RB],
- GET_RESPONSE: [GP.CLA_SM, GP.INS_GR, GP.P1_GR, GP.P2_GR],
- SELECT_BY_DF: [GP.CLA_SM, GP.INS_SF, GP.P1_SF_DF, GP.P2_SF_FCP],
-
- // Non-null if there is a channel open
- channel: null,
-
- // Refresh tag path in the acMain file as described in GPD spec,
- // sections 7.1.5 and C.1.
- REFRESH_TAG_PATH: [GP.TAG_SEQUENCE, GP.TAG_OCTETSTRING],
- refreshTag: null,
-
- // Contains rules as read from the SE
- rules: [],
-
- // Returns the latest rules. Results are cached.
- getAccessRules: function getAccessRules() {
- debug("getAccessRules");
-
- return new Promise((resolve, reject) => {
- this._readAccessRules(() => resolve(this.rules));
- });
- },
-
- _readAccessRules: Task.async(function*(done) {
- try {
- yield this._openChannel(this.PKCS_AID);
-
- let odf = yield this._readODF();
- let dodf = yield this._readDODF(odf);
-
- let acmf = yield this._readACMF(dodf);
- let refreshTag = acmf[this.REFRESH_TAG_PATH[0]]
- [this.REFRESH_TAG_PATH[1]];
-
- // Update cached rules based on refreshTag.
- if (SEUtils.arraysEqual(this.refreshTag, refreshTag)) {
- debug("_readAccessRules: refresh tag equals to the one saved.");
- yield this._closeChannel();
- return done();
- }
-
- this.refreshTag = refreshTag;
- debug("_readAccessRules: refresh tag saved: " + this.refreshTag);
-
- let acrf = yield this._readACRules(acmf);
- let accf = yield this._readACConditions(acrf);
- this.rules = yield this._parseRules(acrf, accf);
-
- DEBUG && debug("_readAccessRules: " + JSON.stringify(this.rules, 0, 2));
-
- yield this._closeChannel();
- done();
- } catch (error) {
- debug("_readAccessRules: " + error);
- this.rules = [];
- yield this._closeChannel();
- done();
- }
- }),
-
- _openChannel: function _openChannel(aid) {
- if (this.channel !== null) {
- debug("_openChannel: Channel already opened, rejecting.");
- return Promise.reject();
- }
-
- return new Promise((resolve, reject) => {
- UiccConnector.openChannel(aid, {
- notifyOpenChannelSuccess: (channel, openResponse) => {
- debug("_openChannel/notifyOpenChannelSuccess: Channel " + channel +
- " opened, open response: " + openResponse);
- this.channel = channel;
- resolve();
- },
- notifyError: (error) => {
- debug("_openChannel/notifyError: failed to open channel, error: " +
- error);
- reject(error);
- }
- });
- });
- },
-
- _closeChannel: function _closeChannel() {
- if (this.channel === null) {
- debug("_closeChannel: Channel not opened, rejecting.");
- return Promise.reject();
- }
-
- return new Promise((resolve, reject) => {
- UiccConnector.closeChannel(this.channel, {
- notifyCloseChannelSuccess: () => {
- debug("_closeChannel/notifyCloseChannelSuccess: chanel " +
- this.channel + " closed");
- this.channel = null;
- resolve();
- },
- notifyError: (error) => {
- debug("_closeChannel/notifyError: error closing channel, error" +
- error);
- reject(error);
- }
- });
- });
- },
-
- _exchangeAPDU: function _exchangeAPDU(bytes) {
- DEBUG && debug("apdu " + JSON.stringify(bytes));
-
- let apdu = this._bytesToAPDU(bytes);
- return new Promise((resolve, reject) => {
- UiccConnector.exchangeAPDU(this.channel, apdu.cla,
- apdu.ins, apdu.p1, apdu.p2, apdu.data, apdu.le,
- {
- notifyExchangeAPDUResponse: (sw1, sw2, data) => {
- debug("APDU response is " + sw1.toString(16) + sw2.toString(16) +
- " data: " + data);
-
- // 90 00 is "success"
- if (sw1 !== 0x90 && sw2 !== 0x00) {
- debug("rejecting APDU response");
- reject(new Error("Response " + sw1 + "," + sw2));
- return;
- }
-
- resolve(this._parseTLV(data));
- },
-
- notifyError: (error) => {
- debug("_exchangeAPDU/notifyError " + error);
- reject(error);
- }
- }
- );
- });
- },
-
- _readBinaryFile: function _readBinaryFile(selectResponse) {
- DEBUG && debug("Select response: " + JSON.stringify(selectResponse));
- // 0x80 tag parameter - get the elementary file (EF) length
- // without structural information.
- let fileLength = selectResponse[GP.TAG_FCP][0x80];
-
- // If file is empty, no need to attempt to read it.
- if (fileLength[0] === 0 && fileLength[1] === 0) {
- return Promise.resolve(null);
- }
-
- // TODO READ BINARY with filelength not supported
- // let readApdu = this.READ_BINARY.concat(fileLength);
- return this._exchangeAPDU(this.READ_BINARY);
- },
-
- _selectAndRead: function _selectAndRead(df) {
- return this._exchangeAPDU(this.SELECT_BY_DF.concat(df.length & 0xFF, df))
- .then((resp) => this._readBinaryFile(resp));
- },
-
- _readODF: function _readODF() {
- debug("_readODF");
- return this._selectAndRead(GP.ODF_DF);
- },
-
- _readDODF: function _readDODF(odfFile) {
- debug("_readDODF, ODF file: " + odfFile);
-
- // Data Object Directory File (DODF) is used as an entry point to the
- // Access Control data. It is specified in PKCS#15 section 6.7.6.
- // DODF is referenced by the ODF file, which looks as follows:
- // A7 06
- // 30 04
- // 04 02 XY WZ
- // where [0xXY, 0xWZ] is a DF of DODF file.
- let DODF_DF = odfFile[GP.TAG_EF_ODF][GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
- return this._selectAndRead(DODF_DF);
- },
-
- _readACMF: function _readACMF(dodfFile) {
- debug("_readACMF, DODF file: " + dodfFile);
-
- // ACMF file DF is referenced in DODF file, which looks like this:
- //
- // A1 29
- // 30 00
- // 30 0F
- // 0C 0D 47 50 20 53 45 20 41 63 63 20 43 74 6C
- // A1 14
- // 30 12
- // 06 0A 2A 86 48 86 FC 6B 81 48 01 01 <-- GPD registered OID
- // 30 04
- // 04 02 AB CD <-- ACMF DF
- // A1 2B
- // 30 00
- // 30 0F
- // 0C 0D 53 41 54 53 41 20 47 54 4F 20 31 2E 31
- // A1 16
- // 30 14
- // 06 0C 2B 06 01 04 01 2A 02 6E 03 01 01 01 <-- some other OID
- // 30 04
- // 04 02 XY WZ <-- some other file's DF
- //
- // DODF file consists of DataTypes with oidDO entries. Entry with OID
- // equal to "1.2.840.114283.200.1.1" ("2A 86 48 86 FC 6B 81 48 01 01")
- // contains DF of the ACMF. In the file above, it means that ACMF DF
- // equals to [0xAB, 0xCD], and not [0xXY, 0xWZ].
- //
- // Algorithm used to encode OID to an byte array:
- // http://www.snmpsharpnet.com/?p=153
-
- let gpdOid = [0x2A, // 1.2
- 0x86, 0x48, // 840
- 0x86, 0xFC, 0x6B, // 114283
- 0x81, 0x48, // 129
- 0x01, // 1
- 0x01]; // 1
-
- let records = SEUtils.ensureIsArray(dodfFile[GP.TAG_EXTERNALDO]);
-
- // Look for the OID registered for GPD SE.
- let gpdRecords = records.filter((record) => {
- let oid = record[GP.TAG_EXTERNALDO][GP.TAG_SEQUENCE][GP.TAG_OID];
- return SEUtils.arraysEqual(oid, gpdOid);
- });
-
- // [1] 7.1.5: "There shall be only one ACMF file per Secure Element.
- // If a Secure Element contains several ACMF files, then the security shall
- // be considered compromised and the Access Control enforcer shall forbid
- // access to all (...) apps."
- if (gpdRecords.length !== 1) {
- return Promise.reject(new Error(gpdRecords.length + " ACMF files found"));
- }
-
- let ACMain_DF = gpdRecords[0][GP.TAG_EXTERNALDO][GP.TAG_SEQUENCE]
- [GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
- return this._selectAndRead(ACMain_DF);
- },
-
- _readACRules: function _readACRules(acMainFile) {
- debug("_readACRules, ACMain file: " + acMainFile);
-
- // ACMF looks like this:
- //
- // 30 10
- // 04 08 XX XX XX XX XX XX XX XX
- // 30 04
- // 04 02 XY WZ
- //
- // where [XY, WZ] is a DF of ACRF, and XX XX XX XX XX XX XX XX is a refresh
- // tag.
-
- let ACRules_DF = acMainFile[GP.TAG_SEQUENCE][GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
- return this._selectAndRead(ACRules_DF);
- },
-
- _readACConditions: function _readACConditions(acRulesFile) {
- debug("_readACCondition, ACRules file: " + acRulesFile);
-
- let acRules = SEUtils.ensureIsArray(acRulesFile[GP.TAG_SEQUENCE]);
- if (acRules.length === 0) {
- debug("No rules found in ACRules file.");
- return Promise.reject(new Error("No rules found in ACRules file"));
- }
-
- // We first read all the condition files referenced in the ACRules file,
- // because ACRules file might reference one ACCondition file more than
- // once. Since reading it isn't exactly fast, we optimize here.
- let acReadQueue = Promise.resolve({});
-
- acRules.forEach((ruleEntry) => {
- let df = ruleEntry[GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
-
- // Promise chain read condition entries:
- let readAcCondition = (acConditionFiles) => {
- if (acConditionFiles[df] !== undefined) {
- debug("Skipping previously read acCondition df: " + df);
- return acConditionFiles;
- }
-
- return this._selectAndRead(df)
- .then((acConditionFileContents) => {
- acConditionFiles[df] = acConditionFileContents;
- return acConditionFiles;
- });
- }
-
- acReadQueue = acReadQueue.then(readAcCondition);
- });
-
- return acReadQueue;
- },
-
- _parseRules: function _parseRules(acRulesFile, acConditionFiles) {
- DEBUG && debug("_parseRules: acConditionFiles " + JSON.stringify(acConditionFiles));
- let rules = [];
-
- let acRules = SEUtils.ensureIsArray(acRulesFile[GP.TAG_SEQUENCE]);
- acRules.forEach((ruleEntry) => {
- DEBUG && debug("Parsing one rule: " + JSON.stringify(ruleEntry));
- let rule = {};
-
- // 0xA0 and 0x82 tags as per GPD spec sections C.1 - C.3. 0xA0 means
- // that rule describes access to one SE applet only (and its AID is
- // given). 0x82 means that rule describes acccess to all SE applets.
- let oneApplet = ruleEntry[GP.TAG_GPD_AID];
- let allApplets = ruleEntry[GP.TAG_GPD_ALL];
-
- if (oneApplet) {
- rule.applet = oneApplet[GP.TAG_OCTETSTRING];
- } else if (allApplets) {
- rule.applet = Ci.nsIAccessRulesManager.ALL_APPLET;
- } else {
- throw Error("Unknown applet definition");
- }
-
- let df = ruleEntry[GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
- let condition = acConditionFiles[df];
- if (condition === null) {
- rule.application = Ci.nsIAccessRulesManager.DENY_ALL;
- } else if (condition[GP.TAG_SEQUENCE]) {
- if (!Array.isArray(condition[GP.TAG_SEQUENCE]) &&
- !condition[GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING]) {
- rule.application = Ci.nsIAccessRulesManager.ALLOW_ALL;
- } else {
- rule.application = SEUtils.ensureIsArray(condition[GP.TAG_SEQUENCE])
- .map((conditionEntry) => {
- return conditionEntry[GP.TAG_OCTETSTRING];
- });
- }
- } else {
- throw Error("Unknown application definition");
- }
-
- DEBUG && debug("Rule parsed, adding to the list: " + JSON.stringify(rule));
- rules.push(rule);
- });
-
- DEBUG && debug("All rules parsed, we have those in total: " + JSON.stringify(rules));
- return rules;
- },
-
- _parseTLV: function _parseTLV(bytes) {
- let containerTags = [
- GP.TAG_SEQUENCE,
- GP.TAG_FCP,
- GP.TAG_GPD_AID,
- GP.TAG_EXTERNALDO,
- GP.TAG_INDIRECT,
- GP.TAG_EF_ODF
- ];
- return SEUtils.parseTLV(bytes, containerTags);
- },
-
- // TODO consider removing if better format for storing
- // APDU consts will be introduced
- _bytesToAPDU: function _bytesToAPDU(arr) {
- let apdu = {
- cla: arr[0] & 0xFF,
- ins: arr[1] & 0xFF,
- p1: arr[2] & 0xFF,
- p2: arr[3] & 0xFF,
- p3: arr[4] & 0xFF,
- le: 0
- };
-
- let data = (apdu.p3 > 0) ? (arr.slice(5)) : [];
- apdu.data = (data.length) ? SEUtils.byteArrayToHexString(data) : null;
- return apdu;
- },
-
- classID: Components.ID("{3e046b4b-9e66-439a-97e0-98a69f39f55f}"),
- contractID: "@mozilla.org/secureelement/access-control/rules-manager;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessRulesManager])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GPAccessRulesManager]);
diff --git a/dom/secureelement/gonk/GPAccessRulesManager.manifest b/dom/secureelement/gonk/GPAccessRulesManager.manifest
deleted file mode 100644
index 2d7ea038b..000000000
--- a/dom/secureelement/gonk/GPAccessRulesManager.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {3e046b4b-9e66-439a-97e0-98a69f39f55f} GPAccessRulesManager.js
-contract @mozilla.org/secureelement/access-control/rules-manager;1 {3e046b4b-9e66-439a-97e0-98a69f39f55f}
diff --git a/dom/secureelement/gonk/SecureElement.js b/dom/secureelement/gonk/SecureElement.js
deleted file mode 100644
index 144c6d8d6..000000000
--- a/dom/secureelement/gonk/SecureElement.js
+++ /dev/null
@@ -1,514 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Copyright © 2014, Deutsche Telekom, Inc. */
-
-"use strict";
-
-/* globals dump, Components, XPCOMUtils, SE, Services, UiccConnector,
- SEUtils, ppmm, gMap, UUIDGenerator */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyGetter(this, "SE", () => {
- let obj = {};
- Cu.import("resource://gre/modules/se_consts.js", obj);
- return obj;
-});
-
-// set to true in se_consts.js to see debug messages
-var DEBUG = SE.DEBUG_SE;
-function debug(s) {
- if (DEBUG) {
- dump("-*- SecureElement: " + s + "\n");
- }
-}
-
-const SE_IPC_SECUREELEMENT_MSG_NAMES = [
- "SE:GetSEReaders",
- "SE:OpenChannel",
- "SE:CloseChannel",
- "SE:TransmitAPDU"
-];
-
-const SECUREELEMENTMANAGER_CONTRACTID =
- "@mozilla.org/secureelement/parent-manager;1";
-const SECUREELEMENTMANAGER_CID =
- Components.ID("{48f4e650-28d2-11e4-8c21-0800200c9a66}");
-const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageBroadcaster");
-
-XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
- "resource://gre/modules/SEUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "UiccConnector", () => {
- let uiccClass = Cc["@mozilla.org/secureelement/connector/uicc;1"];
- return uiccClass ? uiccClass.getService(Ci.nsISecureElementConnector) : null;
-});
-
-function getConnector(type) {
- switch (type) {
- case SE.TYPE_UICC:
- return UiccConnector;
- case SE.TYPE_ESE:
- default:
- debug("Unsupported SEConnector : " + type);
- return null;
- }
-}
-
-/**
- * 'gMap' is a nested dictionary object that manages all the information
- * pertaining to channels for a given application (appId). It manages the
- * relationship between given application and its opened channels.
- */
-XPCOMUtils.defineLazyGetter(this, "gMap", function() {
- return {
- // example structure of AppInfoMap
- // {
- // "appId1": {
- // target: target1,
- // channels: {
- // "channelToken1": {
- // seType: "uicc",
- // aid: "aid1",
- // channelNumber: 1
- // },
- // "channelToken2": { ... }
- // }
- // },
- // "appId2": { ... }
- // }
- appInfoMap: {},
-
- registerSecureElementTarget: function(appId, target) {
- if (this.isAppIdRegistered(appId)) {
- debug("AppId: " + appId + "already registered");
- return;
- }
-
- this.appInfoMap[appId] = {
- target: target,
- channels: {}
- };
-
- debug("Registered a new SE target " + appId);
- },
-
- unregisterSecureElementTarget: function(target) {
- let appId = Object.keys(this.appInfoMap).find((id) => {
- return this.appInfoMap[id].target === target;
- });
-
- if (!appId) {
- return;
- }
-
- debug("Unregistered SE Target for AppId: " + appId);
- delete this.appInfoMap[appId];
- },
-
- isAppIdRegistered: function(appId) {
- return this.appInfoMap[appId] !== undefined;
- },
-
- getChannelCountByAppIdType: function(appId, type) {
- return Object.keys(this.appInfoMap[appId].channels)
- .reduce((cnt, ch) => ch.type === type ? ++cnt : cnt, 0);
- },
-
- // Add channel to the appId. Upon successfully adding the entry
- // this function will return the 'token'
- addChannel: function(appId, type, aid, channelNumber) {
- let token = UUIDGenerator.generateUUID().toString();
- this.appInfoMap[appId].channels[token] = {
- seType: type,
- aid: aid,
- channelNumber: channelNumber
- };
- return token;
- },
-
- removeChannel: function(appId, channelToken) {
- if (this.appInfoMap[appId].channels[channelToken]) {
- debug("Deleting channel with token : " + channelToken);
- delete this.appInfoMap[appId].channels[channelToken];
- }
- },
-
- getChannel: function(appId, channelToken) {
- if (!this.appInfoMap[appId].channels[channelToken]) {
- return null;
- }
-
- return this.appInfoMap[appId].channels[channelToken];
- },
-
- getChannelsByTarget: function(target) {
- let appId = Object.keys(this.appInfoMap).find((id) => {
- return this.appInfoMap[id].target === target;
- });
-
- if (!appId) {
- return [];
- }
-
- return Object.keys(this.appInfoMap[appId].channels)
- .map(token => this.appInfoMap[appId].channels[token]);
- },
-
- getTargets: function() {
- return Object.keys(this.appInfoMap)
- .map(appId => this.appInfoMap[appId].target);
- },
- };
-});
-
-/**
- * 'SecureElementManager' is the main object that handles IPC messages from
- * child process. It interacts with other objects such as 'gMap' & 'Connector
- * instances (UiccConnector, eSEConnector)' to perform various
- * SE-related (open, close, transmit) operations.
- * @TODO: Bug 1118097 Support slot based SE/reader names
- * @TODO: Bug 1118101 Introduce SE type specific permissions
- */
-function SecureElementManager() {
- this._registerMessageListeners();
- this._registerSEListeners();
- Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
- this._acEnforcer =
- Cc["@mozilla.org/secureelement/access-control/ace;1"]
- .getService(Ci.nsIAccessControlEnforcer);
-}
-
-SecureElementManager.prototype = {
- QueryInterface: XPCOMUtils.generateQI([
- Ci.nsIMessageListener,
- Ci.nsISEListener,
- Ci.nsIObserver]),
- classID: SECUREELEMENTMANAGER_CID,
- classInfo: XPCOMUtils.generateCI({
- classID: SECUREELEMENTMANAGER_CID,
- classDescription: "SecureElementManager",
- interfaces: [Ci.nsIMessageListener,
- Ci.nsISEListener,
- Ci.nsIObserver]
- }),
-
- // Stores information about supported SE types and their presence.
- // key: secure element type, value: (Boolean) is present/accessible
- _sePresence: {},
-
- _acEnforcer: null,
-
- _shutdown: function() {
- this._acEnforcer = null;
- this.secureelement = null;
- Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
- this._unregisterMessageListeners();
- this._unregisterSEListeners();
- },
-
- _registerMessageListeners: function() {
- ppmm.addMessageListener("child-process-shutdown", this);
- for (let msgname of SE_IPC_SECUREELEMENT_MSG_NAMES) {
- ppmm.addMessageListener(msgname, this);
- }
- },
-
- _unregisterMessageListeners: function() {
- ppmm.removeMessageListener("child-process-shutdown", this);
- for (let msgname of SE_IPC_SECUREELEMENT_MSG_NAMES) {
- ppmm.removeMessageListener(msgname, this);
- }
- ppmm = null;
- },
-
- _registerSEListeners: function() {
- let connector = getConnector(SE.TYPE_UICC);
- if (!connector) {
- return;
- }
-
- this._sePresence[SE.TYPE_UICC] = false;
- connector.registerListener(this);
- },
-
- _unregisterSEListeners: function() {
- Object.keys(this._sePresence).forEach((type) => {
- let connector = getConnector(type);
- if (connector) {
- connector.unregisterListener(this);
- }
- });
-
- this._sePresence = {};
- },
-
- notifySEPresenceChanged: function(type, isPresent) {
- // we need to notify all targets, even those without open channels,
- // app could've stored the reader without actually using it
- debug("notifying DOM about SE state change");
- this._sePresence[type] = isPresent;
- gMap.getTargets().forEach(target => {
- let result = { type: type, isPresent: isPresent };
- target.sendAsyncMessage("SE:ReaderPresenceChanged", { result: result });
- });
- },
-
- _canOpenChannel: function(appId, type) {
- let opened = gMap.getChannelCountByAppIdType(appId, type);
- let limit = SE.MAX_CHANNELS_ALLOWED_PER_SESSION;
- // UICC basic channel is not accessible see comment in se_consts.js
- limit = type === SE.TYPE_UICC ? limit - 1 : limit;
- return opened < limit;
- },
-
- _handleOpenChannel: function(msg, callback) {
- if (!this._canOpenChannel(msg.appId, msg.type)) {
- debug("Max channels per session exceed");
- callback({ error: SE.ERROR_GENERIC });
- return;
- }
-
- let connector = getConnector(msg.type);
- if (!connector) {
- debug("No SE connector available");
- callback({ error: SE.ERROR_NOTPRESENT });
- return;
- }
-
- this._acEnforcer.isAccessAllowed(msg.appId, msg.type, msg.aid)
- .then((allowed) => {
- if (!allowed) {
- callback({ error: SE.ERROR_SECURITY });
- return;
- }
- connector.openChannel(SEUtils.byteArrayToHexString(msg.aid), {
-
- notifyOpenChannelSuccess: (channelNumber, openResponse) => {
- // Add the new 'channel' to the map upon success
- let channelToken =
- gMap.addChannel(msg.appId, msg.type, msg.aid, channelNumber);
- if (channelToken) {
- callback({
- error: SE.ERROR_NONE,
- channelToken: channelToken,
- isBasicChannel: (channelNumber === SE.BASIC_CHANNEL),
- openResponse: SEUtils.hexStringToByteArray(openResponse)
- });
- } else {
- callback({ error: SE.ERROR_GENERIC });
- }
- },
-
- notifyError: (reason) => {
- debug("Failed to open the channel to AID : " +
- SEUtils.byteArrayToHexString(msg.aid) +
- ", Rejected with Reason : " + reason);
- callback({ error: SE.ERROR_GENERIC, reason: reason, response: [] });
- }
- });
- })
- .catch((error) => {
- debug("Failed to get info from accessControlEnforcer " + error);
- callback({ error: SE.ERROR_SECURITY });
- });
- },
-
- _handleTransmit: function(msg, callback) {
- let channel = gMap.getChannel(msg.appId, msg.channelToken);
- if (!channel) {
- debug("Invalid token:" + msg.channelToken + ", appId: " + msg.appId);
- callback({ error: SE.ERROR_GENERIC });
- return;
- }
-
- let connector = getConnector(channel.seType);
- if (!connector) {
- debug("No SE connector available");
- callback({ error: SE.ERROR_NOTPRESENT });
- return;
- }
-
- // Bug 1137533 - ACE GPAccessRulesManager APDU filters
- connector.exchangeAPDU(channel.channelNumber, msg.apdu.cla, msg.apdu.ins,
- msg.apdu.p1, msg.apdu.p2,
- SEUtils.byteArrayToHexString(msg.apdu.data),
- msg.apdu.le, {
- notifyExchangeAPDUResponse: (sw1, sw2, response) => {
- callback({
- error: SE.ERROR_NONE,
- sw1: sw1,
- sw2: sw2,
- response: SEUtils.hexStringToByteArray(response)
- });
- },
-
- notifyError: (reason) => {
- debug("Transmit failed, rejected with Reason : " + reason);
- callback({ error: SE.ERROR_INVALIDAPPLICATION, reason: reason });
- }
- });
- },
-
- _handleCloseChannel: function(msg, callback) {
- let channel = gMap.getChannel(msg.appId, msg.channelToken);
- if (!channel) {
- debug("Invalid token:" + msg.channelToken + ", appId:" + msg.appId);
- callback({ error: SE.ERROR_GENERIC });
- return;
- }
-
- let connector = getConnector(channel.seType);
- if (!connector) {
- debug("No SE connector available");
- callback({ error: SE.ERROR_NOTPRESENT });
- return;
- }
-
- connector.closeChannel(channel.channelNumber, {
- notifyCloseChannelSuccess: () => {
- gMap.removeChannel(msg.appId, msg.channelToken);
- callback({ error: SE.ERROR_NONE });
- },
-
- notifyError: (reason) => {
- debug("Failed to close channel with token: " + msg.channelToken +
- ", reason: "+ reason);
- callback({ error: SE.ERROR_BADSTATE, reason: reason });
- }
- });
- },
-
- _handleGetSEReadersRequest: function(msg, target, callback) {
- gMap.registerSecureElementTarget(msg.appId, target);
- let readers = Object.keys(this._sePresence).map(type => {
- return { type: type, isPresent: this._sePresence[type] };
- });
- callback({ readers: readers, error: SE.ERROR_NONE });
- },
-
- _handleChildProcessShutdown: function(target) {
- let channels = gMap.getChannelsByTarget(target);
-
- let createCb = (seType, channelNumber) => {
- return {
- notifyCloseChannelSuccess: () => {
- debug("closed " + seType + ", channel " + channelNumber);
- },
-
- notifyError: (reason) => {
- debug("Failed to close " + seType + " channel " +
- channelNumber + ", reason: " + reason);
- }
- };
- };
-
- channels.forEach((channel) => {
- let connector = getConnector(channel.seType);
- if (!connector) {
- return;
- }
-
- connector.closeChannel(channel.channelNumber,
- createCb(channel.seType, channel.channelNumber));
- });
-
- gMap.unregisterSecureElementTarget(target);
- },
-
- _sendSEResponse: function(msg, result) {
- let promiseStatus = (result.error === SE.ERROR_NONE) ? "Resolved" : "Rejected";
- result.resolverId = msg.data.resolverId;
- msg.target.sendAsyncMessage(msg.name + promiseStatus, {result: result});
- },
-
- _isValidMessage: function(msg) {
- let appIdValid = gMap.isAppIdRegistered(msg.data.appId);
- return msg.name === "SE:GetSEReaders" ? true : appIdValid;
- },
-
- /**
- * nsIMessageListener interface methods.
- */
-
- receiveMessage: function(msg) {
- DEBUG && debug("Received '" + msg.name + "' message from content process" +
- ": " + JSON.stringify(msg.data));
-
- if (msg.name === "child-process-shutdown") {
- this._handleChildProcessShutdown(msg.target);
- return null;
- }
-
- if (SE_IPC_SECUREELEMENT_MSG_NAMES.indexOf(msg.name) !== -1) {
- if (!msg.target.assertPermission("secureelement-manage")) {
- debug("SecureElement message " + msg.name + " from a content process " +
- "with no 'secureelement-manage' privileges.");
- return null;
- }
- } else {
- debug("Ignoring unknown message type: " + msg.name);
- return null;
- }
-
- let callback = (result) => this._sendSEResponse(msg, result);
- if (!this._isValidMessage(msg)) {
- debug("Message not valid");
- callback({ error: SE.ERROR_GENERIC });
- return null;
- }
-
- switch (msg.name) {
- case "SE:GetSEReaders":
- this._handleGetSEReadersRequest(msg.data, msg.target, callback);
- break;
- case "SE:OpenChannel":
- this._handleOpenChannel(msg.data, callback);
- break;
- case "SE:CloseChannel":
- this._handleCloseChannel(msg.data, callback);
- break;
- case "SE:TransmitAPDU":
- this._handleTransmit(msg.data, callback);
- break;
- }
- return null;
- },
-
- /**
- * nsIObserver interface methods.
- */
-
- observe: function(subject, topic, data) {
- if (topic === NS_XPCOM_SHUTDOWN_OBSERVER_ID) {
- this._shutdown();
- }
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SecureElementManager]);
diff --git a/dom/secureelement/gonk/SecureElement.manifest b/dom/secureelement/gonk/SecureElement.manifest
deleted file mode 100644
index a76fcfc11..000000000
--- a/dom/secureelement/gonk/SecureElement.manifest
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2012 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# SecureElementManager
-component {48f4e650-28d2-11e4-8c21-0800200c9a66} SecureElement.js
-contract @mozilla.org/secureelement/parent-manager;1 {48f4e650-28d2-11e4-8c21-0800200c9a66}
-category profile-after-change SecureElementManager @mozilla.org/secureelement/parent-manager;1
diff --git a/dom/secureelement/gonk/UiccConnector.js b/dom/secureelement/gonk/UiccConnector.js
deleted file mode 100644
index 517303de2..000000000
--- a/dom/secureelement/gonk/UiccConnector.js
+++ /dev/null
@@ -1,360 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Copyright © 2014, Deutsche Telekom, Inc. */
-
-"use strict";
-
-/* globals Components, XPCOMUtils, SE, dump, libcutils, Services,
- iccService, SEUtils */
-
-const { interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyGetter(this, "SE", function() {
- let obj = {};
- Cu.import("resource://gre/modules/se_consts.js", obj);
- return obj;
-});
-
-// set to true in se_consts.js to see debug messages
-var DEBUG = SE.DEBUG_CONNECTOR;
-function debug(s) {
- if (DEBUG) {
- dump("-*- UiccConnector: " + s + "\n");
- }
-}
-
-XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
- "resource://gre/modules/SEUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "iccService",
- "@mozilla.org/icc/iccservice;1",
- "nsIIccService");
-
-const UICCCONNECTOR_CONTRACTID =
- "@mozilla.org/secureelement/connector/uicc;1";
-const UICCCONNECTOR_CID =
- Components.ID("{8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4}");
-const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
-
-// TODO: Bug 1118099 - Add multi-sim support.
-// In the Multi-sim, there is more than one client.
-// For now, use default clientID as 0. Ideally, SE parent process would like to
-// know which clients (uicc slot) are connected to CLF over SWP interface.
-const PREFERRED_UICC_CLIENTID =
- libcutils.property_get("ro.moz.se.def_client_id", "0");
-
-/**
- * 'UiccConnector' object is a wrapper over iccService's channel management
- * related interfaces that implements nsISecureElementConnector interface.
- */
-function UiccConnector() {
- this._init();
-}
-
-UiccConnector.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISecureElementConnector,
- Ci.nsIIccListener]),
- classID: UICCCONNECTOR_CID,
- classInfo: XPCOMUtils.generateCI({
- classID: UICCCONNECTOR_CID,
- contractID: UICCCONNECTOR_CONTRACTID,
- classDescription: "UiccConnector",
- interfaces: [Ci.nsISecureElementConnector,
- Ci.nsIIccListener,
- Ci.nsIObserver]
- }),
-
- _SEListeners: [],
- _isPresent: false,
-
- _init: function() {
- Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.registerListener(this);
-
- // Update the state in order to avoid race condition.
- // By this time, 'notifyCardStateChanged (with proper card state)'
- // may have occurred already before this module initialization.
- this._updatePresenceState();
- },
-
- _shutdown: function() {
- Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.unregisterListener(this);
- },
-
- _updatePresenceState: function() {
- let uiccNotReadyStates = [
- Ci.nsIIcc.CARD_STATE_UNKNOWN,
- Ci.nsIIcc.CARD_STATE_ILLEGAL,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS,
- Ci.nsIIcc.CARD_STATE_PERMANENT_BLOCKED,
- Ci.nsIIcc.CARD_STATE_UNDETECTED
- ];
-
- let cardState = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID).cardState;
- let uiccPresent = cardState !== null &&
- uiccNotReadyStates.indexOf(cardState) == -1;
-
- if (this._isPresent === uiccPresent) {
- return;
- }
-
- debug("Uicc presence changed " + this._isPresent + " -> " + uiccPresent);
- this._isPresent = uiccPresent;
- this._SEListeners.forEach((listener) => {
- listener.notifySEPresenceChanged(SE.TYPE_UICC, this._isPresent);
- });
- },
-
- // See GP Spec, 11.1.4 Class Byte Coding
- _setChannelToCLAByte: function(cla, channel) {
- if (channel < SE.LOGICAL_CHANNEL_NUMBER_LIMIT) {
- // b7 = 0 indicates the first interindustry class byte coding
- cla = (cla & 0x9C) & 0xFF | channel;
- } else if (channel < SE.SUPPLEMENTARY_LOGICAL_CHANNEL_NUMBER_LIMIT) {
- // b7 = 1 indicates the further interindustry class byte coding
- cla = (cla & 0xB0) & 0xFF | 0x40 | (channel - SE.LOGICAL_CHANNEL_NUMBER_LIMIT);
- } else {
- debug("Channel number must be within [0..19]");
- return SE.ERROR_GENERIC;
- }
- return cla;
- },
-
- _doGetOpenResponse: function(channel, length, callback) {
- // Le value is set. It means that this is a request for all available
- // response bytes.
- let cla = this._setChannelToCLAByte(SE.CLA_GET_RESPONSE, channel);
- this.exchangeAPDU(channel, cla, SE.INS_GET_RESPONSE, 0x00, 0x00,
- null, length, {
- notifyExchangeAPDUResponse: function(sw1, sw2, response) {
- debug("GET Response : " + response);
- if (callback) {
- callback({
- error: SE.ERROR_NONE,
- sw1: sw1,
- sw2: sw2,
- response: response
- });
- }
- },
-
- notifyError: function(reason) {
- debug("Failed to get open response: " +
- ", Rejected with Reason : " + reason);
- if (callback) {
- callback({ error: SE.ERROR_INVALIDAPPLICATION, reason: reason });
- }
- }
- });
- },
-
- _doIccExchangeAPDU: function(channel, cla, ins, p1, p2, p3,
- data, appendResp, callback) {
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.iccExchangeAPDU(channel, cla & 0xFC, ins, p1, p2, p3, data, {
- notifyExchangeAPDUResponse: (sw1, sw2, response) => {
- debug("sw1 : " + sw1 + ", sw2 : " + sw2 + ", response : " + response);
-
- // According to ETSI TS 102 221 , Section 7.2.2.3.1,
- // Enforce 'Procedure bytes' checks before notifying the callback.
- // Note that 'Procedure bytes'are special cases.
- // There is no need to handle '0x60' procedure byte as it implies
- // no-action from SE stack perspective. This procedure byte is not
- // notified to application layer.
- if (sw1 === 0x6C) {
- // Use the previous command header with length as second procedure
- // byte (SW2) as received and repeat the procedure.
-
- // Recursive! and Pass empty response '' as args, since '0x6C'
- // procedure does not have to deal with appended responses.
- this._doIccExchangeAPDU(channel, cla, ins, p1, p2,
- sw2, data, "", callback);
- } else if (sw1 === 0x61) {
- // Since the terminal waited for a second procedure byte and
- // received it (sw2), send a GET RESPONSE command header to the UICC
- // with a maximum length of 'XX', where 'XX' is the value of the
- // second procedure byte (SW2).
-
- let claWithChannel = this._setChannelToCLAByte(SE.CLA_GET_RESPONSE,
- channel);
-
- // Recursive, with GET RESPONSE bytes and '0x61' procedure IS interested
- // in appended responses. Pass appended response and note that p3=sw2.
- this._doIccExchangeAPDU(channel, claWithChannel, SE.INS_GET_RESPONSE,
- 0x00, 0x00, sw2, null,
- (response ? response + appendResp : appendResp),
- callback);
- } else if (callback) {
- callback.notifyExchangeAPDUResponse(sw1, sw2, response);
- }
- },
-
- notifyError: (reason) => {
- debug("Failed to trasmit C-APDU over the channel # : " + channel +
- ", Rejected with Reason : " + reason);
- if (callback) {
- callback.notifyError(reason);
- }
- }
- });
- },
-
- /**
- * nsISecureElementConnector interface methods.
- */
-
- /**
- * Opens a channel on a default clientId
- */
- openChannel: function(aid, callback) {
- if (!this._isPresent) {
- callback.notifyError(SE.ERROR_NOTPRESENT);
- return;
- }
-
- // TODO: Bug 1118106: Handle Resource management / leaks by persisting
- // the newly opened channel in some persistent storage so that when this
- // module gets restarted (say after opening a channel) in the event of
- // some erroneous conditions such as gecko restart /, crash it can read
- // the persistent storage to check if there are any held resources
- // (opened channels) and close them.
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.iccOpenChannel(aid, {
- notifyOpenChannelSuccess: (channel) => {
- this._doGetOpenResponse(channel, 0x00, function(result) {
- if (callback) {
- callback.notifyOpenChannelSuccess(channel, result.response);
- }
- });
- },
-
- notifyError: (reason) => {
- debug("Failed to open the channel to AID : " + aid +
- ", Rejected with Reason : " + reason);
- if (callback) {
- callback.notifyError(reason);
- }
- }
- });
- },
-
- /**
- * Transmit the C-APDU (command) on default clientId.
- */
- exchangeAPDU: function(channel, cla, ins, p1, p2, data, le, callback) {
- if (!this._isPresent) {
- callback.notifyError(SE.ERROR_NOTPRESENT);
- return;
- }
-
- if (data && data.length % 2 !== 0) {
- callback.notifyError("Data should be a hex string with length % 2 === 0");
- return;
- }
-
- cla = this._setChannelToCLAByte(cla, channel);
- let lc = data ? data.length / 2 : 0;
- let p3 = lc || le;
-
- if (lc && (le !== -1)) {
- data += SEUtils.byteArrayToHexString([le]);
- }
-
- // Pass empty response '' as args as we are not interested in appended
- // responses yet!
- debug("exchangeAPDU on Channel # " + channel);
- this._doIccExchangeAPDU(channel, cla, ins, p1, p2, p3, data, "",
- callback);
- },
-
- /**
- * Closes the channel on default clientId.
- */
- closeChannel: function(channel, callback) {
- if (!this._isPresent) {
- callback.notifyError(SE.ERROR_NOTPRESENT);
- return;
- }
-
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.iccCloseChannel(channel, {
- notifyCloseChannelSuccess: function() {
- debug("closeChannel successfully closed the channel # : " + channel);
- if (callback) {
- callback.notifyCloseChannelSuccess();
- }
- },
-
- notifyError: function(reason) {
- debug("Failed to close the channel # : " + channel +
- ", Rejected with Reason : " + reason);
- if (callback) {
- callback.notifyError(reason);
- }
- }
- });
- },
-
- registerListener: function(listener) {
- if (this._SEListeners.indexOf(listener) !== -1) {
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- this._SEListeners.push(listener);
- // immediately notify listener about the current state
- listener.notifySEPresenceChanged(SE.TYPE_UICC, this._isPresent);
- },
-
- unregisterListener: function(listener) {
- let idx = this._SEListeners.indexOf(listener);
- if (idx !== -1) {
- this._SEListeners.splice(idx, 1);
- }
- },
-
- /**
- * nsIIccListener interface methods.
- */
- notifyStkCommand: function() {},
-
- notifyStkSessionEnd: function() {},
-
- notifyIccInfoChanged: function() {},
-
- notifyCardStateChanged: function() {
- debug("Card state changed, updating UICC presence.");
- this._updatePresenceState();
- },
-
- /**
- * nsIObserver interface methods.
- */
-
- observe: function(subject, topic, data) {
- if (topic === NS_XPCOM_SHUTDOWN_OBSERVER_ID) {
- this._shutdown();
- }
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UiccConnector]);
diff --git a/dom/secureelement/gonk/UiccConnector.manifest b/dom/secureelement/gonk/UiccConnector.manifest
deleted file mode 100644
index 5ac8b3b7b..000000000
--- a/dom/secureelement/gonk/UiccConnector.manifest
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2012 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# UiccConnector
-component {8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4} UiccConnector.js
-contract @mozilla.org/secureelement/connector/uicc;1 {8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4}
diff --git a/dom/secureelement/gonk/gp_consts.js b/dom/secureelement/gonk/gp_consts.js
deleted file mode 100644
index 7c3bc7165..000000000
--- a/dom/secureelement/gonk/gp_consts.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-/* Object Directory File (ODF) is an elementary file which contain
- pointers to other EFs. It is specified in PKCS#15 section 6.7. */
-this.ODF_DF = [0x50, 0x31];
-
-/* ISO 7816-4: secure messaging */
-this.CLA_SM = 0x00;
-
-/* ISO 7816-4, 5.4.1 table 11 */
-this.INS_SF = 0xA4; // select file
-this.INS_GR = 0xC0; // get response
-this.INS_RB = 0xB0; // read binary
-
-/* ISO 7816-4: select file, see 6.11.3, table 58 & 59 */
-this.P1_SF_DF = 0x00; // select DF
-this.P2_SF_FCP = 0x04; // return FCP
-
-/* ISO 7816-4: read binary, 6.1.3. P1 and P2 describe offset of the first byte
- to be read. We always read the whole files at the moment. */
-this.P1_RB = 0x00;
-this.P2_RB = 0x00;
-
-/* ISO 7816-4: get response, 7.1.3 table 74, P1-P2 '0000' (other values RFU) */
-this.P1_GR = 0x00;
-this.P2_GR = 0x00;
-
-/* ISO 7816-4: 5.1.5 File Control Information, Table 1. For FCP and FMD. */
-this.TAG_PROPRIETARY = 0x00;
-this.TAG_NON_TLV = 0x53;
-this.TAG_BER_TLV = 0x73;
-
-/* ASN.1 tags */
-this.TAG_SEQUENCE = 0x30;
-this.TAG_OCTETSTRING = 0x04;
-this.TAG_OID = 0x06; // Object Identifier
-
-/* ISO 7816-4: 5.1.5 File Control Information, Templates. */
-this.TAG_FCP = 0x62; // File control parameters template
-this.TAG_FMD = 0x64; // File management data template
-this.TAG_FCI = 0x6F; // File control information template
-
-/* EF_DIR tags */
-this.TAG_APPLTEMPLATE = 0x61;
-this.TAG_APPLIDENTIFIER = 0x4F;
-this.TAG_APPLLABEL = 0x50;
-this.TAG_APPLPATH = 0x51;
-
-this.TAG_GPD_ALL = 0x82; // EF-ACRules - GPD spec. "all applets"
-
-/* Generic TLVs that are parsed */
-this.TAG_GPD_AID = 0xA0; // AID in the EF-ACRules - GPD spec, "one applet"
-this.TAG_EXTERNALDO = 0xA1; // External data objects - PKCS#15
-this.TAG_INDIRECT = 0xA5; // Indirect value.
-this.TAG_EF_ODF = 0xA7; // Elemenetary File Object Directory File
-
-// Allow this file to be imported via Components.utils.import().
-this.EXPORTED_SYMBOLS = Object.keys(this);
diff --git a/dom/secureelement/gonk/nsIAccessControlEnforcer.idl b/dom/secureelement/gonk/nsIAccessControlEnforcer.idl
deleted file mode 100644
index 7ad1a97f6..000000000
--- a/dom/secureelement/gonk/nsIAccessControlEnforcer.idl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-#include "nsISupports.idl"
-
-interface nsIVariant;
-
-[scriptable, uuid(4994a960-26d9-4d71-82dd-4505bd97bf2a)]
-interface nsIAccessControlEnforcer : nsISupports
-{
- /**
- * Determines whether application identified by its ID should be allowed
- * to access Secure Element's applet identified by its AID. Decision
- * is made according to the GPD specification.
- *
- * @param localId
- * ID of an application accessing SE
- * @param seType
- * Type of the SE.
- * @param aid
- * AID of a SE applet
- * @return Promise which is resolved to true if access should be allowed,
- * false otherwise, and rejected if the application contains
- * no developer certificate.
- */
- jsval isAccessAllowed(in unsigned long localId,
- in DOMString seType,
- in DOMString aid);
-};
diff --git a/dom/secureelement/gonk/nsIAccessRulesManager.idl b/dom/secureelement/gonk/nsIAccessRulesManager.idl
deleted file mode 100644
index 173f57c90..000000000
--- a/dom/secureelement/gonk/nsIAccessRulesManager.idl
+++ /dev/null
@@ -1,50 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(7baedd2a-3189-4b03-b2a3-34016043b5e2)]
-interface nsIAccessRulesManager : nsISupports
-{
- /* Wildcard: rule allows all applications to access an SE applet */
- const unsigned short ALLOW_ALL = 1;
- /* Wildcard: rule denies all applications to access an SE applet */
- const unsigned short DENY_ALL = 2;
- /* Wildcard: rule allows application(s) access to all SE applets */
- const unsigned short ALL_APPLET = 3;
-
- /**
- * Initiates Access Rules Manager, this should perform the initial
- * reading of rules from access rule source
- * @return Promise which is resolved if init is successful or rejected
- * otherwise
- */
- jsval init();
-
- /**
- * Retrieves all access rules.
- *
- * Rules are stored in an array. Each rule contains the following properties:
- * - applet - describes an SE applet referenced by this rule. Might equal
- * to an applet AID (as a byte array), or to a wildcard "all"
- * meaning all applets.
- * - application - describes an application referenced by this rule. Might
- * be an array of developer certificate hashes (each as
- * a byte array) in which case it lists all applications
- * allowed access. Alternatively, might equal to wildcard
- * "allowed-all" or "denied-all".
- *
- * Example rule format:
- * [{ applet: ALL_APPLET,
- * application: [[0x01, 0x02, ..., 0x20],
- * [0x20, 0x19, ...., 0x01]],
- * { applet: [0x00, 0x01, ..., 0x05],
- * application: ALLOW_ALL}}]
- *
- * @return Promise which resolves with Array containing parsed access rules
- */
- jsval getAccessRules();
-};
diff --git a/dom/secureelement/gonk/nsISecureElementConnector.idl b/dom/secureelement/gonk/nsISecureElementConnector.idl
deleted file mode 100644
index 92cc1eb2b..000000000
--- a/dom/secureelement/gonk/nsISecureElementConnector.idl
+++ /dev/null
@@ -1,124 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(1ff3f35a-1b6f-4e65-a89e-a363b8604cd7)]
-interface nsISEChannelCallback : nsISupports
-{
- /**
- * Callback function to notify on successfully opening a logical channel.
- *
- * @param channel
- * The Channel Number/Handle that is successfully opened.
- * @param openResponse
- * Response from SE for OpenChannel operation.
- */
- void notifyOpenChannelSuccess(in long channel, in DOMString openResponse);
-
- /**
- * Callback function to notify on successfully closing the logical channel.
- *
- */
- void notifyCloseChannelSuccess();
-
- /**
- * Callback function to notify the status of 'seExchangeAPDU' command.
- *
- * @param sw1
- * Response's First Status Byte
- * @param sw2
- * Response's Second Status Byte
- * @param data
- * Response's data
- */
- void notifyExchangeAPDUResponse(in octet sw1,
- in octet sw2,
- in DOMString data);
-
- /**
- * Callback function to notify error
- *
- * @param error
- * Error describing the reason for failure.
- */
- void notifyError(in DOMString error);
-};
-
-[scriptable, uuid(417f59ee-f582-45b9-9a4e-e9dcefecb4f7)]
-interface nsISEListener : nsISupports
-{
- void notifySEPresenceChanged(in DOMString seType, in boolean isPresent);
-};
-
-[scriptable, uuid(3cef313a-1d01-432d-9cd2-6610a80911f3)]
-interface nsISecureElementConnector : nsISupports
-{
- /**
- * Open a logical communication channel with the specific secure element type
- *
- * @param aid
- * Application Identifier of the Card Applet on the secure element.
- * @param callback
- * callback to notify the result of the operation.
- */
- void openChannel(in DOMString aid,
- in nsISEChannelCallback callback);
-
- /**
- * Exchanges APDU channel with the specific secure element type
- *
- * @param channel
- * Channel on which C-APDU to be transmitted.
- * @param cla
- Class Byte.
- * @param ins
- Instruction Byte
- * @param p1
- Reference parameter first byte
- * @param p2
- Reference parameter second byte
- * Refer to 3G TS 31.101 , 10.2 'Command APDU Structure' for all the cases.
- * @param data
- Sequence of C-APDU data octets
- * @param le [optional]
- * le is the length of expected response. If the response is not expected,
- it should be explicitly set to -1.
- * @param callback
- * callback to notify the result of the operation.
- */
- void exchangeAPDU(in long channel,
- in octet cla,
- in octet ins,
- in octet p1,
- in octet p2,
- in DOMString data,
- in short le,
- in nsISEChannelCallback callback);
-
- /**
- * Closes the logical communication channel to the specific secure element type
- *
- * @param channel
- * Channel to be closed.
- * @param callback
- * callback to notify the result of the operation.
- */
- void closeChannel(in long channel,
- in nsISEChannelCallback callback);
-
- /**
- * Register a Secure Element listener
- *
- * @param listener
- */
- void registerListener(in nsISEListener listener);
-
- /**
- * Unregister a Secure Element listener
- *
- * @param listener
- */
- void unregisterListener(in nsISEListener listener);
-};
diff --git a/dom/secureelement/gonk/se_consts.js b/dom/secureelement/gonk/se_consts.js
deleted file mode 100644
index 13489b7ae..000000000
--- a/dom/secureelement/gonk/se_consts.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Copyright © 2014, Deutsche Telekom, Inc. */
-
-// Set to true to debug SecureElement (SE) stack
-this.DEBUG_ALL = false;
-
-// Set individually to debug specific layers
-this.DEBUG_CONNECTOR = DEBUG_ALL || false;
-this.DEBUG_ACE = DEBUG_ALL || false ;
-this.DEBUG_SE = DEBUG_ALL || false ;
-
-// Maximun logical channels per session.
-// For 'uicc' SE type this value is 3, as opening a basic channel' : 0
-// is not allowed for security reasons. In such scenarios, possible
-// supplementary logical channels available are : [1, 2, or 3].
-// However,Other SE types may support upto max 4 (including '0').
-this.MAX_CHANNELS_ALLOWED_PER_SESSION = 4;
-
-this.BASIC_CHANNEL = 0;
-
-// According GPCardSpec 2.2
-this.MAX_APDU_LEN = 255; // including APDU header
-
-// CLA (1 byte) + INS (1 byte) + P1 (1 byte) + P2 (1 byte)
-this.APDU_HEADER_LEN = 4;
-
-this.LOGICAL_CHANNEL_NUMBER_LIMIT = 4;
-this.SUPPLEMENTARY_LOGICAL_CHANNEL_NUMBER_LIMIT = 20;
-
-this.MIN_AID_LEN = 5;
-this.MAX_AID_LEN = 16;
-
-this.CLA_GET_RESPONSE = 0x00;
-
-this.INS_SELECT = 0xA4;
-this.INS_MANAGE_CHANNEL = 0x70;
-this.INS_GET_RESPONSE = 0xC0;
-
-// Match the following errors with SecureElement.webidl's SEError enum values
-this.ERROR_NONE = "";
-this.ERROR_SECURITY = "SESecurityError";
-this.ERROR_IO = "SEIoError";
-this.ERROR_BADSTATE = "SEBadStateError";
-this.ERROR_INVALIDCHANNEL = "SEInvalidChannelError";
-this.ERROR_INVALIDAPPLICATION = "SEInvalidApplicationError";
-this.ERROR_GENERIC = "SEGenericError";
-this.ERROR_NOTPRESENT = "SENotPresentError";
-this.ERROR_ILLEGALPARAMETER = "SEIllegalParameterError";
-
-this.TYPE_UICC = "uicc";
-this.TYPE_ESE = "eSE";
-
-// Allow this file to be imported via Components.utils.import().
-this.EXPORTED_SYMBOLS = Object.keys(this);
diff --git a/dom/secureelement/moz.build b/dom/secureelement/moz.build
index a2c87b014..973000512 100644
--- a/dom/secureelement/moz.build
+++ b/dom/secureelement/moz.build
@@ -11,30 +11,6 @@ if CONFIG['MOZ_SECUREELEMENT']:
'DOMSecureElement.manifest',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_SECUREELEMENT']:
- EXTRA_COMPONENTS += [
- 'gonk/ACEService.js',
- 'gonk/ACEService.manifest',
- 'gonk/GPAccessRulesManager.js',
- 'gonk/GPAccessRulesManager.manifest',
- 'gonk/SecureElement.js',
- 'gonk/SecureElement.manifest',
- ]
- XPIDL_MODULE = 'dom_secureelement'
- XPIDL_SOURCES += [
- 'gonk/nsIAccessControlEnforcer.idl',
- 'gonk/nsIAccessRulesManager.idl',
- 'gonk/nsISecureElementConnector.idl',
- ]
- EXTRA_JS_MODULES += [
- 'gonk/gp_consts.js',
- 'gonk/se_consts.js',
- 'SEUtils.jsm'
- ]
- XPCSHELL_TESTS_MANIFESTS += [
- 'tests/unit/xpcshell.ini'
- ]
-
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp
index 5e435d4ca..65be02809 100644
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -171,9 +171,10 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
}
}
- // aExtra is only non-null if the channel got redirected.
- bool wasRedirected = (aExtra != nullptr);
+ // aExtra holds the original URI of the channel if the
+ // channel got redirected (until we fix Bug 1332422).
nsCOMPtr<nsIURI> originalURI = do_QueryInterface(aExtra);
+ bool wasRedirected = originalURI;
bool permitted = permitsInternal(dir,
aContentLocation,
@@ -219,14 +220,6 @@ nsCSPContext::permitsInternal(CSPDirective aDir,
nsAutoString violatedDirective;
for (uint32_t p = 0; p < mPolicies.Length(); p++) {
-
- // According to the W3C CSP spec, frame-ancestors checks are ignored for
- // report-only policies (when "monitoring").
- if (aDir == nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE &&
- mPolicies[p]->getReportOnlyFlag()) {
- continue;
- }
-
if (!mPolicies[p]->permits(aDir,
aContentLocation,
aNonce,
@@ -824,15 +817,6 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
{
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
-#ifdef MOZ_B2G
- // load group information (on process-split necko implementations like b2g).
- // (fix this in bug 1011086)
- if (!mCallingChannelLoadGroup) {
- NS_WARNING("Load group required but not present for report sending; cannot send CSP violation reports");
- return NS_ERROR_FAILURE;
- }
-#endif
-
dom::CSPReport report;
nsresult rv;
diff --git a/dom/security/nsCSPService.cpp b/dom/security/nsCSPService.cpp
index 7344e19fa..4807c9aa4 100644
--- a/dom/security/nsCSPService.cpp
+++ b/dom/security/nsCSPService.cpp
@@ -288,6 +288,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(policyType);
int16_t aDecision = nsIContentPolicy::ACCEPT;
+ nsCOMPtr<nsISupports> requestContext = loadInfo->GetLoadingContext();
// 1) Apply speculative CSP for preloads
if (isPreload) {
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
@@ -298,7 +299,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
preloadCsp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
- nullptr, // nsISupports
+ requestContext, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // aExtra
&aDecision);
@@ -321,7 +322,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
- nullptr, // nsISupports
+ requestContext, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // aExtra
&aDecision);
diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp
index 49832f8f4..71c8e3433 100644
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -258,6 +258,9 @@ CSP_ContentTypeToDirective(nsContentPolicyType aType)
case nsIContentPolicy::TYPE_CSP_REPORT:
return nsIContentSecurityPolicy::NO_DIRECTIVE;
+ case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
+ return nsIContentSecurityPolicy::NO_DIRECTIVE;
+
// Fall through to error for all other directives
default:
MOZ_ASSERT(false, "Can not map nsContentPolicyType to CSPDirective");
diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index c4e1ed8e1..570730312 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -1,20 +1,97 @@
#include "nsContentSecurityManager.h"
+#include "nsEscape.h"
#include "nsIChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIStreamListener.h"
#include "nsILoadInfo.h"
+#include "nsIOService.h"
#include "nsContentUtils.h"
#include "nsCORSListenerProxy.h"
#include "nsIStreamListener.h"
-#include "nsIDocument.h"
-#include "nsMixedContentBlocker.h"
+#include "nsCDefaultURIFixup.h"
+#include "nsIURIFixup.h"
#include "mozilla/dom/Element.h"
+#include "mozilla/dom/TabChild.h"
NS_IMPL_ISUPPORTS(nsContentSecurityManager,
nsIContentSecurityManager,
nsIChannelEventSink)
+/* static */ bool
+nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel)
+{
+ // Let's block all toplevel document navigations to a data: URI.
+ // In all cases where the toplevel document is navigated to a
+ // data: URI the triggeringPrincipal is a codeBasePrincipal, or
+ // a NullPrincipal. In other cases, e.g. typing a data: URL into
+ // the URL-Bar, the triggeringPrincipal is a SystemPrincipal;
+ // we don't want to block those loads. Only exception, loads coming
+ // from an external applicaton (e.g. Thunderbird) don't load
+ // using a codeBasePrincipal, but we want to block those loads.
+ if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) {
+ return true;
+ }
+ nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
+ if (!loadInfo) {
+ return true;
+ }
+ if (loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
+ return true;
+ }
+ if (loadInfo->GetForceAllowDataURI()) {
+ // if the loadinfo explicitly allows the data URI navigation, let's allow it now
+ return true;
+ }
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS(rv, true);
+ bool isDataURI =
+ (NS_SUCCEEDED(uri->SchemeIs("data", &isDataURI)) && isDataURI);
+ if (!isDataURI) {
+ return true;
+ }
+ // Whitelist data: images as long as they are not SVGs
+ nsAutoCString filePath;
+ uri->GetFilePath(filePath);
+ if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) &&
+ !StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) {
+ return true;
+ }
+ // Whitelist data: PDFs and JSON
+ if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/pdf")) ||
+ StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/json"))) {
+ return true;
+ }
+ // Redirecting to a toplevel data: URI is not allowed, hence we make
+ // sure the RedirectChain is empty.
+ if (!loadInfo->GetLoadTriggeredFromExternal() &&
+ nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal()) &&
+ loadInfo->RedirectChain().IsEmpty()) {
+ return true;
+ }
+ nsAutoCString dataSpec;
+ uri->GetSpec(dataSpec);
+ if (dataSpec.Length() > 50) {
+ dataSpec.Truncate(50);
+ dataSpec.AppendLiteral("...");
+ }
+ nsCOMPtr<nsITabChild> tabChild = do_QueryInterface(loadInfo->ContextForTopLevelLoad());
+ nsCOMPtr<nsIDocument> doc;
+ if (tabChild) {
+ doc = static_cast<mozilla::dom::TabChild*>(tabChild.get())->GetDocument();
+ }
+ NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec));
+ const char16_t* params[] = { specUTF16.get() };
+ nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+ NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
+ doc,
+ nsContentUtils::eSECURITY_PROPERTIES,
+ "BlockTopLevelDataURINavigation",
+ params, ArrayLength(params));
+ return false;
+}
+
static nsresult
ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
{
@@ -167,23 +244,31 @@ DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
static nsresult
DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
{
- nsCOMPtr<nsIURI> uri;
- nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
- NS_ENSURE_SUCCESS(rv, rv);
-
nsContentPolicyType contentPolicyType =
aLoadInfo->GetExternalContentPolicyType();
nsContentPolicyType internalContentPolicyType =
aLoadInfo->InternalContentPolicyType();
nsCString mimeTypeGuess;
- nsCOMPtr<nsINode> requestingContext = nullptr;
+ nsCOMPtr<nsISupports> requestingContext = nullptr;
-#ifdef DEBUG
- // Don't enforce TYPE_DOCUMENT assertions for loads
- // initiated by javascript tests.
- bool skipContentTypeCheck = false;
- skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion");
-#endif
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+ contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
+ // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
+ // be wyciwyg:// channels. Let's fix up the URI so we can
+ // perform proper security checks.
+ nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
+ if (NS_SUCCEEDED(rv) && urifixup) {
+ nsCOMPtr<nsIURI> fixedURI;
+ rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
+ if (NS_SUCCEEDED(rv)) {
+ uri = fixedURI;
+ }
+ }
+ }
switch(contentPolicyType) {
case nsIContentPolicy::TYPE_OTHER: {
@@ -217,16 +302,14 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
}
case nsIContentPolicy::TYPE_DOCUMENT: {
- MOZ_ASSERT(skipContentTypeCheck || false, "contentPolicyType not supported yet");
+ mimeTypeGuess = EmptyCString();
+ requestingContext = aLoadInfo->ContextForTopLevelLoad();
break;
}
case nsIContentPolicy::TYPE_SUBDOCUMENT: {
mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
requestingContext = aLoadInfo->LoadingNode();
- MOZ_ASSERT(!requestingContext ||
- requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
- "type_subdocument requires requestingContext of type Document");
break;
}
@@ -250,10 +333,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
case nsIContentPolicy::TYPE_XMLHTTPREQUEST: {
// alias nsIContentPolicy::TYPE_DATAREQUEST:
requestingContext = aLoadInfo->LoadingNode();
- MOZ_ASSERT(!requestingContext ||
- requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
- "type_xml requires requestingContext of type Document");
-
+#ifdef DEBUG
+ {
+ nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+ MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+ "type_xml requires requestingContext of type Document");
+ }
+#endif
// We're checking for the external TYPE_XMLHTTPREQUEST here in case
// an addon creates a request with that type.
if (internalContentPolicyType ==
@@ -274,18 +360,26 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: {
mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode();
- MOZ_ASSERT(!requestingContext ||
- requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE,
- "type_subrequest requires requestingContext of type Element");
+#ifdef DEBUG
+ {
+ nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+ MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
+ "type_subrequest requires requestingContext of type Element");
+ }
+#endif
break;
}
case nsIContentPolicy::TYPE_DTD: {
mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode();
- MOZ_ASSERT(!requestingContext ||
- requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
- "type_dtd requires requestingContext of type Document");
+#ifdef DEBUG
+ {
+ nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+ MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+ "type_dtd requires requestingContext of type Document");
+ }
+#endif
break;
}
@@ -303,9 +397,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
mimeTypeGuess = EmptyCString();
}
requestingContext = aLoadInfo->LoadingNode();
- MOZ_ASSERT(!requestingContext ||
- requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE,
- "type_media requires requestingContext of type Element");
+#ifdef DEBUG
+ {
+ nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+ MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
+ "type_media requires requestingContext of type Element");
+ }
+#endif
break;
}
@@ -332,18 +430,26 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
case nsIContentPolicy::TYPE_XSLT: {
mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
requestingContext = aLoadInfo->LoadingNode();
- MOZ_ASSERT(!requestingContext ||
- requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
- "type_xslt requires requestingContext of type Document");
+#ifdef DEBUG
+ {
+ nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+ MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+ "type_xslt requires requestingContext of type Document");
+ }
+#endif
break;
}
case nsIContentPolicy::TYPE_BEACON: {
mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode();
- MOZ_ASSERT(!requestingContext ||
- requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
- "type_beacon requires requestingContext of type Document");
+#ifdef DEBUG
+ {
+ nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+ MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+ "type_beacon requires requestingContext of type Document");
+ }
+#endif
break;
}
@@ -365,31 +471,44 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
break;
}
+ case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD: {
+ mimeTypeGuess = EmptyCString();
+ requestingContext = aLoadInfo->LoadingNode();
+ break;
+ }
+
default:
// nsIContentPolicy::TYPE_INVALID
MOZ_ASSERT(false, "can not perform security check without a valid contentType");
}
+ // For document loads we use the triggeringPrincipal as the originPrincipal.
+ // Note the the loadingPrincipal for loads of TYPE_DOCUMENT is a nullptr.
+ nsCOMPtr<nsIPrincipal> principal =
+ (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+ contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)
+ ? aLoadInfo->TriggeringPrincipal()
+ : aLoadInfo->LoadingPrincipal();
+
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
uri,
- aLoadInfo->LoadingPrincipal(),
+ principal,
requestingContext,
mimeTypeGuess,
nullptr, //extra,
&shouldLoad,
nsContentUtils::GetContentPolicy(),
nsContentUtils::GetSecurityManager());
- NS_ENSURE_SUCCESS(rv, rv);
- if (NS_CP_REJECTED(shouldLoad)) {
- return NS_ERROR_CONTENT_BLOCKED;
- }
- if (nsMixedContentBlocker::sSendHSTSPriming) {
- rv = nsMixedContentBlocker::MarkLoadInfoForPriming(uri,
- requestingContext,
- aLoadInfo);
- return rv;
+ if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
+ if ((NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) &&
+ (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+ contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)) {
+ // for docshell loads we might have to return SHOW_ALT.
+ return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
+ }
+ return NS_ERROR_CONTENT_BLOCKED;
}
return NS_OK;
@@ -529,6 +648,24 @@ nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
+ nsContentPolicyType contentPolicyType =
+ loadInfo->GetExternalContentPolicyType();
+
+ if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+ contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
+ // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
+ // be wyciwyg:// channels. Let's fix up the URI so we can
+ // perform proper security checks.
+ nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
+ if (NS_SUCCEEDED(rv) && urifixup) {
+ nsCOMPtr<nsIURI> fixedURI;
+ rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
+ if (NS_SUCCEEDED(rv)) {
+ uri = fixedURI;
+ }
+ }
+ }
+
// Handle cookie policies
uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h
index 912c0e89f..bab847743 100644
--- a/dom/security/nsContentSecurityManager.h
+++ b/dom/security/nsContentSecurityManager.h
@@ -32,6 +32,8 @@ public:
static nsresult doContentSecurityCheck(nsIChannel* aChannel,
nsCOMPtr<nsIStreamListener>& aInAndOutListener);
+ static bool AllowTopLevelNavigationToDataURI(nsIChannel* aChannel);
+
private:
static nsresult CheckChannel(nsIChannel* aChannel);
diff --git a/dom/security/nsMixedContentBlocker.cpp b/dom/security/nsMixedContentBlocker.cpp
index 4e80dce3f..c03628da0 100644
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -54,13 +54,6 @@ bool nsMixedContentBlocker::sBlockMixedScript = false;
// Is mixed display content blocking (images, audio, video, <a ping>) enabled?
bool nsMixedContentBlocker::sBlockMixedDisplay = false;
-// Do we move HSTS before mixed-content
-bool nsMixedContentBlocker::sUseHSTS = false;
-// Do we send an HSTS priming request
-bool nsMixedContentBlocker::sSendHSTSPriming = false;
-// Default HSTS Priming failure timeout to 7 days, in seconds
-uint32_t nsMixedContentBlocker::sHSTSPrimingCacheTimeout = (60 * 24 * 7);
-
// Fired at the document that attempted to load mixed content. The UI could
// handle this event, for example, by displaying an info bar that offers the
// choice to reload the page with mixed content permitted.
@@ -202,18 +195,6 @@ nsMixedContentBlocker::nsMixedContentBlocker()
// Cache the pref for mixed display blocking
Preferences::AddBoolVarCache(&sBlockMixedDisplay,
"security.mixed_content.block_display_content");
-
- // Cache the pref for HSTS
- Preferences::AddBoolVarCache(&sUseHSTS,
- "security.mixed_content.use_hsts");
-
- // Cache the pref for sending HSTS priming
- Preferences::AddBoolVarCache(&sSendHSTSPriming,
- "security.mixed_content.send_hsts_priming");
-
- // Cache the pref for HSTS priming failure cache time
- Preferences::AddUintVarCache(&sHSTSPrimingCacheTimeout,
- "security.mixed_content.hsts_priming_cache_timeout");
}
nsMixedContentBlocker::~nsMixedContentBlocker()
@@ -343,22 +324,6 @@ nsMixedContentBlocker::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
return NS_BINDING_FAILED;
}
- if (nsMixedContentBlocker::sSendHSTSPriming) {
- // The LoadInfo passed in is for the original channel, HSTS priming needs to
- // be set on the new channel, if required. If the redirect changes
- // http->https, or vice-versa, the need for priming may change.
- nsCOMPtr<nsILoadInfo> newLoadInfo;
- rv = aNewChannel->GetLoadInfo(getter_AddRefs(newLoadInfo));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = nsMixedContentBlocker::MarkLoadInfoForPriming(newUri,
- requestingContext,
- newLoadInfo);
- if (NS_FAILED(rv)) {
- decision = REJECT_REQUEST;
- newLoadInfo->ClearHSTSPriming();
- }
- }
-
// If the channel is about to load mixed content, abort the channel
if (!NS_CP_ACCEPTED(decision)) {
autoCallback.DontCallback();
@@ -503,6 +468,13 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
*aDecision = ACCEPT;
return NS_OK;
+ // Creating insecure connections for a save-as link download is acceptable.
+ // This download is completely disconnected from the docShell, but still
+ // using the same loading principal.
+ case TYPE_SAVEAS_DOWNLOAD:
+ *aDecision = ACCEPT;
+ return NS_OK;
+
// Static display content is considered moderate risk for mixed content so
// these will be blocked according to the mixed display preference
case TYPE_IMAGE:
@@ -691,12 +663,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
// the parent is https, and the protocol associated with innerContentLocation
// doesn't map to the secure URI flags checked above. Assert this for
// sanity's sake
-#ifdef DEBUG
- bool isHttpsScheme = false;
- rv = innerContentLocation->SchemeIs("https", &isHttpsScheme);
- NS_ENSURE_SUCCESS(rv, rv);
- MOZ_ASSERT(!isHttpsScheme);
-#endif
*aDecision = REJECT_REQUEST;
return NS_OK;
}
@@ -836,34 +802,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
}
nsresult stateRV = securityUI->GetState(&state);
- bool doHSTSPriming = false;
- if (isHttpScheme) {
- bool hsts = false;
- bool cached = false;
- nsCOMPtr<nsISiteSecurityService> sss =
- do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aContentLocation,
- 0, &cached, &hsts);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (hsts && sUseHSTS) {
- // assume we will be upgraded later
- *aDecision = ACCEPT;
- return NS_OK;
- }
-
- // Send a priming request if the result is not already cached and priming
- // requests are allowed
- if (!cached && sSendHSTSPriming) {
- // add this URI as a priming location
- doHSTSPriming = true;
- document->AddHSTSPrimingLocation(innerContentLocation,
- HSTSPrimingState::eHSTS_PRIMING_ALLOW);
- *aDecision = ACCEPT;
- }
- }
-
// At this point we know that the request is mixed content, and the only
// question is whether we block it. Record telemetry at this point as to
// whether HSTS would have fixed things by making the content location
@@ -879,14 +817,14 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
bool active = (classification == eMixedScript);
if (!aHadInsecureImageRedirect) {
if (XRE_IsParentProcess()) {
- AccumulateMixedContentHSTS(innerContentLocation, active, doHSTSPriming);
+ AccumulateMixedContentHSTS(innerContentLocation, active);
} else {
// Ask the parent process to do the same call
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
if (cc) {
mozilla::ipc::URIParams uri;
SerializeURI(innerContentLocation, uri);
- cc->SendAccumulateMixedContentHSTS(uri, active, doHSTSPriming);
+ cc->SendAccumulateMixedContentHSTS(uri, active);
}
}
}
@@ -929,13 +867,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
}
}
} else {
- if (doHSTSPriming) {
- document->AddHSTSPrimingLocation(innerContentLocation,
- HSTSPrimingState::eHSTS_PRIMING_BLOCK);
- *aDecision = nsIContentPolicy::ACCEPT;
- } else {
- *aDecision = nsIContentPolicy::REJECT_REQUEST;
- }
+ *aDecision = nsIContentPolicy::REJECT_REQUEST;
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
if (!rootDoc->GetHasMixedDisplayContentBlocked() && NS_SUCCEEDED(stateRV)) {
rootDoc->SetHasMixedDisplayContentBlocked(true);
@@ -981,13 +913,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
}
} else {
//User has not overriden the pref by Disabling protection. Reject the request and update the security state.
- if (doHSTSPriming) {
- document->AddHSTSPrimingLocation(innerContentLocation,
- HSTSPrimingState::eHSTS_PRIMING_BLOCK);
- *aDecision = nsIContentPolicy::ACCEPT;
- } else {
- *aDecision = nsIContentPolicy::REJECT_REQUEST;
- }
+ *aDecision = nsIContentPolicy::REJECT_REQUEST;
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
// See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
if (rootDoc->GetHasMixedActiveContentBlocked()) {
@@ -1052,24 +978,10 @@ enum MixedContentHSTSState {
MCB_HSTS_ACTIVE_WITH_HSTS = 3
};
-// Similar to the existing mixed-content HSTS, except MCB_HSTS_*_NO_HSTS is
-// broken into two distinct states, indicating whether we plan to send a priming
-// request or not. If we decided not go send a priming request, it could be
-// because it is a type we do not support, or because we cached a previous
-// negative response.
-enum MixedContentHSTSPrimingState {
- eMCB_HSTS_PASSIVE_WITH_HSTS = 0,
- eMCB_HSTS_ACTIVE_WITH_HSTS = 1,
- eMCB_HSTS_PASSIVE_NO_PRIMING = 2,
- eMCB_HSTS_PASSIVE_DO_PRIMING = 3,
- eMCB_HSTS_ACTIVE_NO_PRIMING = 4,
- eMCB_HSTS_ACTIVE_DO_PRIMING = 5
-};
-
// Record information on when HSTS would have made mixed content not mixed
// content (regardless of whether it was actually blocked)
void
-nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive, bool aHasHSTSPriming)
+nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive)
{
// This method must only be called in the parent, because
// nsSiteSecurityService is only available in the parent
@@ -1089,108 +1001,26 @@ nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive, bo
return;
}
- // states: would upgrade, would prime, hsts info cached
+ // states: would upgrade, hsts info cached
// active, passive
//
if (!aActive) {
if (!hsts) {
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
MCB_HSTS_PASSIVE_NO_HSTS);
- if (aHasHSTSPriming) {
- Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
- eMCB_HSTS_PASSIVE_DO_PRIMING);
- } else {
- Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
- eMCB_HSTS_PASSIVE_NO_PRIMING);
- }
}
else {
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
MCB_HSTS_PASSIVE_WITH_HSTS);
- Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
- eMCB_HSTS_PASSIVE_WITH_HSTS);
}
} else {
if (!hsts) {
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
MCB_HSTS_ACTIVE_NO_HSTS);
- if (aHasHSTSPriming) {
- Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
- eMCB_HSTS_ACTIVE_DO_PRIMING);
- } else {
- Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
- eMCB_HSTS_ACTIVE_NO_PRIMING);
- }
}
else {
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
MCB_HSTS_ACTIVE_WITH_HSTS);
- Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
- eMCB_HSTS_ACTIVE_WITH_HSTS);
}
}
-}
-
-//static
-nsresult
-nsMixedContentBlocker::MarkLoadInfoForPriming(nsIURI* aURI,
- nsISupports* aRequestingContext,
- nsILoadInfo* aLoadInfo)
-{
- nsresult rv;
- bool sendPriming = false;
- bool mixedContentWouldBlock = false;
- rv = GetHSTSPrimingFromRequestingContext(aURI,
- aRequestingContext,
- &sendPriming,
- &mixedContentWouldBlock);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (sendPriming) {
- aLoadInfo->SetHSTSPriming(mixedContentWouldBlock);
- }
-
- return NS_OK;
-}
-
-//static
-nsresult
-nsMixedContentBlocker::GetHSTSPrimingFromRequestingContext(nsIURI* aURI,
- nsISupports* aRequestingContext,
- bool* aSendPrimingRequest,
- bool* aMixedContentWouldBlock)
-{
- *aSendPrimingRequest = false;
- *aMixedContentWouldBlock = false;
- // If we marked for priming, we used the innermost URI, so get that
- nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
- if (!innerURI) {
- NS_ERROR("Can't get innerURI from aContentLocation");
- return NS_ERROR_CONTENT_BLOCKED;
- }
-
- bool isHttp = false;
- innerURI->SchemeIs("http", &isHttp);
- if (!isHttp) {
- // there is nothign to do
- return NS_OK;
- }
-
- // If the DocShell was marked for HSTS priming, propagate that to the LoadInfo
- nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
- if (!docShell) {
- return NS_OK;
- }
- nsCOMPtr<nsIDocument> document = docShell->GetDocument();
- if (!document) {
- return NS_OK;
- }
-
- HSTSPrimingState status = document->GetHSTSPrimingStateForLocation(innerURI);
- if (status != HSTSPrimingState::eNO_HSTS_PRIMING) {
- *aSendPrimingRequest = (status != HSTSPrimingState::eNO_HSTS_PRIMING);
- *aMixedContentWouldBlock = (status == HSTSPrimingState::eHSTS_PRIMING_BLOCK);
- }
-
- return NS_OK;
-}
+} \ No newline at end of file
diff --git a/dom/security/nsMixedContentBlocker.h b/dom/security/nsMixedContentBlocker.h
index 539c3ebbb..56ab9621f 100644
--- a/dom/security/nsMixedContentBlocker.h
+++ b/dom/security/nsMixedContentBlocker.h
@@ -62,44 +62,11 @@ public:
nsIPrincipal* aRequestPrincipal,
int16_t* aDecision);
static void AccumulateMixedContentHSTS(nsIURI* aURI,
- bool aActive,
- bool aHasHSTSPriming);
- /* If the document associated with aRequestingContext requires priming for
- * aURI, propagate that to the LoadInfo so the HttpChannel will find out about
- * it.
- *
- * @param aURI The URI associated with the load
- * @param aRequestingContext the requesting context passed to ShouldLoad
- * @param aLoadInfo the LoadInfo for the load
- */
- static nsresult MarkLoadInfoForPriming(nsIURI* aURI,
- nsISupports* aRequestingContext,
- nsILoadInfo* aLoadInfo);
-
- /* Given a context, return whether HSTS was marked on the document associated
- * with the load for the given URI. This is used by MarkLoadInfoForPriming and
- * directly by the image loader to determine whether to allow a load to occur
- * from the cache.
- *
- * @param aURI The URI associated with the load
- * @param aRequestingContext the requesting context passed to ShouldLoad
- * @param aSendPrimingRequest out true if priming is required on the channel
- * @param aMixedContentWouldBlock out true if mixed content would block
- */
- static nsresult GetHSTSPrimingFromRequestingContext(nsIURI* aURI,
- nsISupports* aRequestingContext,
- bool* aSendPrimingRequest,
- bool* aMixedContentWouldBlock);
+ bool aActive);
static bool sBlockMixedScript;
static bool sBlockMixedDisplay;
- // Do we move HSTS before mixed-content
- static bool sUseHSTS;
- // Do we send an HSTS priming request
- static bool sSendHSTSPriming;
- // Default HSTS Priming failure timeout in seconds
- static uint32_t sHSTSPrimingCacheTimeout;
};
#endif /* nsMixedContentBlocker_h___ */
diff --git a/dom/security/test/csp/file_frame_ancestors_ro.html b/dom/security/test/csp/file_frame_ancestors_ro.html
new file mode 100644
index 000000000..ff5ae9cf9
--- /dev/null
+++ b/dom/security/test/csp/file_frame_ancestors_ro.html
@@ -0,0 +1 @@
+<html><body>Child Document</body></html>
diff --git a/dom/security/test/csp/file_frame_ancestors_ro.html^headers^ b/dom/security/test/csp/file_frame_ancestors_ro.html^headers^
new file mode 100644
index 000000000..d018af3a9
--- /dev/null
+++ b/dom/security/test/csp/file_frame_ancestors_ro.html^headers^
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: frame-ancestors 'none'; report-uri http://mochi.test:8888/foo.sjs
diff --git a/dom/security/test/csp/file_nonce_redirector.sjs b/dom/security/test/csp/file_nonce_redirector.sjs
new file mode 100644
index 000000000..21a8f4e9c
--- /dev/null
+++ b/dom/security/test/csp/file_nonce_redirector.sjs
@@ -0,0 +1,25 @@
+// custom *.sjs file for
+// Bug 1469150:Scripts with valid nonce get blocked if URL redirects.
+
+const URL_PATH = "example.com/tests/dom/security/test/csp/";
+
+function handleRequest(request, response) {
+ response.setHeader("Cache-Control", "no-cache", false);
+ let queryStr = request.queryString;
+
+ if (queryStr === "redirect") {
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location",
+ "https://" + URL_PATH + "file_nonce_redirector.sjs?load", false);
+ return;
+ }
+
+ if (queryStr === "load") {
+ response.setHeader("Content-Type", "application/javascript", false);
+ response.write("console.log('script loaded');");
+ return;
+ }
+
+ // we should never get here - return something unexpected
+ response.write("d'oh");
+}
diff --git a/dom/security/test/csp/file_nonce_redirects.html b/dom/security/test/csp/file_nonce_redirects.html
new file mode 100644
index 000000000..e29116490
--- /dev/null
+++ b/dom/security/test/csp/file_nonce_redirects.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-abcd1234'">
+ <title>Bug 1469150:Scripts with valid nonce get blocked if URL redirects</title>
+ </head>
+<body>
+
+<script nonce='abcd1234' id='redirectScript'></script>
+
+<script nonce='abcd1234' type='application/javascript'>
+ var redirectScript = document.getElementById('redirectScript');
+ redirectScript.onload = function(e) {
+ window.parent.postMessage({result: 'script-loaded'}, '*');
+ };
+ redirectScript.onerror = function(e) {
+ window.parent.postMessage({result: 'script-blocked'}, '*');
+ }
+ redirectScript.src = 'file_nonce_redirector.sjs?redirect';
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini
index ca5c2c6ea..86b7fd0cd 100644
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -88,9 +88,13 @@ support-files =
file_shouldprocess.html
file_nonce_source.html
file_nonce_source.html^headers^
+ file_nonce_redirects.html
+ file_nonce_redirector.sjs
file_bug941404.html
file_bug941404_xhr.html
file_bug941404_xhr.html^headers^
+ file_frame_ancestors_ro.html
+ file_frame_ancestors_ro.html^headers^
file_hash_source.html
file_dual_header_testserver.sjs
file_hash_source.html^headers^
@@ -240,8 +244,10 @@ skip-if = toolkit == 'android' # Times out, not sure why (bug 1008445)
[test_bug910139.html]
[test_bug909029.html]
[test_bug1229639.html]
+[test_frame_ancestors_ro.html]
[test_policyuri_regression_from_multipolicy.html]
[test_nonce_source.html]
+[test_nonce_redirects.html]
[test_bug941404.html]
[test_form-action.html]
[test_hash_source.html]
diff --git a/dom/security/test/csp/test_frame_ancestors_ro.html b/dom/security/test/csp/test_frame_ancestors_ro.html
new file mode 100644
index 000000000..90f68e25e
--- /dev/null
+++ b/dom/security/test/csp/test_frame_ancestors_ro.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for frame-ancestors support in Content-Security-Policy-Report-Only</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width: 100%" id="cspframe"></iframe>
+<script type="text/javascript">
+const docUri = "http://mochi.test:8888/tests/dom/security/test/csp/file_frame_ancestors_ro.html";
+const frame = document.getElementById("cspframe");
+
+let testResults = {
+ reportFired: false,
+ frameLoaded: false
+};
+
+function checkResults(reportObj) {
+ let cspReport = reportObj["csp-report"];
+ is(cspReport["document-uri"], docUri, "Incorrect document-uri");
+
+ // we can not test for the whole referrer since it includes platform specific information
+ is(cspReport["referrer"], document.location.toString(), "Incorrect referrer");
+ is(cspReport["blocked-uri"], document.location.toString(), "Incorrect blocked-uri");
+ is(cspReport["violated-directive"], "frame-ancestors 'none'", "Incorrect violated-directive");
+ is(cspReport["original-policy"], "frame-ancestors 'none'; report-uri http://mochi.test:8888/foo.sjs", "Incorrect original-policy");
+ testResults.reportFired = true;
+}
+
+let chromeScriptUrl = SimpleTest.getTestFileURL("file_report_chromescript.js");
+let script = SpecialPowers.loadChromeScript(chromeScriptUrl);
+
+script.addMessageListener('opening-request-completed', function ml(msg) {
+ if (msg.error) {
+ ok(false, "Could not query report (exception: " + msg.error + ")");
+ } else {
+ try {
+ let reportObj = JSON.parse(msg.report);
+ // test for the proper values in the report object
+ checkResults(reportObj);
+ } catch (e) {
+ ok(false, "Error verifying report object (exception: " + e + ")");
+ }
+ }
+
+ script.removeMessageListener('opening-request-completed', ml);
+ script.sendAsyncMessage("finish");
+ checkTestResults();
+});
+
+frame.addEventListener( 'load', () => {
+ // Make sure the frame is still loaded
+ testResults.frameLoaded = true;
+ checkTestResults()
+} );
+
+function checkTestResults() {
+ if( testResults.reportFired && testResults.frameLoaded ) {
+ SimpleTest.finish();
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+frame.src = docUri;
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/test_nonce_redirects.html b/dom/security/test/csp/test_nonce_redirects.html
new file mode 100644
index 000000000..f84fdcc7b
--- /dev/null
+++ b/dom/security/test/csp/test_nonce_redirects.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1469150:Scripts with valid nonce get blocked if URL redirects</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ * We load a script with a matching nonce, which redirects
+ * and we make sure that script is allowed.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+function finishTest() {
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+}
+
+function checkResults(aResult) {
+
+ if (aResult === "script-loaded") {
+ ok(true, "expected result: script loaded");
+ }
+ else {
+ ok(false, "unexpected result: script blocked");
+ }
+ finishTest();
+}
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ checkResults(event.data.result);
+}
+
+document.getElementById("testframe").src = "file_nonce_redirects.html";
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/csp/test_referrerdirective.html b/dom/security/test/csp/test_referrerdirective.html
index 770fcc40b..f590460a0 100644
--- a/dom/security/test/csp/test_referrerdirective.html
+++ b/dom/security/test/csp/test_referrerdirective.html
@@ -116,8 +116,6 @@ SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
'set': [['security.mixed_content.block_active_content', false],
['security.mixed_content.block_display_content', false],
- ['security.mixed_content.send_hsts_priming', false],
- ['security.mixed_content.use_hsts', false],
]
},
function() {
diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini
new file mode 100644
index 000000000..b00baa95d
--- /dev/null
+++ b/dom/security/test/general/browser.ini
@@ -0,0 +1,14 @@
+[DEFAULT]
+[browser_test_toplevel_data_navigations.js]
+support-files =
+ file_toplevel_data_navigations.sjs
+ file_toplevel_data_meta_redirect.html
+[browser_test_data_download.js]
+support-files =
+ file_data_download.html
+[browser_test_data_text_csv.js]
+support-files =
+ file_data_text_csv.html
+[browser_test_view_image_data_navigation.js]
+support-files =
+ file_view_image_data_navigation.html
diff --git a/dom/security/test/general/browser_test_data_download.js b/dom/security/test/general/browser_test_data_download.js
new file mode 100644
index 000000000..1ee8d5844
--- /dev/null
+++ b/dom/security/test/general/browser_test_data_download.js
@@ -0,0 +1,37 @@
+"use strict";
+
+const kTestPath = getRootDirectory(gTestPath)
+ .replace("chrome://mochitests/content", "http://example.com")
+const kTestURI = kTestPath + "file_data_download.html";
+
+function addWindowListener(aURL, aCallback) {
+ Services.wm.addListener({
+ onOpenWindow(aXULWindow) {
+ info("window opened, waiting for focus");
+ Services.wm.removeListener(this);
+ var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow);
+ waitForFocus(function() {
+ is(domwindow.document.location.href, aURL, "should have seen the right window open");
+ aCallback(domwindow);
+ }, domwindow);
+ },
+ onCloseWindow(aXULWindow) { },
+ onWindowTitleChange(aXULWindow, aNewTitle) { }
+ });
+}
+
+function test() {
+ waitForExplicitFinish();
+ Services.prefs.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true);
+ registerCleanupFunction(function() {
+ Services.prefs.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations");
+ });
+ addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function(win) {
+ is(win.document.getElementById("location").value, "data-foo.html",
+ "file name of download should match");
+ win.close();
+ finish();
+ });
+ gBrowser.loadURI(kTestURI);
+}
diff --git a/dom/security/test/general/browser_test_data_text_csv.js b/dom/security/test/general/browser_test_data_text_csv.js
new file mode 100644
index 000000000..c45e40cc2
--- /dev/null
+++ b/dom/security/test/general/browser_test_data_text_csv.js
@@ -0,0 +1,37 @@
+"use strict";
+
+const kTestPath = getRootDirectory(gTestPath)
+ .replace("chrome://mochitests/content", "http://example.com")
+const kTestURI = kTestPath + "file_data_text_csv.html";
+
+function addWindowListener(aURL, aCallback) {
+ Services.wm.addListener({
+ onOpenWindow(aXULWindow) {
+ info("window opened, waiting for focus");
+ Services.wm.removeListener(this);
+ var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow);
+ waitForFocus(function() {
+ is(domwindow.document.location.href, aURL, "should have seen the right window open");
+ aCallback(domwindow);
+ }, domwindow);
+ },
+ onCloseWindow(aXULWindow) { },
+ onWindowTitleChange(aXULWindow, aNewTitle) { }
+ });
+}
+
+function test() {
+ waitForExplicitFinish();
+ Services.prefs.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true);
+ registerCleanupFunction(function() {
+ Services.prefs.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations");
+ });
+ addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function(win) {
+ is(win.document.getElementById("location").value, "text/csv;foo,bar,foobar",
+ "file name of download should match");
+ win.close();
+ finish();
+ });
+ gBrowser.loadURI(kTestURI);
+}
diff --git a/dom/security/test/general/browser_test_toplevel_data_navigations.js b/dom/security/test/general/browser_test_toplevel_data_navigations.js
new file mode 100644
index 000000000..a13a6350e
--- /dev/null
+++ b/dom/security/test/general/browser_test_toplevel_data_navigations.js
@@ -0,0 +1,54 @@
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
+
+"use strict";
+
+const kDataBody = "toplevel navigation to data: URI allowed";
+const kDataURI = "data:text/html,<body>" + kDataBody + "</body>";
+const kTestPath = getRootDirectory(gTestPath)
+ .replace("chrome://mochitests/content", "http://example.com")
+const kRedirectURI = kTestPath + "file_toplevel_data_navigations.sjs";
+const kMetaRedirectURI = kTestPath + "file_toplevel_data_meta_redirect.html";
+
+add_task(async function test_nav_data_uri() {
+ await SpecialPowers.pushPrefEnv({
+ "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]],
+ });
+ await BrowserTestUtils.withNewTab(kDataURI, async function(browser) {
+ await ContentTask.spawn(gBrowser.selectedBrowser, {kDataBody}, async function({kDataBody}) { // eslint-disable-line
+ is(content.document.body.innerHTML, kDataBody,
+ "data: URI navigation from system should be allowed");
+ });
+ });
+});
+
+add_task(async function test_nav_data_uri_redirect() {
+ await SpecialPowers.pushPrefEnv({
+ "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]],
+ });
+ let tab = BrowserTestUtils.addTab(gBrowser, kRedirectURI);
+ registerCleanupFunction(async function() {
+ await BrowserTestUtils.removeTab(tab);
+ });
+ // wait to make sure data: URI did not load before checking that it got blocked
+ await new Promise(resolve => setTimeout(resolve, 500));
+ await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
+ is(content.document.body.innerHTML, "",
+ "data: URI navigation after server redirect should be blocked");
+ });
+});
+
+add_task(async function test_nav_data_uri_meta_redirect() {
+ await SpecialPowers.pushPrefEnv({
+ "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]],
+ });
+ let tab = BrowserTestUtils.addTab(gBrowser, kMetaRedirectURI);
+ registerCleanupFunction(async function() {
+ await BrowserTestUtils.removeTab(tab);
+ });
+ // wait to make sure data: URI did not load before checking that it got blocked
+ await new Promise(resolve => setTimeout(resolve, 500));
+ await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
+ is(content.document.body.innerHTML, "",
+ "data: URI navigation after meta redirect should be blocked");
+ });
+});
diff --git a/dom/security/test/general/browser_test_view_image_data_navigation.js b/dom/security/test/general/browser_test_view_image_data_navigation.js
new file mode 100644
index 000000000..22de35894
--- /dev/null
+++ b/dom/security/test/general/browser_test_view_image_data_navigation.js
@@ -0,0 +1,30 @@
+"use strict";
+
+const TEST_PAGE = getRootDirectory(gTestPath) + "file_view_image_data_navigation.html";
+
+add_task(async function test_principal_right_click_open_link_in_new_tab() {
+ await SpecialPowers.pushPrefEnv({
+ "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]],
+ });
+
+ await BrowserTestUtils.withNewTab(TEST_PAGE, async function(browser) {
+ let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, true);
+
+ // simulate right-click->view-image
+ BrowserTestUtils.waitForEvent(document, "popupshown", false, event => {
+ // These are operations that must be executed synchronously with the event.
+ document.getElementById("context-viewimage").doCommand();
+ event.target.hidePopup();
+ return true;
+ });
+ BrowserTestUtils.synthesizeMouseAtCenter("#testimage",
+ { type: "contextmenu", button: 2 },
+ gBrowser.selectedBrowser);
+ await loadPromise;
+
+ await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
+ ok(content.document.location.toString().startsWith("data:image/svg+xml;"),
+ "data:image/svg navigation allowed through right-click view-image")
+ });
+ });
+});
diff --git a/dom/security/test/general/file_block_toplevel_data_navigation.html b/dom/security/test/general/file_block_toplevel_data_navigation.html
new file mode 100644
index 000000000..5fbfdfdef
--- /dev/null
+++ b/dom/security/test/general/file_block_toplevel_data_navigation.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Toplevel data navigation</title>
+</head>
+<body>
+test1: clicking data: URI tries to navigate window<br/>
+<a id="testlink" href="data:text/html,<body>toplevel data: URI navigations should be blocked</body>">click me</a>
+<script>
+ document.getElementById('testlink').click();
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/file_block_toplevel_data_navigation2.html b/dom/security/test/general/file_block_toplevel_data_navigation2.html
new file mode 100644
index 000000000..e0308e1ae
--- /dev/null
+++ b/dom/security/test/general/file_block_toplevel_data_navigation2.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Toplevel data navigation</title>
+</head>
+<body>
+test2: data: URI in iframe tries to window.open(data:, _blank);<br/>
+<iframe id="testFrame" src=""></iframe>
+<script>
+ let DATA_URI = `data:text/html,<body><script>
+ var win = window.open("data:text/html,<body>toplevel data: URI navigations should be blocked</body>", "_blank");
+ setTimeout(function () {
+ var result = win.document.body.innerHTML === "" ? "blocked" : "navigated";
+ parent.postMessage(result, "*");
+ win.close();
+ }, 1000);
+ <\/script></body>`;
+
+ window.addEventListener("message", receiveMessage);
+ function receiveMessage(event) {
+ window.removeEventListener("message", receiveMessage);
+ // propagate the information back to the caller
+ window.opener.postMessage(event.data, "*");
+ }
+ document.getElementById('testFrame').src = DATA_URI;
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/file_block_toplevel_data_navigation3.html b/dom/security/test/general/file_block_toplevel_data_navigation3.html
new file mode 100644
index 000000000..34aeddab3
--- /dev/null
+++ b/dom/security/test/general/file_block_toplevel_data_navigation3.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Toplevel data navigation</title>
+</head>
+<body>
+test3: performing data: URI navigation through win.loc.href<br/>
+<script>
+ window.location.href = "data:text/html,<body>toplevel data: URI navigations should be blocked</body>";
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/file_block_toplevel_data_redirect.sjs b/dom/security/test/general/file_block_toplevel_data_redirect.sjs
new file mode 100644
index 000000000..64e294cab
--- /dev/null
+++ b/dom/security/test/general/file_block_toplevel_data_redirect.sjs
@@ -0,0 +1,14 @@
+// Custom *.sjs file specifically for the needs of Bug:
+// Bug 1394554 - Block toplevel data: URI navigations after redirect
+
+var DATA_URI =
+ "<body>toplevel data: URI navigations after redirect should be blocked</body>";
+
+function handleRequest(request, response)
+{
+ // avoid confusing cache behaviors
+ response.setHeader("Cache-Control", "no-cache", false);
+
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location", "data:text/html," + escape(DATA_URI), false);
+}
diff --git a/dom/security/test/general/file_data_download.html b/dom/security/test/general/file_data_download.html
new file mode 100644
index 000000000..4cc92fe8f
--- /dev/null
+++ b/dom/security/test/general/file_data_download.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test download attribute for data: URI</title>
+</head>
+<body>
+ <a href="data:text/html,<body>data download</body>" download="data-foo.html" id="testlink">download data</a>
+ <script>
+ // click the link to have the downoad panel appear
+ let testlink = document.getElementById("testlink");
+ testlink.click();
+ </script>
+ </body>
+</html>
diff --git a/dom/security/test/general/file_data_text_csv.html b/dom/security/test/general/file_data_text_csv.html
new file mode 100644
index 000000000..a9ac369d1
--- /dev/null
+++ b/dom/security/test/general/file_data_text_csv.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test open data:text/csv</title>
+</head>
+<body>
+ <a href="data:text/csv;foo,bar,foobar" id="testlink">test text/csv</a>
+ <script>
+ // click the link to have the downoad panel appear
+ let testlink = document.getElementById("testlink");
+ testlink.click();
+ </script>
+ </body>
+</html>
diff --git a/dom/security/test/general/file_toplevel_data_meta_redirect.html b/dom/security/test/general/file_toplevel_data_meta_redirect.html
new file mode 100644
index 000000000..f4f5deb52
--- /dev/null
+++ b/dom/security/test/general/file_toplevel_data_meta_redirect.html
@@ -0,0 +1,10 @@
+<html>
+<body>
+<head>
+ <meta http-equiv="refresh"
+ content="0; url='data:text/html,<body>toplevel meta redirect to data: URI should be blocked</body>'">
+</head>
+<body>
+Meta Redirect to data: URI
+</body>
+</html>
diff --git a/dom/security/test/general/file_toplevel_data_navigations.sjs b/dom/security/test/general/file_toplevel_data_navigations.sjs
new file mode 100644
index 000000000..501b833e5
--- /dev/null
+++ b/dom/security/test/general/file_toplevel_data_navigations.sjs
@@ -0,0 +1,14 @@
+// Custom *.sjs file specifically for the needs of Bug:
+// Bug 1394554 - Block toplevel data: URI navigations after redirect
+
+var DATA_URI =
+ "data:text/html,<body>toplevel data: URI navigations after redirect should be blocked</body>";
+
+function handleRequest(request, response)
+{
+ // avoid confusing cache behaviors
+ response.setHeader("Cache-Control", "no-cache", false);
+
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location", DATA_URI, false);
+}
diff --git a/dom/security/test/general/file_view_image_data_navigation.html b/dom/security/test/general/file_view_image_data_navigation.html
new file mode 100644
index 000000000..a3f9acfb4
--- /dev/null
+++ b/dom/security/test/general/file_view_image_data_navigation.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1407891: Test navigation for right-click view-image on data:image/svg</title>
+</head>
+<body>
+
+<img id="testimage" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg=="></img>
+
+</body>
+</html>
diff --git a/dom/security/test/general/mochitest.ini b/dom/security/test/general/mochitest.ini
index 70c0c9fb6..f3bcca072 100644
--- a/dom/security/test/general/mochitest.ini
+++ b/dom/security/test/general/mochitest.ini
@@ -3,7 +3,19 @@ support-files =
file_contentpolicytype_targeted_link_iframe.sjs
file_nosniff_testserver.sjs
file_block_script_wrong_mime_server.sjs
+ file_block_toplevel_data_navigation.html
+ file_block_toplevel_data_navigation2.html
+ file_block_toplevel_data_navigation3.html
+ file_block_toplevel_data_redirect.sjs
[test_contentpolicytype_targeted_link_iframe.html]
[test_nosniff.html]
[test_block_script_wrong_mime.html]
+[test_block_toplevel_data_navigation.html]
+skip-if = toolkit == 'android' # intermittent failure
+[test_block_toplevel_data_img_navigation.html]
+skip-if = toolkit == 'android' # intermittent failure
+[test_allow_opening_data_pdf.html]
+skip-if = toolkit == 'android'
+[test_allow_opening_data_json.html]
+skip-if = toolkit == 'android'
diff --git a/dom/security/test/general/test_allow_opening_data_json.html b/dom/security/test/general/test_allow_opening_data_json.html
new file mode 100644
index 000000000..1530a24e8
--- /dev/null
+++ b/dom/security/test/general/test_allow_opening_data_json.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1403814: Allow toplevel data URI navigation data:application/json</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function test_toplevel_data_json() {
+ const DATA_JSON = "data:application/json,{'my_json_key':'my_json_value'}";
+
+ let win = window.open(DATA_JSON);
+ let wrappedWin = SpecialPowers.wrap(win);
+
+ // Unfortunately we can't detect whether the JSON has loaded or not using some
+ // event, hence we are constantly polling location.href till we see that
+ // the data: URI appears. Test times out on failure.
+ var jsonLoaded = setInterval(function() {
+ if (wrappedWin.document.location.href.startsWith("data:application/json")) {
+ clearInterval(jsonLoaded);
+ ok(true, "navigating to data:application/json allowed");
+ wrappedWin.close();
+ SimpleTest.finish();
+ }
+ }, 200);
+}
+
+SpecialPowers.pushPrefEnv({
+ set: [["security.data_uri.block_toplevel_data_uri_navigations", true]]
+}, test_toplevel_data_json);
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/test_allow_opening_data_pdf.html b/dom/security/test/general/test_allow_opening_data_pdf.html
new file mode 100644
index 000000000..6b51fe57b
--- /dev/null
+++ b/dom/security/test/general/test_allow_opening_data_pdf.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1398692: Allow toplevel navigation to a data:application/pdf</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function test_toplevel_data_pdf() {
+ // The PDF contains one page and it is a 3/72" square, the minimum allowed by the spec
+ const DATA_PDF =
+ "data:application/pdf;base64,JVBERi0xLjANCjEgMCBvYmo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFI+PmVuZG9iaiAyIDAgb2JqPDwvVHlwZS9QYWdlcy9LaWRzWzMgMCBSXS9Db3VudCAxPj5lbmRvYmogMyAwIG9iajw8L1R5cGUvUGFnZS9NZWRpYUJveFswIDAgMyAzXT4+ZW5kb2JqDQp4cmVmDQowIDQNCjAwMDAwMDAwMDAgNjU1MzUgZg0KMDAwMDAwMDAxMCAwMDAwMCBuDQowMDAwMDAwMDUzIDAwMDAwIG4NCjAwMDAwMDAxMDIgMDAwMDAgbg0KdHJhaWxlcjw8L1NpemUgNC9Sb290IDEgMCBSPj4NCnN0YXJ0eHJlZg0KMTQ5DQolRU9G";
+
+ let win = window.open(DATA_PDF);
+ let wrappedWin = SpecialPowers.wrap(win);
+
+ // Unfortunately we can't detect whether the PDF has loaded or not using some
+ // event, hence we are constantly polling location.href till we see that
+ // the data: URI appears. Test times out on failure.
+ var pdfLoaded = setInterval(function() {
+ if (wrappedWin.document.location.href.startsWith("data:application/pdf")) {
+ clearInterval(pdfLoaded);
+ ok(true, "navigating to data:application/pdf allowed");
+ wrappedWin.close();
+ SimpleTest.finish();
+ }
+ }, 200);
+}
+
+SpecialPowers.pushPrefEnv({
+ set: [["security.data_uri.block_toplevel_data_uri_navigations", true]]
+}, test_toplevel_data_pdf);
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/test_block_toplevel_data_img_navigation.html b/dom/security/test/general/test_block_toplevel_data_img_navigation.html
new file mode 100644
index 000000000..7f8dfc748
--- /dev/null
+++ b/dom/security/test/general/test_block_toplevel_data_img_navigation.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1396798: Do not block toplevel data: navigation to image (except svgs)</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+SpecialPowers.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true);
+SimpleTest.registerCleanupFunction(() => {
+ SpecialPowers.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations");
+});
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("have to test that top level data:image loading is blocked/allowed");
+
+function test_toplevel_data_image() {
+ const DATA_PNG =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
+ let win1 = window.open(DATA_PNG);
+ let wrappedWin1 = SpecialPowers.wrap(win1);
+ setTimeout(function () {
+ let images = wrappedWin1.document.getElementsByTagName('img');
+ is(images.length, 1, "Loading data:image/png should be allowed");
+ is(images[0].src, DATA_PNG, "Sanity: img src matches");
+ wrappedWin1.close();
+ test_toplevel_data_image_svg();
+ }, 1000);
+}
+
+function test_toplevel_data_image_svg() {
+ const DATA_SVG =
+ "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==";
+ let win2 = window.open(DATA_SVG);
+ // Unfortunately we can't detect whether the window was closed using some event,
+ // hence we are constantly polling till we see that win == null.
+ // Test times out on failure.
+ var win2Closed = setInterval(function() {
+ if (win2 == null || win2.closed) {
+ clearInterval(win2Closed);
+ ok(true, "Loading data:image/svg+xml should be blocked");
+ SimpleTest.finish();
+ }
+ }, 200);
+}
+// fire up the tests
+test_toplevel_data_image();
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/test_block_toplevel_data_navigation.html b/dom/security/test/general/test_block_toplevel_data_navigation.html
new file mode 100644
index 000000000..cef232b65
--- /dev/null
+++ b/dom/security/test/general/test_block_toplevel_data_navigation.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1331351 - Block top level window data: URI navigations</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+SpecialPowers.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true);
+SimpleTest.registerCleanupFunction(() => {
+ SpecialPowers.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations");
+});
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("have to test that top level data: URI navgiation is blocked");
+
+function test1() {
+ // simple data: URI click navigation should be prevented
+ let TEST_FILE = "file_block_toplevel_data_navigation.html";
+ let win1 = window.open(TEST_FILE);
+ setTimeout(function () {
+ ok(SpecialPowers.wrap(win1).document.body.innerHTML.indexOf("test1:") !== -1,
+ "toplevel data: URI navigation through click() should be blocked");
+ win1.close();
+ test2();
+ }, 1000);
+}
+
+function test2() {
+ // data: URI in iframe which opens data: URI in _blank should be blocked
+ let win2 = window.open("file_block_toplevel_data_navigation2.html");
+ window.addEventListener("message", receiveMessage);
+ function receiveMessage(event) {
+ window.removeEventListener("message", receiveMessage);
+ is(event.data, "blocked",
+ "data: URI navigation using _blank from data: URI should be blocked");
+ win2.close();
+ test3();
+ }
+}
+
+function test3() {
+ // navigating to a data: URI using window.location.href should be blocked
+ let win3 = window.open("file_block_toplevel_data_navigation3.html");
+ setTimeout(function () {
+ ok(win3.document.body.innerHTML.indexOf("test3:") !== -1,
+ "data: URI navigation through win.loc.href should be blocked");
+ win3.close();
+ test4();
+ }, 1000);
+}
+
+function test4() {
+ // navigating to a data: URI using window.open() should be blocked
+ let win4 = window.open("data:text/html,<body>toplevel data: URI navigations should be blocked</body>");
+ setTimeout(function () {
+ // Please note that the data: URI will be displayed in the URL-Bar but not
+ // loaded, hence we rather rely on document.body than document.location
+ is(win4.document.body.innerHTML, "",
+ "navigating to a data: URI using window.open() should be blocked");
+ test5();
+ }, 1000);
+}
+
+function test5() {
+ // navigating to a URI which redirects to a data: URI using window.open() should be blocked
+ let win5 = window.open("file_block_toplevel_data_redirect.sjs");
+ setTimeout(function () {
+ // Please note that the data: URI will be displayed in the URL-Bar but not
+ // loaded, hence we rather rely on document.body than document.location
+ is(SpecialPowers.wrap(win5).document.body.innerHTML, "",
+ "navigating to URI which redirects to a data: URI using window.open() should be blocked");
+ win5.close();
+ SimpleTest.finish();
+ }, 1000);
+}
+
+// fire up the tests
+test1();
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html b/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html
index 7b1ab72dc..3ef243824 100644
--- a/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html
+++ b/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html
@@ -61,6 +61,7 @@ var policy = {
"content policy type should TYPESUBDOCUMENT");
categoryManager.deleteCategoryEntry("content-policy", POLICYNAME, false);
SimpleTest.finish();
+ return Ci.nsIContentPolicy.REJECT_REQUEST;
}
return Ci.nsIContentPolicy.ACCEPT;
},
diff --git a/dom/security/test/hsts/browser.ini b/dom/security/test/hsts/browser.ini
deleted file mode 100644
index ae75031df..000000000
--- a/dom/security/test/hsts/browser.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[DEFAULT]
-skip-if = debug # bug 1311599, bug 1311239, etc
-support-files =
- head.js
- file_priming-top.html
- file_testserver.sjs
- file_1x1.png
- file_priming.js
- file_stylesheet.css
-
-[browser_hsts-priming_allow_active.js]
-[browser_hsts-priming_block_active.js]
-[browser_hsts-priming_hsts_after_mixed.js]
-[browser_hsts-priming_allow_display.js]
-[browser_hsts-priming_block_display.js]
-[browser_hsts-priming_block_active_css.js]
-[browser_hsts-priming_block_active_with_redir_same.js]
-[browser_hsts-priming_no-duplicates.js]
-[browser_hsts-priming_cache-timeout.js]
diff --git a/dom/security/test/hsts/browser_hsts-priming_allow_active.js b/dom/security/test/hsts/browser_hsts-priming_allow_active.js
deleted file mode 100644
index a932b31b3..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_allow_active.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Description of the test:
- * Check that HSTS priming occurs correctly with mixed content when active
- * content is allowed.
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Services.obs.addObserver(Observer, "console-api-log-event", false);
- Services.obs.addObserver(Observer, "http-on-examine-response", false);
- registerCleanupFunction(do_cleanup);
-
- let which = "allow_active";
-
- SetupPrefTestEnvironment(which);
-
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/browser_hsts-priming_allow_display.js b/dom/security/test/hsts/browser_hsts-priming_allow_display.js
deleted file mode 100644
index 06546ca65..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_allow_display.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Description of the test:
- * Check that HSTS priming occurs correctly with mixed content when display
- * content is allowed.
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Services.obs.addObserver(Observer, "console-api-log-event", false);
- Services.obs.addObserver(Observer, "http-on-examine-response", false);
- registerCleanupFunction(do_cleanup);
-
- let which = "allow_display";
-
- SetupPrefTestEnvironment(which);
-
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/browser_hsts-priming_block_active.js b/dom/security/test/hsts/browser_hsts-priming_block_active.js
deleted file mode 100644
index a5478b185..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_block_active.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Description of the test:
- * Check that HSTS priming occurs correctly with mixed content when active
- * content is blocked.
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Services.obs.addObserver(Observer, "console-api-log-event", false);
- Services.obs.addObserver(Observer, "http-on-examine-response", false);
- registerCleanupFunction(do_cleanup);
-
- let which = "block_active";
-
- SetupPrefTestEnvironment(which);
-
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/browser_hsts-priming_block_active_css.js b/dom/security/test/hsts/browser_hsts-priming_block_active_css.js
deleted file mode 100644
index 340d11483..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_block_active_css.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Description of the test:
- * Check that HSTS priming occurs correctly with mixed content when active
- * content is blocked for css.
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Services.obs.addObserver(Observer, "console-api-log-event", false);
- Services.obs.addObserver(Observer, "http-on-examine-response", false);
- registerCleanupFunction(do_cleanup);
-
- let which = "block_active_css";
-
- SetupPrefTestEnvironment(which);
-
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/browser_hsts-priming_block_active_with_redir_same.js b/dom/security/test/hsts/browser_hsts-priming_block_active_with_redir_same.js
deleted file mode 100644
index 130a3d5ec..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_block_active_with_redir_same.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Description of the test:
- * Check that HSTS priming occurs correctly with mixed content when active
- * content is blocked and redirect to the same host should still upgrade.
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Services.obs.addObserver(Observer, "console-api-log-event", false);
- Services.obs.addObserver(Observer, "http-on-examine-response", false);
- registerCleanupFunction(do_cleanup);
-
- let which = "block_active_with_redir_same";
-
- SetupPrefTestEnvironment(which);
-
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/browser_hsts-priming_block_display.js b/dom/security/test/hsts/browser_hsts-priming_block_display.js
deleted file mode 100644
index 4eca62718..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_block_display.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Description of the test:
- * Check that HSTS priming occurs correctly with mixed content when display
- * content is blocked.
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Services.obs.addObserver(Observer, "console-api-log-event", false);
- Services.obs.addObserver(Observer, "http-on-examine-response", false);
- registerCleanupFunction(do_cleanup);
-
- let which = "block_display";
-
- SetupPrefTestEnvironment(which);
-
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/browser_hsts-priming_cache-timeout.js b/dom/security/test/hsts/browser_hsts-priming_cache-timeout.js
deleted file mode 100644
index 5416a71d2..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_cache-timeout.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Description of the test:
- * Test that the network.hsts_priming.cache_timeout preferene causes the cache
- * to timeout
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Observer.add_observers(Services);
- registerCleanupFunction(do_cleanup);
-
- let which = "block_display";
-
- SetupPrefTestEnvironment(which, [["security.mixed_content.hsts_priming_cache_timeout", 1]]);
-
- yield execute_test("no-ssl", test_settings[which].mimetype);
-
- let pre_promise = performance.now();
-
- while ((performance.now() - pre_promise) < 2000) {
- yield new Promise(function (resolve) {
- setTimeout(resolve, 2000);
- });
- }
-
- // clear the fact that we saw a priming request
- test_settings[which].priming = {};
-
- yield execute_test("no-ssl", test_settings[which].mimetype);
- is(test_settings[which].priming["no-ssl"], true,
- "Correctly send a priming request after expiration.");
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/browser_hsts-priming_hsts_after_mixed.js b/dom/security/test/hsts/browser_hsts-priming_hsts_after_mixed.js
deleted file mode 100644
index 89ea6fbeb..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_hsts_after_mixed.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Description of the test:
- * Check that HSTS priming occurs correctly with mixed content when the
- * mixed-content blocks before HSTS.
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Services.obs.addObserver(Observer, "console-api-log-event", false);
- Services.obs.addObserver(Observer, "http-on-examine-response", false);
- registerCleanupFunction(do_cleanup);
-
- let which = "hsts_after_mixed";
-
- SetupPrefTestEnvironment(which);
-
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/browser_hsts-priming_no-duplicates.js b/dom/security/test/hsts/browser_hsts-priming_no-duplicates.js
deleted file mode 100644
index 3846fe4f0..000000000
--- a/dom/security/test/hsts/browser_hsts-priming_no-duplicates.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Description of the test:
- * Only one request should be sent per host, even if we run the test more
- * than once.
- */
-'use strict';
-
-//jscs:disable
-add_task(function*() {
- //jscs:enable
- Observer.add_observers(Services);
- registerCleanupFunction(do_cleanup);
-
- let which = "block_display";
-
- SetupPrefTestEnvironment(which);
-
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- test_settings[which].priming = {};
-
- // run the tests twice to validate the cache is being used
- for (let server of Object.keys(test_servers)) {
- yield execute_test(server, test_settings[which].mimetype);
- }
-
- SpecialPowers.popPrefEnv();
-});
diff --git a/dom/security/test/hsts/file_1x1.png b/dom/security/test/hsts/file_1x1.png
deleted file mode 100644
index 1ba31ba1a..000000000
--- a/dom/security/test/hsts/file_1x1.png
+++ /dev/null
Binary files differ
diff --git a/dom/security/test/hsts/file_priming-top.html b/dom/security/test/hsts/file_priming-top.html
deleted file mode 100644
index b1d1bfa40..000000000
--- a/dom/security/test/hsts/file_priming-top.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <title>Bug 1246540</title>
- <meta http-equiv='content-type' content="text/html;charset=utf-8" />
-</head>
-<body>
- <p id="display"></p>
- <div id="content" style="visibility: hidden">
- </div>
-
-<script type="text/javascript">
-/*
- * Description of the test:
- * Attempt to load an insecure resource. If the resource responds to HSTS
- * priming with an STS header, the load should continue securely.
- * If it does not, the load should continue be blocked or continue insecurely.
- */
-
-function parse_query_string() {
- var q = {};
- document.location.search.substr(1).
- split('&').forEach(function (item, idx, ar) {
- let [k, v] = item.split('=');
- q[k] = unescape(v);
- });
- return q;
-}
-
-var args = parse_query_string();
-
-var subresources = {
- css: { mimetype: 'text/css', file: 'file_stylesheet.css' },
- img: { mimetype: 'image/png', file: 'file_1x1.png' },
- script: { mimetype: 'text/javascript', file: 'file_priming.js' },
-};
-
-function handler(ev) {
- console.log("HSTS_PRIMING: Blocked "+args.id);
-}
-
-function loadCss(src) {
- let head = document.getElementsByTagName("head")[0];
- let link = document.createElement("link");
- link.setAttribute("rel", "stylesheet");
- link.setAttribute("type", subresources[args.type].mimetype);
- link.setAttribute("href", src);
- head.appendChild(link);
-}
-
-function loadResource(src) {
- let content = document.getElementById("content");
- let testElem = document.createElement(args.type);
- testElem.setAttribute("id", args.id);
- testElem.setAttribute("charset", "UTF-8");
- testElem.onerror = handler;
- content.appendChild(testElem);
- testElem.src = src;
-}
-
-function loadTest() {
- let subresource = subresources[args.type];
-
- let src = "http://"
- + args.host
- + "/browser/dom/security/test/hsts/file_testserver.sjs"
- + "?file=" +escape("browser/dom/security/test/hsts/" + subresource.file)
- + "&primer=" + escape(args.id)
- + "&mimetype=" + escape(subresource.mimetype)
- ;
- if (args.type == 'css') {
- loadCss(src);
- return;
- }
-
- loadResource(src);
-}
-
-// start running the tests
-loadTest();
-
-</script>
-</body>
-</html>
diff --git a/dom/security/test/hsts/file_priming.js b/dom/security/test/hsts/file_priming.js
deleted file mode 100644
index 023022da6..000000000
--- a/dom/security/test/hsts/file_priming.js
+++ /dev/null
@@ -1,4 +0,0 @@
-function completed() {
- return;
-}
-completed();
diff --git a/dom/security/test/hsts/file_stylesheet.css b/dom/security/test/hsts/file_stylesheet.css
deleted file mode 100644
index e69de29bb..000000000
--- a/dom/security/test/hsts/file_stylesheet.css
+++ /dev/null
diff --git a/dom/security/test/hsts/file_testserver.sjs b/dom/security/test/hsts/file_testserver.sjs
deleted file mode 100644
index d5cd6b17a..000000000
--- a/dom/security/test/hsts/file_testserver.sjs
+++ /dev/null
@@ -1,66 +0,0 @@
-// SJS file for HSTS mochitests
-
-Components.utils.import("resource://gre/modules/NetUtil.jsm");
-Components.utils.importGlobalProperties(["URLSearchParams"]);
-
-function loadFromFile(path) {
- // Load the HTML to return in the response from file.
- // Since it's relative to the cwd of the test runner, we start there and
- // append to get to the actual path of the file.
- var testFile =
- Components.classes["@mozilla.org/file/directory_service;1"].
- getService(Components.interfaces.nsIProperties).
- get("CurWorkD", Components.interfaces.nsILocalFile);
- var dirs = path.split("/");
- for (var i = 0; i < dirs.length; i++) {
- testFile.append(dirs[i]);
- }
- var testFileStream =
- Components.classes["@mozilla.org/network/file-input-stream;1"].
- createInstance(Components.interfaces.nsIFileInputStream);
- testFileStream.init(testFile, -1, 0, 0);
- var test = NetUtil.readInputStreamToString(testFileStream, testFileStream.available());
- return test;
-}
-
-function handleRequest(request, response)
-{
- const query = new URLSearchParams(request.queryString);
-
- redir = query.get('redir');
- if (redir == 'same') {
- query.delete("redir");
- response.setStatus(302);
- let newURI = request.uri;
- newURI.queryString = query.serialize();
- response.setHeader("Location", newURI.spec)
- }
-
- // avoid confusing cache behaviors
- response.setHeader("Cache-Control", "no-cache", false);
-
- // if we have a priming header, check for required behavior
- // and set header appropriately
- if (request.hasHeader('Upgrade-Insecure-Requests')) {
- var expected = query.get('primer');
- if (expected == 'prime-hsts') {
- // set it for 5 minutes
- response.setHeader("Strict-Transport-Security", "max-age="+(60*5), false);
- } else if (expected == 'reject-upgrade') {
- response.setHeader("Strict-Transport-Security", "max-age=0", false);
- }
- response.write('');
- return;
- }
-
- var file = query.get('file');
- if (file) {
- var mimetype = unescape(query.get('mimetype'));
- response.setHeader("Content-Type", mimetype, false);
- response.write(loadFromFile(unescape(file)));
- return;
- }
-
- response.setHeader("Content-Type", "application/json", false);
- response.write('{}');
-}
diff --git a/dom/security/test/hsts/head.js b/dom/security/test/hsts/head.js
deleted file mode 100644
index 362b36444..000000000
--- a/dom/security/test/hsts/head.js
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Description of the tests:
- * Check that HSTS priming occurs correctly with mixed content
- *
- * This test uses three hostnames, each of which treats an HSTS priming
- * request differently.
- * * no-ssl never returns an ssl response
- * * reject-upgrade returns an ssl response, but with no STS header
- * * prime-hsts returns an ssl response with the appropriate STS header
- *
- * For each server, test that it response appropriately when the we allow
- * or block active or display content, as well as when we send an hsts priming
- * request, but do not change the order of mixed-content and HSTS.
- *
- * Test use http-on-examine-response, so must be run in browser context.
- */
-'use strict';
-
-var TOP_URI = "https://example.com/browser/dom/security/test/hsts/file_priming-top.html";
-
-var test_servers = {
- // a test server that does not support TLS
- 'no-ssl': {
- host: 'example.co.jp',
- response: false,
- id: 'no-ssl',
- },
- // a test server which does not support STS upgrade
- 'reject-upgrade': {
- host: 'example.org',
- response: true,
- id: 'reject-upgrade',
- },
- // a test server when sends an STS header when priming
- 'prime-hsts': {
- host: 'test1.example.com',
- response: true,
- id: 'prime-hsts'
- },
-};
-
-var test_settings = {
- // mixed active content is allowed, priming will upgrade
- allow_active: {
- block_active: false,
- block_display: false,
- use_hsts: true,
- send_hsts_priming: true,
- type: 'script',
- result: {
- 'no-ssl': 'insecure',
- 'reject-upgrade': 'insecure',
- 'prime-hsts': 'secure',
- },
- },
- // mixed active content is blocked, priming will upgrade
- block_active: {
- block_active: true,
- block_display: false,
- use_hsts: true,
- send_hsts_priming: true,
- type: 'script',
- result: {
- 'no-ssl': 'blocked',
- 'reject-upgrade': 'blocked',
- 'prime-hsts': 'secure',
- },
- },
- // keep the original order of mixed-content and HSTS, but send
- // priming requests
- hsts_after_mixed: {
- block_active: true,
- block_display: false,
- use_hsts: false,
- send_hsts_priming: true,
- type: 'script',
- result: {
- 'no-ssl': 'blocked',
- 'reject-upgrade': 'blocked',
- 'prime-hsts': 'blocked',
- },
- },
- // mixed display content is allowed, priming will upgrade
- allow_display: {
- block_active: true,
- block_display: false,
- use_hsts: true,
- send_hsts_priming: true,
- type: 'img',
- result: {
- 'no-ssl': 'insecure',
- 'reject-upgrade': 'insecure',
- 'prime-hsts': 'secure',
- },
- },
- // mixed display content is blocked, priming will upgrade
- block_display: {
- block_active: true,
- block_display: true,
- use_hsts: true,
- send_hsts_priming: true,
- type: 'img',
- result: {
- 'no-ssl': 'blocked',
- 'reject-upgrade': 'blocked',
- 'prime-hsts': 'secure',
- },
- },
- // mixed active content is blocked, priming will upgrade (css)
- block_active_css: {
- block_active: true,
- block_display: false,
- use_hsts: true,
- send_hsts_priming: true,
- type: 'css',
- result: {
- 'no-ssl': 'blocked',
- 'reject-upgrade': 'blocked',
- 'prime-hsts': 'secure',
- },
- },
- // mixed active content is blocked, priming will upgrade
- // redirect to the same host
- block_active_with_redir_same: {
- block_active: true,
- block_display: false,
- use_hsts: true,
- send_hsts_priming: true,
- type: 'script',
- redir: 'same',
- result: {
- 'no-ssl': 'blocked',
- 'reject-upgrade': 'blocked',
- 'prime-hsts': 'secure',
- },
- },
-}
-// track which test we are on
-var which_test = "";
-
-const Observer = {
- observe: function (subject, topic, data) {
- switch (topic) {
- case 'console-api-log-event':
- return Observer.console_api_log_event(subject, topic, data);
- case 'http-on-examine-response':
- return Observer.http_on_examine_response(subject, topic, data);
- case 'http-on-modify-request':
- return Observer.http_on_modify_request(subject, topic, data);
- }
- throw "Can't handle topic "+topic;
- },
- add_observers: function (services) {
- services.obs.addObserver(Observer, "console-api-log-event", false);
- services.obs.addObserver(Observer, "http-on-examine-response", false);
- services.obs.addObserver(Observer, "http-on-modify-request", false);
- },
- // When a load is blocked which results in an error event within a page, the
- // test logs to the console.
- console_api_log_event: function (subject, topic, data) {
- var message = subject.wrappedJSObject.arguments[0];
- // when we are blocked, this will match the message we sent to the console,
- // ignore everything else.
- var re = RegExp(/^HSTS_PRIMING: Blocked ([-\w]+).*$/);
- if (!re.test(message)) {
- return;
- }
-
- let id = message.replace(re, '$1');
- let curTest =test_servers[id];
-
- if (!curTest) {
- ok(false, "HSTS priming got a console message blocked, "+
- "but doesn't match expectations "+id+" (msg="+message);
- return;
- }
-
- is("blocked", test_settings[which_test].result[curTest.id], "HSTS priming "+
- which_test+":"+curTest.id+" expected "+
- test_settings[which_test].result[curTest.id]+", got blocked");
- test_settings[which_test].finished[curTest.id] = "blocked";
- },
- get_current_test: function(uri) {
- for (let item in test_servers) {
- let re = RegExp('https?://'+test_servers[item].host);
- if (re.test(uri)) {
- return test_servers[item];
- }
- }
- return null;
- },
- http_on_modify_request: function (subject, topic, data) {
- let channel = subject.QueryInterface(Ci.nsIHttpChannel);
- if (channel.requestMethod != 'HEAD') {
- return;
- }
-
- let curTest = this.get_current_test(channel.URI.asciiSpec);
-
- if (!curTest) {
- return;
- }
-
- ok(!(curTest.id in test_settings[which_test].priming), "Already saw a priming request for " + curTest.id);
- test_settings[which_test].priming[curTest.id] = true;
- },
- // When we see a response come back, peek at the response and test it is secure
- // or insecure as needed. Addtionally, watch the response for priming requests.
- http_on_examine_response: function (subject, topic, data) {
- let channel = subject.QueryInterface(Ci.nsIHttpChannel);
- let curTest = this.get_current_test(channel.URI.asciiSpec);
-
- if (!curTest) {
- return;
- }
-
- let result = (channel.URI.asciiSpec.startsWith('https:')) ? "secure" : "insecure";
-
- // This is a priming request, go ahead and validate we were supposed to see
- // a response from the server
- if (channel.requestMethod == 'HEAD') {
- is(true, curTest.response, "HSTS priming response found " + curTest.id);
- return;
- }
-
- // This is the response to our query, make sure it matches
- is(result, test_settings[which_test].result[curTest.id],
- "HSTS priming result " + which_test + ":" + curTest.id);
- test_settings[which_test].finished[curTest.id] = result;
- },
-};
-
-// opens `uri' in a new tab and focuses it.
-// returns the newly opened tab
-function openTab(uri) {
- let tab = gBrowser.addTab(uri);
-
- // select tab and make sure its browser is focused
- gBrowser.selectedTab = tab;
- tab.ownerDocument.defaultView.focus();
-
- return tab;
-}
-
-function clear_sts_data() {
- for (let test in test_servers) {
- SpecialPowers.cleanUpSTSData('http://'+test_servers[test].host);
- }
-}
-
-function do_cleanup() {
- clear_sts_data();
-
- Services.obs.removeObserver(Observer, "console-api-log-event");
- Services.obs.removeObserver(Observer, "http-on-examine-response");
-}
-
-function SetupPrefTestEnvironment(which, additional_prefs) {
- which_test = which;
- clear_sts_data();
-
- var settings = test_settings[which];
- // priming counts how many priming requests we saw
- settings.priming = {};
- // priming counts how many tests were finished
- settings.finished= {};
-
- var prefs = [["security.mixed_content.block_active_content",
- settings.block_active],
- ["security.mixed_content.block_display_content",
- settings.block_display],
- ["security.mixed_content.use_hsts",
- settings.use_hsts],
- ["security.mixed_content.send_hsts_priming",
- settings.send_hsts_priming]];
-
- if (additional_prefs) {
- for (let idx in additional_prefs) {
- prefs.push(additional_prefs[idx]);
- }
- }
-
- console.log("prefs=%s", prefs);
-
- SpecialPowers.pushPrefEnv({'set': prefs});
-}
-
-// make the top-level test uri
-function build_test_uri(base_uri, host, test_id, type) {
- return base_uri +
- "?host=" + escape(host) +
- "&id=" + escape(test_id) +
- "&type=" + escape(type);
-}
-
-// open a new tab, load the test, and wait for it to finish
-function execute_test(test, mimetype) {
- var src = build_test_uri(TOP_URI, test_servers[test].host,
- test, test_settings[which_test].type);
-
- let tab = openTab(src);
- test_servers[test]['tab'] = tab;
-
- let browser = gBrowser.getBrowserForTab(tab);
- yield BrowserTestUtils.browserLoaded(browser);
-
- yield BrowserTestUtils.removeTab(tab);
-}
diff --git a/dom/security/test/mixedcontentblocker/test_main.html b/dom/security/test/mixedcontentblocker/test_main.html
index d2bc9dc7e..bb9536939 100644
--- a/dom/security/test/mixedcontentblocker/test_main.html
+++ b/dom/security/test/mixedcontentblocker/test_main.html
@@ -162,9 +162,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=62178
}
function startTest() {
- // Set prefs to use mixed-content before HSTS
- SpecialPowers.pushPrefEnv({'set': [["security.mixed_content.use_hsts", false],
- ["security.mixed_content.send_hsts_priming", false]]});
//Set the first set of mixed content settings and increment the counter.
changePrefs([], function() {
//listen for a messages from the mixed content test harness
diff --git a/dom/security/test/moz.build b/dom/security/test/moz.build
index ddb4e9b89..759e76c73 100644
--- a/dom/security/test/moz.build
+++ b/dom/security/test/moz.build
@@ -27,5 +27,5 @@ MOCHITEST_CHROME_MANIFESTS += [
BROWSER_CHROME_MANIFESTS += [
'contentverifier/browser.ini',
'csp/browser.ini',
- 'hsts/browser.ini',
+ 'general/browser.ini',
]
diff --git a/dom/settings/SettingsService.js b/dom/settings/SettingsService.js
deleted file mode 100644
index 09bd3ca72..000000000
--- a/dom/settings/SettingsService.js
+++ /dev/null
@@ -1,358 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import('resource://gre/modules/SettingsRequestManager.jsm');
-
-/* static functions */
-var DEBUG = false;
-var VERBOSE = false;
-
-try {
- DEBUG =
- Services.prefs.getBoolPref("dom.mozSettings.SettingsService.debug.enabled");
- VERBOSE =
- Services.prefs.getBoolPref("dom.mozSettings.SettingsService.verbose.enabled");
-} catch (ex) { }
-
-function debug(s) {
- dump("-*- SettingsService: " + s + "\n");
-}
-
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsIMessageSender");
-XPCOMUtils.defineLazyServiceGetter(this, "mrm",
- "@mozilla.org/memory-reporter-manager;1",
- "nsIMemoryReporterManager");
-
-const nsIClassInfo = Ci.nsIClassInfo;
-const kXpcomShutdownObserverTopic = "xpcom-shutdown";
-
-const SETTINGSSERVICELOCK_CONTRACTID = "@mozilla.org/settingsServiceLock;1";
-const SETTINGSSERVICELOCK_CID = Components.ID("{d7a395a0-e292-11e1-834e-1761d57f5f99}");
-const nsISettingsServiceLock = Ci.nsISettingsServiceLock;
-
-function makeSettingsServiceRequest(aCallback, aName, aValue) {
- return {
- callback: aCallback,
- name: aName,
- value: aValue
- };
-};
-
-const kLockListeners = ["Settings:Get:OK", "Settings:Get:KO",
- "Settings:Clear:OK", "Settings:Clear:KO",
- "Settings:Set:OK", "Settings:Set:KO",
- "Settings:Finalize:OK", "Settings:Finalize:KO"];
-
-function SettingsServiceLock(aSettingsService, aTransactionCallback) {
- if (VERBOSE) debug("settingsServiceLock constr!");
- this._open = true;
- this._settingsService = aSettingsService;
- this._id = uuidgen.generateUUID().toString();
- this._transactionCallback = aTransactionCallback;
- this._requests = {};
- let closeHelper = function() {
- if (VERBOSE) debug("closing lock " + this._id);
- this._open = false;
- this.runOrFinalizeQueries();
- }.bind(this);
-
- this.addListeners();
-
- let createLockPayload = {
- lockID: this._id,
- isServiceLock: true,
- windowID: undefined,
- lockStack: (new Error).stack
- };
-
- this.returnMessage("Settings:CreateLock", createLockPayload);
- Services.tm.currentThread.dispatch(closeHelper, Ci.nsIThread.DISPATCH_NORMAL);
-}
-
-SettingsServiceLock.prototype = {
- get closed() {
- return !this._open;
- },
-
- addListeners: function() {
- for (let msg of kLockListeners) {
- cpmm.addMessageListener(msg, this);
- }
- },
-
- removeListeners: function() {
- for (let msg of kLockListeners) {
- cpmm.removeMessageListener(msg, this);
- }
- },
-
- returnMessage: function(aMessage, aData) {
- SettingsRequestManager.receiveMessage({
- name: aMessage,
- data: aData,
- target: undefined,
- principal: Services.scriptSecurityManager.getSystemPrincipal()
- });
- },
-
- runOrFinalizeQueries: function() {
- if (!this._requests || Object.keys(this._requests).length == 0) {
- this.returnMessage("Settings:Finalize", {lockID: this._id});
- } else {
- this.returnMessage("Settings:Run", {lockID: this._id});
- }
- },
-
- receiveMessage: function(aMessage) {
-
- let msg = aMessage.data;
- // SettingsRequestManager broadcasts changes to all locks in the child. If
- // our lock isn't being addressed, just return.
- if(msg.lockID != this._id) {
- return;
- }
- if (VERBOSE) debug("receiveMessage (" + this._id + "): " + aMessage.name);
- // Finalizing a transaction does not return a request ID since we are
- // supposed to fire callbacks.
- if (!msg.requestID) {
- switch (aMessage.name) {
- case "Settings:Finalize:OK":
- if (VERBOSE) debug("Lock finalize ok!");
- this.callTransactionHandle();
- break;
- case "Settings:Finalize:KO":
- if (DEBUG) debug("Lock finalize failed!");
- this.callAbort();
- break;
- default:
- if (DEBUG) debug("Message type " + aMessage.name + " is missing a requestID");
- }
-
- this._settingsService.unregisterLock(this._id);
- return;
- }
-
- let req = this._requests[msg.requestID];
- if (!req) {
- if (DEBUG) debug("Matching request not found.");
- return;
- }
- delete this._requests[msg.requestID];
- switch (aMessage.name) {
- case "Settings:Get:OK":
- this._open = true;
- let settings_names = Object.keys(msg.settings);
- if (settings_names.length > 0) {
- let name = settings_names[0];
- if (DEBUG && settings_names.length > 1) {
- debug("Warning: overloaded setting:" + name);
- }
- let result = msg.settings[name];
- this.callHandle(req.callback, name, result);
- } else {
- this.callHandle(req.callback, req.name, null);
- }
- this._open = false;
- break;
- case "Settings:Set:OK":
- this._open = true;
- // We don't pass values back from sets in SettingsManager...
- this.callHandle(req.callback, req.name, req.value);
- this._open = false;
- break;
- case "Settings:Get:KO":
- case "Settings:Set:KO":
- if (DEBUG) debug("error:" + msg.errorMsg);
- this.callError(req.callback, msg.error);
- break;
- default:
- if (DEBUG) debug("Wrong message: " + aMessage.name);
- }
- this.runOrFinalizeQueries();
- },
-
- get: function get(aName, aCallback) {
- if (VERBOSE) debug("get (" + this._id + "): " + aName);
- if (!this._open) {
- if (DEBUG) debug("Settings lock not open!\n");
- throw Components.results.NS_ERROR_ABORT;
- }
- let reqID = uuidgen.generateUUID().toString();
- this._requests[reqID] = makeSettingsServiceRequest(aCallback, aName);
- this.returnMessage("Settings:Get", {requestID: reqID,
- lockID: this._id,
- name: aName});
- },
-
- set: function set(aName, aValue, aCallback) {
- if (VERBOSE) debug("set: " + aName + " " + aValue);
- if (!this._open) {
- throw "Settings lock not open";
- }
- let reqID = uuidgen.generateUUID().toString();
- this._requests[reqID] = makeSettingsServiceRequest(aCallback, aName, aValue);
- let settings = {};
- settings[aName] = aValue;
- this.returnMessage("Settings:Set", {requestID: reqID,
- lockID: this._id,
- settings: settings});
- },
-
- callHandle: function callHandle(aCallback, aName, aValue) {
- try {
- aCallback && aCallback.handle ? aCallback.handle(aName, aValue) : null;
- } catch (e) {
- if (DEBUG) debug("settings 'handle' for " + aName + " callback threw an exception, dropping: " + e + "\n");
- }
- },
-
- callAbort: function callAbort(aCallback, aMessage) {
- try {
- aCallback && aCallback.handleAbort ? aCallback.handleAbort(aMessage) : null;
- } catch (e) {
- if (DEBUG) debug("settings 'abort' callback threw an exception, dropping: " + e + "\n");
- }
- },
-
- callError: function callError(aCallback, aMessage) {
- try {
- aCallback && aCallback.handleError ? aCallback.handleError(aMessage) : null;
- } catch (e) {
- if (DEBUG) debug("settings 'error' callback threw an exception, dropping: " + e + "\n");
- }
- },
-
- callTransactionHandle: function callTransactionHandle() {
- try {
- this._transactionCallback && this._transactionCallback.handle ? this._transactionCallback.handle() : null;
- } catch (e) {
- if (DEBUG) debug("settings 'Transaction handle' callback threw an exception, dropping: " + e + "\n");
- }
- },
-
- classID : SETTINGSSERVICELOCK_CID,
- QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock])
-};
-
-const SETTINGSSERVICE_CID = Components.ID("{f656f0c0-f776-11e1-a21f-0800200c9a66}");
-
-function SettingsService()
-{
- if (VERBOSE) debug("settingsService Constructor");
- this._locks = [];
- this._serviceLocks = {};
- this._createdLocks = 0;
- this._unregisteredLocks = 0;
- this.init();
-}
-
-SettingsService.prototype = {
-
- init: function() {
- Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false);
- mrm.registerStrongReporter(this);
- },
-
- uninit: function() {
- Services.obs.removeObserver(this, kXpcomShutdownObserverTopic);
- mrm.unregisterStrongReporter(this);
- },
-
- observe: function(aSubject, aTopic, aData) {
- if (VERBOSE) debug("observe: " + aTopic);
- if (aTopic === kXpcomShutdownObserverTopic) {
- this.uninit();
- }
- },
-
- receiveMessage: function(aMessage) {
- if (VERBOSE) debug("Entering receiveMessage");
-
- let lockID = aMessage.data.lockID;
- if (!lockID) {
- if (DEBUG) debug("No lock ID");
- return;
- }
-
- if (!(lockID in this._serviceLocks)) {
- if (DEBUG) debug("Received message for lock " + lockID + " but no lock");
- return;
- }
-
- if (VERBOSE) debug("Delivering message");
- this._serviceLocks[lockID].receiveMessage(aMessage);
- },
-
- createLock: function createLock(aCallback) {
- if (VERBOSE) debug("Calling createLock");
- var lock = new SettingsServiceLock(this, aCallback);
- if (VERBOSE) debug("Created lock " + lock._id);
- this.registerLock(lock);
- return lock;
- },
-
- registerLock: function(aLock) {
- if (VERBOSE) debug("Registering lock " + aLock._id);
- this._locks.push(aLock._id);
- this._serviceLocks[aLock._id] = aLock;
- this._createdLocks++;
- },
-
- unregisterLock: function(aLockID) {
- let lock_index = this._locks.indexOf(aLockID);
- if (lock_index != -1) {
- if (VERBOSE) debug("Unregistering lock " + aLockID);
- this._locks.splice(lock_index, 1);
- this._serviceLocks[aLockID].removeListeners();
- this._serviceLocks[aLockID] = null;
- delete this._serviceLocks[aLockID];
- this._unregisteredLocks++;
- }
- },
-
- collectReports: function(aCallback, aData, aAnonymize) {
- aCallback.callback("",
- "settings-service-locks/alive",
- Ci.nsIMemoryReporter.KIND_OTHER,
- Ci.nsIMemoryReporter.UNITS_COUNT,
- this._locks.length,
- "The number of service locks that are currently alives.",
- aData);
-
- aCallback.callback("",
- "settings-service-locks/created",
- Ci.nsIMemoryReporter.KIND_OTHER,
- Ci.nsIMemoryReporter.UNITS_COUNT,
- this._createdLocks,
- "The number of service locks that were created.",
- aData);
-
- aCallback.callback("",
- "settings-service-locks/deleted",
- Ci.nsIMemoryReporter.KIND_OTHER,
- Ci.nsIMemoryReporter.UNITS_COUNT,
- this._unregisteredLocks,
- "The number of service locks that were deleted.",
- aData);
- },
-
- classID : SETTINGSSERVICE_CID,
- QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService,
- Ci.nsIObserver,
- Ci.nsIMemoryReporter])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock]);
diff --git a/dom/settings/SettingsService.manifest b/dom/settings/SettingsService.manifest
deleted file mode 100644
index ae464f921..000000000
--- a/dom/settings/SettingsService.manifest
+++ /dev/null
@@ -1,5 +0,0 @@
-component {d7a395a0-e292-11e1-834e-1761d57f5f99} SettingsService.js
-contract @mozilla.org/settingsServiceLock;1 {d7a395a0-e292-11e1-834e-1761d57f5f99}
-
-component {f656f0c0-f776-11e1-a21f-0800200c9a66} SettingsService.js
-contract @mozilla.org/settingsService;1 {f656f0c0-f776-11e1-a21f-0800200c9a66}
diff --git a/dom/settings/moz.build b/dom/settings/moz.build
index 426edcbce..580a55e6a 100644
--- a/dom/settings/moz.build
+++ b/dom/settings/moz.build
@@ -12,12 +12,6 @@ EXTRA_PP_COMPONENTS += [
'SettingsManager.js'
]
-if CONFIG['MOZ_B2G']:
- EXTRA_COMPONENTS += [
- 'SettingsService.js',
- 'SettingsService.manifest',
- ]
-
EXTRA_JS_MODULES += [
'SettingsDB.jsm',
'SettingsRequestManager.jsm'
diff --git a/dom/settings/tests/chrome.ini b/dom/settings/tests/chrome.ini
index 92b1554a0..5b0db9e40 100644
--- a/dom/settings/tests/chrome.ini
+++ b/dom/settings/tests/chrome.ini
@@ -4,13 +4,7 @@ support-files =
file_loadserver.js
file_bug1110872.js
file_bug1110872.html
- test_settings_service.js
- test_settings_service_callback.js
-[test_settings_service.xul]
-run-if = buildapp == 'b2g' || buildapp == 'mulet'
-[test_settings_service_callback.xul]
-run-if = buildapp == 'b2g' || buildapp == 'mulet'
[test_settings_basics.html]
[test_settings_permissions.html]
[test_settings_blobs.html]
diff --git a/dom/settings/tests/test_settings_service.js b/dom/settings/tests/test_settings_service.js
deleted file mode 100644
index 132877a5d..000000000
--- a/dom/settings/tests/test_settings_service.js
+++ /dev/null
@@ -1,138 +0,0 @@
-"use strict";
-
-var Cu = Components.utils;
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-
-if (SpecialPowers.isMainProcess()) {
- SpecialPowers.Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
-}
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-SimpleTest.waitForExplicitFinish();
-
-XPCOMUtils.defineLazyServiceGetter(this, "SettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-var tests = [
- /* Callback tests */
- function() {
- let callbackCount = 10;
-
- let callback = {
- handle: function(name, result) {
- switch (callbackCount) {
- case 10:
- case 9:
- is(result, true, "result is true");
- break;
- case 8:
- case 7:
- is(result, false, "result is false");
- break;
- case 6:
- case 5:
- is(result, 9, "result is 9");
- break;
- case 4:
- case 3:
- is(result, 9.4, "result is 9.4");
- break;
- case 2:
- is(result, false, "result is false");
- break;
- case 1:
- is(result, null, "result is null");
- break;
- default:
- ok(false, "Unexpected call: " + callbackCount);
- }
-
- --callbackCount;
- if (callbackCount === 0) {
- next();
- }
- },
-
- handleError: function(name) {
- ok(false, "error: " + name);
- }
- };
-
- let lock = SettingsService.createLock();
- let lock1 = SettingsService.createLock();
-
- lock.set("asdf", true, callback, null);
- lock1.get("asdf", callback);
- lock.get("asdf", callback);
- lock.set("asdf", false, callback, null);
- lock.get("asdf", callback);
- lock.set("int", 9, callback, null);
- lock.get("int", callback);
- lock.set("doub", 9.4, callback, null);
- lock.get("doub", callback);
- lock1.get("asdfxxx", callback);
- },
-
- /* Observer tests */
- function() {
- const MOZSETTINGS_CHANGED = "mozsettings-changed";
- const TEST_OBSERVER_KEY = "test.observer.key";
- const TEST_OBSERVER_VALUE = true;
- const TEST_OBSERVER_MESSAGE = "test.observer.message";
-
- var obs = {
- observe: function (subject, topic, data) {
-
- if (topic !== MOZSETTINGS_CHANGED) {
- ok(false, "Event is not mozsettings-changed.");
- return;
- }
- // Data is now stored in subject
- if ("wrappedJSObject" in subject) {
- ok(true, "JS object wrapped into subject");
- subject = subject.wrappedJSObject;
- }
- if (subject["key"] != TEST_OBSERVER_KEY) {
- return;
- }
-
- function checkProp(name, type, value) {
- ok(name in subject, "subject." + name + " is present");
- is(typeof subject[name], type, "subject." + name + " is " + type);
- is(subject[name], value, "subject." + name + " is " + value);
- }
-
- checkProp("key", "string", TEST_OBSERVER_KEY);
- checkProp("value", "boolean", TEST_OBSERVER_VALUE);
- checkProp("isInternalChange", "boolean", true);
-
- Services.obs.removeObserver(this, MOZSETTINGS_CHANGED);
- next();
- }
- };
-
- Services.obs.addObserver(obs, MOZSETTINGS_CHANGED, false);
-
- let lock = SettingsService.createLock();
- lock.set(TEST_OBSERVER_KEY, TEST_OBSERVER_VALUE, null);
- }
-];
-
-function next() {
- let step = tests.shift();
- if (step) {
- try {
- step();
- } catch(e) {
- ok(false, "Test threw: " + e);
- }
- } else {
- SimpleTest.finish();
- }
-}
-
-next();
diff --git a/dom/settings/tests/test_settings_service.xul b/dom/settings/tests/test_settings_service.xul
deleted file mode 100644
index 58a9efad9..000000000
--- a/dom/settings/tests/test_settings_service.xul
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
-<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=678695
--->
-<window title="Mozilla Bug 678695"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-
- <!-- test results are displayed in the html:body -->
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=678695"
- target="_blank">Mozilla Bug 678695</a>
- </body>
-
- <script type="application/javascript;version=1.7" src="test_settings_service.js" />
-</window>
diff --git a/dom/settings/tests/test_settings_service_callback.js b/dom/settings/tests/test_settings_service_callback.js
deleted file mode 100644
index a780bb9c3..000000000
--- a/dom/settings/tests/test_settings_service_callback.js
+++ /dev/null
@@ -1,47 +0,0 @@
-"use strict";
-
-var Cu = Components.utils;
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-SimpleTest.waitForExplicitFinish();
-
-XPCOMUtils.defineLazyServiceGetter(this, "SettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-var tests = [
- function () {
- let callback = {
- handle: function() {
- ok(true, "handle called!");
- next();
- },
-
- handleAbort: function(name) {
- ok(false, "error: " + name);
- next();
- }
- }
- let lock = SettingsService.createLock(callback);
- lock.set("xasdf", true, null, null);
- }
-];
-
-function next() {
- let step = tests.shift();
- if (step) {
- try {
- step();
- } catch(e) {
- ok(false, "Test threw: " + e);
- }
- } else {
- SimpleTest.finish();
- }
-}
-
-next();
diff --git a/dom/settings/tests/test_settings_service_callback.xul b/dom/settings/tests/test_settings_service_callback.xul
deleted file mode 100644
index 3e4d27751..000000000
--- a/dom/settings/tests/test_settings_service_callback.xul
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
-<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1012214
--->
-<window title="Mozilla Bug 1012214"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-
- <!-- test results are displayed in the html:body -->
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1012214"
- target="_blank">Mozilla Bug 1012214</a>
- </body>
-
- <script type="application/javascript;version=1.7" src="test_settings_service_callback.js" />
-</window>
diff --git a/dom/speakermanager/SpeakerManager.cpp b/dom/speakermanager/SpeakerManager.cpp
deleted file mode 100644
index 2b30fa72c..000000000
--- a/dom/speakermanager/SpeakerManager.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SpeakerManager.h"
-
-#include "mozilla/Services.h"
-
-#include "mozilla/dom/Event.h"
-
-#include "AudioChannelService.h"
-#include "nsIDocShell.h"
-#include "nsIDOMClassInfo.h"
-#include "nsIDOMEventListener.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsIPermissionManager.h"
-#include "SpeakerManagerService.h"
-
-namespace mozilla {
-namespace dom {
-
-NS_IMPL_QUERY_INTERFACE_INHERITED(SpeakerManager, DOMEventTargetHelper,
- nsIDOMEventListener)
-NS_IMPL_ADDREF_INHERITED(SpeakerManager, DOMEventTargetHelper)
-NS_IMPL_RELEASE_INHERITED(SpeakerManager, DOMEventTargetHelper)
-
-SpeakerManager::SpeakerManager()
- : mForcespeaker(false)
- , mVisible(false)
-{
- SpeakerManagerService *service =
- SpeakerManagerService::GetOrCreateSpeakerManagerService();
- MOZ_ASSERT(service);
- service->RegisterSpeakerManager(this);
-}
-
-SpeakerManager::~SpeakerManager()
-{
- SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
- MOZ_ASSERT(service);
-
- service->UnRegisterSpeakerManager(this);
- nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner());
- NS_ENSURE_TRUE_VOID(target);
-
- target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
- this,
- /* useCapture = */ true);
-}
-
-bool
-SpeakerManager::Speakerforced()
-{
- // If a background app calls forcespeaker=true that doesn't change anything.
- // 'speakerforced' remains false everywhere.
- if (mForcespeaker && !mVisible) {
- return false;
- }
- SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
- MOZ_ASSERT(service);
- return service->GetSpeakerStatus();
-
-}
-
-bool
-SpeakerManager::Forcespeaker()
-{
- return mForcespeaker;
-}
-
-void
-SpeakerManager::SetForcespeaker(bool aEnable)
-{
- SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
- MOZ_ASSERT(service);
-
- service->ForceSpeaker(aEnable, mVisible);
- mForcespeaker = aEnable;
-}
-
-void
-SpeakerManager::DispatchSimpleEvent(const nsAString& aStr)
-{
- MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
- nsresult rv = CheckInnerWindowCorrectness();
- if (NS_FAILED(rv)) {
- return;
- }
-
- RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
- event->InitEvent(aStr, false, false);
- event->SetTrusted(true);
-
- rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
- if (NS_FAILED(rv)) {
- NS_ERROR("Failed to dispatch the event!!!");
- return;
- }
-}
-
-void
-SpeakerManager::Init(nsPIDOMWindowInner* aWindow)
-{
- BindToOwner(aWindow);
-
- nsCOMPtr<nsIDocShell> docshell = GetOwner()->GetDocShell();
- NS_ENSURE_TRUE_VOID(docshell);
- docshell->GetIsActive(&mVisible);
-
- nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
- NS_ENSURE_TRUE_VOID(target);
-
- target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
- this,
- /* useCapture = */ true,
- /* wantsUntrusted = */ false);
-}
-
-nsPIDOMWindowInner*
-SpeakerManager::GetParentObject() const
-{
- return GetOwner();
-}
-
-/* static */ already_AddRefed<SpeakerManager>
-SpeakerManager::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
-{
- nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal.GetAsSupports());
- if (!sgo) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- nsCOMPtr<nsPIDOMWindowInner> ownerWindow = do_QueryInterface(aGlobal.GetAsSupports());
- if (!ownerWindow) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
- NS_ENSURE_TRUE(permMgr, nullptr);
-
- uint32_t permission = nsIPermissionManager::DENY_ACTION;
- nsresult rv =
- permMgr->TestPermissionFromWindow(ownerWindow, "speaker-control",
- &permission);
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- if (permission != nsIPermissionManager::ALLOW_ACTION) {
- aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
- return nullptr;
- }
-
- RefPtr<SpeakerManager> object = new SpeakerManager();
- object->Init(ownerWindow);
- return object.forget();
-}
-
-JSObject*
-SpeakerManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
- return MozSpeakerManagerBinding::Wrap(aCx, this, aGivenProto);
-}
-
-NS_IMETHODIMP
-SpeakerManager::HandleEvent(nsIDOMEvent* aEvent)
-{
- nsAutoString type;
- aEvent->GetType(type);
-
- if (!type.EqualsLiteral("visibilitychange")) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
- NS_ENSURE_TRUE(docshell, NS_ERROR_FAILURE);
- docshell->GetIsActive(&mVisible);
-
- // If an app that has called forcespeaker=true is switched
- // from the background to the foreground 'speakerforced'
- // switches to true in all apps. I.e. the app doesn't have to
- // call forcespeaker=true again when it comes into foreground.
- SpeakerManagerService *service =
- SpeakerManagerService::GetOrCreateSpeakerManagerService();
- MOZ_ASSERT(service);
-
- if (mVisible && mForcespeaker) {
- service->ForceSpeaker(mForcespeaker, mVisible);
- }
- // If an application that has called forcespeaker=true, but no audio is
- // currently playing in the app itself, if application switch to
- // the background, we switch 'speakerforced' to false.
- if (!mVisible && mForcespeaker) {
- RefPtr<AudioChannelService> audioChannelService =
- AudioChannelService::GetOrCreate();
- if (audioChannelService && !audioChannelService->AnyAudioChannelIsActive()) {
- service->ForceSpeaker(false, mVisible);
- }
- }
- return NS_OK;
-}
-
-void
-SpeakerManager::SetAudioChannelActive(bool isActive)
-{
- if (mForcespeaker) {
- SpeakerManagerService *service =
- SpeakerManagerService::GetOrCreateSpeakerManagerService();
- MOZ_ASSERT(service);
- service->ForceSpeaker(isActive, mVisible);
- }
-}
-
-} // namespace dom
-} // namespace mozilla
diff --git a/dom/speakermanager/SpeakerManager.h b/dom/speakermanager/SpeakerManager.h
deleted file mode 100644
index bf084dfd9..000000000
--- a/dom/speakermanager/SpeakerManager.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_SpeakerManager_h
-#define mozilla_dom_SpeakerManager_h
-
-#include "mozilla/DOMEventTargetHelper.h"
-#include "mozilla/dom/MozSpeakerManagerBinding.h"
-
-namespace mozilla {
-namespace dom {
-/* This class is used for UA to control devices's speaker status.
- * After UA set the speaker status, the UA should handle the
- * forcespeakerchange event and change the speaker status in UI.
- * The device's speaker status would set back to normal when UA close the application.
- */
-class SpeakerManager final
- : public DOMEventTargetHelper
- , public nsIDOMEventListener
-{
- friend class SpeakerManagerService;
- friend class SpeakerManagerServiceChild;
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIDOMEVENTLISTENER
-
-public:
- void Init(nsPIDOMWindowInner* aWindow);
-
- nsPIDOMWindowInner* GetParentObject() const;
-
- virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
- /**
- * WebIDL Interface
- */
- // Get this api's force speaker setting.
- bool Forcespeaker();
- // Force acoustic sound go through speaker. Don't force to speaker if application
- // stay in the background and re-force when application
- // go to foreground
- void SetForcespeaker(bool aEnable);
- // Get the device's speaker forced setting.
- bool Speakerforced();
-
- void SetAudioChannelActive(bool aIsActive);
- IMPL_EVENT_HANDLER(speakerforcedchange)
-
- static already_AddRefed<SpeakerManager>
- Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
-
-protected:
- SpeakerManager();
- ~SpeakerManager();
- void DispatchSimpleEvent(const nsAString& aStr);
- // This api's force speaker setting
- bool mForcespeaker;
- bool mVisible;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_SpeakerManager_h
diff --git a/dom/speakermanager/SpeakerManagerService.cpp b/dom/speakermanager/SpeakerManagerService.cpp
deleted file mode 100644
index a444f7163..000000000
--- a/dom/speakermanager/SpeakerManagerService.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SpeakerManagerService.h"
-#include "SpeakerManagerServiceChild.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/Unused.h"
-#include "mozilla/dom/ContentParent.h"
-#include "nsIPropertyBag2.h"
-#include "nsThreadUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "AudioChannelService.h"
-#include <cutils/properties.h>
-
-#define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
-#include "nsIAudioManager.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-StaticRefPtr<SpeakerManagerService> gSpeakerManagerService;
-
-// static
-SpeakerManagerService*
-SpeakerManagerService::GetOrCreateSpeakerManagerService()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!XRE_IsParentProcess()) {
- return SpeakerManagerServiceChild::GetOrCreateSpeakerManagerService();
- }
-
- // If we already exist, exit early
- if (gSpeakerManagerService) {
- return gSpeakerManagerService;
- }
-
- // Create new instance, register, return
- RefPtr<SpeakerManagerService> service = new SpeakerManagerService();
-
- gSpeakerManagerService = service;
-
- return gSpeakerManagerService;
-}
-
-SpeakerManagerService*
-SpeakerManagerService::GetSpeakerManagerService()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!XRE_IsParentProcess()) {
- return SpeakerManagerServiceChild::GetSpeakerManagerService();
- }
-
- return gSpeakerManagerService;
-}
-
-void
-SpeakerManagerService::Shutdown()
-{
- if (!XRE_IsParentProcess()) {
- return SpeakerManagerServiceChild::Shutdown();
- }
-
- if (gSpeakerManagerService) {
- gSpeakerManagerService = nullptr;
- }
-}
-
-NS_IMPL_ISUPPORTS(SpeakerManagerService, nsIObserver)
-
-void
-SpeakerManagerService::ForceSpeaker(bool aEnable, uint64_t aChildId)
-{
- TurnOnSpeaker(aEnable);
- if (aEnable) {
- mSpeakerStatusSet.Put(aChildId);
- }
- Notify();
- return;
-}
-
-void
-SpeakerManagerService::ForceSpeaker(bool aEnable, bool aVisible)
-{
- // b2g main process without oop
- TurnOnSpeaker(aEnable && aVisible);
- mVisible = aVisible;
- mOrgSpeakerStatus = aEnable;
- Notify();
-}
-
-void
-SpeakerManagerService::TurnOnSpeaker(bool aOn)
-{
- nsCOMPtr<nsIAudioManager> audioManager = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
- NS_ENSURE_TRUE_VOID(audioManager);
- int32_t phoneState;
- audioManager->GetPhoneState(&phoneState);
- int32_t forceuse = (phoneState == nsIAudioManager::PHONE_STATE_IN_CALL ||
- phoneState == nsIAudioManager::PHONE_STATE_IN_COMMUNICATION)
- ? nsIAudioManager::USE_COMMUNICATION : nsIAudioManager::USE_MEDIA;
- if (aOn) {
- audioManager->SetForceForUse(forceuse, nsIAudioManager::FORCE_SPEAKER);
- } else {
- audioManager->SetForceForUse(forceuse, nsIAudioManager::FORCE_NONE);
- }
-}
-
-bool
-SpeakerManagerService::GetSpeakerStatus()
-{
- char propQemu[PROPERTY_VALUE_MAX];
- property_get("ro.kernel.qemu", propQemu, "");
- if (!strncmp(propQemu, "1", 1)) {
- return mOrgSpeakerStatus;
- }
- nsCOMPtr<nsIAudioManager> audioManager = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
- NS_ENSURE_TRUE(audioManager, false);
- int32_t usage;
- audioManager->GetForceForUse(nsIAudioManager::USE_MEDIA, &usage);
- return usage == nsIAudioManager::FORCE_SPEAKER;
-}
-
-void
-SpeakerManagerService::Notify()
-{
- // Parent Notify to all the child processes.
- nsTArray<ContentParent*> children;
- ContentParent::GetAll(children);
- for (uint32_t i = 0; i < children.Length(); i++) {
- Unused << children[i]->SendSpeakerManagerNotify();
- }
-
- for (uint32_t i = 0; i < mRegisteredSpeakerManagers.Length(); i++) {
- mRegisteredSpeakerManagers[i]->
- DispatchSimpleEvent(NS_LITERAL_STRING("speakerforcedchange"));
- }
-}
-
-void
-SpeakerManagerService::SetAudioChannelActive(bool aIsActive)
-{
- if (!aIsActive && !mVisible) {
- ForceSpeaker(!mOrgSpeakerStatus, mVisible);
- }
-}
-
-NS_IMETHODIMP
-SpeakerManagerService::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- if (!strcmp(aTopic, "ipc:content-shutdown")) {
- nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
- if (!props) {
- NS_WARNING("ipc:content-shutdown message without property bag as subject");
- return NS_OK;
- }
-
- uint64_t childID = 0;
- nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"),
- &childID);
- if (NS_SUCCEEDED(rv)) {
- // If the audio has paused by audiochannel,
- // the enable flag should be false and don't need to handle.
- if (mSpeakerStatusSet.Contains(childID)) {
- TurnOnSpeaker(false);
- mSpeakerStatusSet.Remove(childID);
- }
- if (mOrgSpeakerStatus) {
- TurnOnSpeaker(!mOrgSpeakerStatus);
- mOrgSpeakerStatus = false;
- }
- } else {
- NS_WARNING("ipc:content-shutdown message without childID property");
- }
- } else if (!strcmp(aTopic, "xpcom-will-shutdown")) {
- // Note that we need to do this before xpcom-shutdown, since the
- // AudioChannelService cannot be used past that point.
- RefPtr<AudioChannelService> audioChannelService =
- AudioChannelService::GetOrCreate();
- if (audioChannelService) {
- audioChannelService->UnregisterSpeakerManager(this);
- }
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- obs->RemoveObserver(this, "ipc:content-shutdown");
- obs->RemoveObserver(this, "xpcom-will-shutdown");
- }
-
- Shutdown();
- }
- return NS_OK;
-}
-
-SpeakerManagerService::SpeakerManagerService()
- : mOrgSpeakerStatus(false),
- mVisible(false)
-{
- MOZ_COUNT_CTOR(SpeakerManagerService);
- if (XRE_IsParentProcess()) {
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- obs->AddObserver(this, "ipc:content-shutdown", false);
- obs->AddObserver(this, "xpcom-will-shutdown", false);
- }
- }
- RefPtr<AudioChannelService> audioChannelService =
- AudioChannelService::GetOrCreate();
- if (audioChannelService) {
- audioChannelService->RegisterSpeakerManager(this);
- }
-}
-
-SpeakerManagerService::~SpeakerManagerService()
-{
- MOZ_COUNT_DTOR(SpeakerManagerService);
-}
diff --git a/dom/speakermanager/SpeakerManagerService.h b/dom/speakermanager/SpeakerManagerService.h
deleted file mode 100644
index 5f3506ae2..000000000
--- a/dom/speakermanager/SpeakerManagerService.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_SpeakerManagerService_h__
-#define mozilla_dom_SpeakerManagerService_h__
-
-#include "nsIObserver.h"
-#include "nsTArray.h"
-#include "SpeakerManager.h"
-#include "nsIAudioManager.h"
-#include "nsCheapSets.h"
-#include "nsHashKeys.h"
-
-namespace mozilla {
-namespace dom {
-
-class SpeakerManagerService : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- /*
- * Return null or instance which has been created.
- */
- static SpeakerManagerService* GetSpeakerManagerService();
- /*
- * Return SpeakerManagerService instance.
- * If SpeakerManagerService is not exist, create and return new one.
- */
- static SpeakerManagerService* GetOrCreateSpeakerManagerService();
- virtual void ForceSpeaker(bool aEnable, bool aVisible);
- virtual bool GetSpeakerStatus();
- virtual void SetAudioChannelActive(bool aIsActive);
- // Called by child
- void ForceSpeaker(bool enable, uint64_t aChildid);
- // Register the SpeakerManager to service for notify the speakerforcedchange event
- void RegisterSpeakerManager(SpeakerManager* aSpeakerManager)
- {
- mRegisteredSpeakerManagers.AppendElement(aSpeakerManager);
- }
- void UnRegisterSpeakerManager(SpeakerManager* aSpeakerManager)
- {
- mRegisteredSpeakerManagers.RemoveElement(aSpeakerManager);
- }
-
-protected:
- SpeakerManagerService();
-
- virtual ~SpeakerManagerService();
- // Notify to UA if device speaker status changed
- virtual void Notify();
-
- void TurnOnSpeaker(bool aEnable);
-
- /**
- * Shutdown the singleton.
- */
- static void Shutdown();
-
- nsTArray<RefPtr<SpeakerManager> > mRegisteredSpeakerManagers;
- // Set for remember all the child speaker status
- nsCheapSet<nsUint64HashKey> mSpeakerStatusSet;
- // The Speaker status assign by UA
- bool mOrgSpeakerStatus;
-
- bool mVisible;
- // This is needed for IPC communication between
- // SpeakerManagerServiceChild and this class.
- friend class ContentParent;
- friend class ContentChild;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif
diff --git a/dom/speakermanager/SpeakerManagerServiceChild.cpp b/dom/speakermanager/SpeakerManagerServiceChild.cpp
deleted file mode 100644
index 6c1e30b78..000000000
--- a/dom/speakermanager/SpeakerManagerServiceChild.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SpeakerManagerServiceChild.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/Unused.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/ContentParent.h"
-#include "nsIObserverService.h"
-#include "nsThreadUtils.h"
-#include "AudioChannelService.h"
-#include <cutils/properties.h>
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-StaticRefPtr<SpeakerManagerServiceChild> gSpeakerManagerServiceChild;
-
-// static
-SpeakerManagerService*
-SpeakerManagerServiceChild::GetOrCreateSpeakerManagerService()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // If we already exist, exit early
- if (gSpeakerManagerServiceChild) {
- return gSpeakerManagerServiceChild;
- }
-
- // Create new instance, register, return
- RefPtr<SpeakerManagerServiceChild> service = new SpeakerManagerServiceChild();
-
- gSpeakerManagerServiceChild = service;
-
- return gSpeakerManagerServiceChild;
-}
-
-// static
-SpeakerManagerService*
-SpeakerManagerServiceChild::GetSpeakerManagerService()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- return gSpeakerManagerServiceChild;
-}
-
-void
-SpeakerManagerServiceChild::ForceSpeaker(bool aEnable, bool aVisible)
-{
- mVisible = aVisible;
- mOrgSpeakerStatus = aEnable;
- ContentChild *cc = ContentChild::GetSingleton();
- if (cc) {
- cc->SendSpeakerManagerForceSpeaker(aEnable && aVisible);
- }
-}
-
-bool
-SpeakerManagerServiceChild::GetSpeakerStatus()
-{
- ContentChild *cc = ContentChild::GetSingleton();
- bool status = false;
- if (cc) {
- cc->SendSpeakerManagerGetSpeakerStatus(&status);
- }
- char propQemu[PROPERTY_VALUE_MAX];
- property_get("ro.kernel.qemu", propQemu, "");
- if (!strncmp(propQemu, "1", 1)) {
- return mOrgSpeakerStatus;
- }
- return status;
-}
-
-void
-SpeakerManagerServiceChild::Shutdown()
-{
- if (gSpeakerManagerServiceChild) {
- gSpeakerManagerServiceChild = nullptr;
- }
-}
-
-void
-SpeakerManagerServiceChild::SetAudioChannelActive(bool aIsActive)
-{
- // Content process and switch to background with no audio and speaker forced.
- // Then disable speaker
- for (uint32_t i = 0; i < mRegisteredSpeakerManagers.Length(); i++) {
- mRegisteredSpeakerManagers[i]->SetAudioChannelActive(aIsActive);
- }
-}
-
-SpeakerManagerServiceChild::SpeakerManagerServiceChild()
-{
- MOZ_ASSERT(NS_IsMainThread());
- RefPtr<AudioChannelService> audioChannelService = AudioChannelService::GetOrCreate();
- if (audioChannelService) {
- audioChannelService->RegisterSpeakerManager(this);
- }
- MOZ_COUNT_CTOR(SpeakerManagerServiceChild);
-}
-
-SpeakerManagerServiceChild::~SpeakerManagerServiceChild()
-{
- RefPtr<AudioChannelService> audioChannelService = AudioChannelService::GetOrCreate();
- if (audioChannelService) {
- audioChannelService->UnregisterSpeakerManager(this);
- }
- MOZ_COUNT_DTOR(SpeakerManagerServiceChild);
-}
-
-void
-SpeakerManagerServiceChild::Notify()
-{
- for (uint32_t i = 0; i < mRegisteredSpeakerManagers.Length(); i++) {
- mRegisteredSpeakerManagers[i]->DispatchSimpleEvent(NS_LITERAL_STRING("speakerforcedchange"));
- }
-}
diff --git a/dom/speakermanager/SpeakerManagerServiceChild.h b/dom/speakermanager/SpeakerManagerServiceChild.h
deleted file mode 100644
index 5eb1c6afa..000000000
--- a/dom/speakermanager/SpeakerManagerServiceChild.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_SpeakerManagerServicechild_h__
-#define mozilla_dom_SpeakerManagerServicechild_h__
-
-#include "nsISupports.h"
-#include "SpeakerManagerService.h"
-
-namespace mozilla {
-namespace dom {
-/* This class is used to do the IPC to enable/disable speaker status
- Also handle the application speaker competition problem
-*/
-class SpeakerManagerServiceChild : public SpeakerManagerService
-{
-public:
- /*
- * Return null or instance which has been created.
- */
- static SpeakerManagerService* GetSpeakerManagerService();
- /*
- * Return SpeakerManagerServiceChild instance.
- * If SpeakerManagerServiceChild is not exist, create and return new one.
- */
- static SpeakerManagerService* GetOrCreateSpeakerManagerService();
- static void Shutdown();
- virtual void ForceSpeaker(bool aEnable, bool aVisible) override;
- virtual bool GetSpeakerStatus() override;
- virtual void SetAudioChannelActive(bool aIsActive) override;
- virtual void Notify() override;
-protected:
- SpeakerManagerServiceChild();
- virtual ~SpeakerManagerServiceChild();
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif
-
diff --git a/dom/speakermanager/tests/mochitest.ini b/dom/speakermanager/tests/mochitest.ini
deleted file mode 100644
index bb272adc0..000000000
--- a/dom/speakermanager/tests/mochitest.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[DEFAULT]
-
-[test_speakermanager.html]
diff --git a/dom/speakermanager/tests/test_speakermanager.html b/dom/speakermanager/tests/test_speakermanager.html
deleted file mode 100644
index 509df5e84..000000000
--- a/dom/speakermanager/tests/test_speakermanager.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <meta charset="utf-8">
- <title>Test MozSpeakerManager API</title>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none"></div>
-<pre id="test">
- <script type="application/javascript">
-
- "use strict";
-
- function testObject() {
- var mgr = new MozSpeakerManager();
- var spkforced = false;
- mgr.onspeakerforcedchange = function() {
- if (spkforced) {
- is(mgr.speakerforced, true, 'speaker should be true');
- spkforced = false;
- mgr.forcespeaker = false;
- } else {
- is(mgr.speakerforced, false, 'speaker should be false');
- SimpleTest.finish();
- }
- }
- spkforced = true;
- mgr.forcespeaker = true;
- }
-
- function startTests() {
- // Currently applicable only on FxOS
- if (navigator.userAgent.indexOf("Mobile") != -1 &&
- navigator.appVersion.indexOf("Android") == -1) {
- testObject();
- } else {
- ok(true, "MozSpeakerManager on Firefox OS only.");
- SimpleTest.finish();
- }
- }
-
- SimpleTest.waitForExplicitFinish();
- SpecialPowers.pushPermissions(
- [{ "type": "speaker-control", "allow": 1, "context": document }],
- startTests);
-
- </script>
-</pre>
-</body>
-</html>
diff --git a/dom/svg/SVGClipPathElement.cpp b/dom/svg/SVGClipPathElement.cpp
index 60d72fdf0..682d1271e 100644
--- a/dom/svg/SVGClipPathElement.cpp
+++ b/dom/svg/SVGClipPathElement.cpp
@@ -50,6 +50,13 @@ SVGClipPathElement::GetEnumInfo()
ArrayLength(sEnumInfo));
}
+bool
+SVGClipPathElement::IsUnitsObjectBoundingBox() const
+{
+ return mEnumAttributes[CLIPPATHUNITS].GetAnimValue() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+}
+
+
//----------------------------------------------------------------------
// nsIDOMNode methods
diff --git a/dom/svg/SVGClipPathElement.h b/dom/svg/SVGClipPathElement.h
index d84f5b30f..2d9f4c15e 100644
--- a/dom/svg/SVGClipPathElement.h
+++ b/dom/svg/SVGClipPathElement.h
@@ -36,6 +36,10 @@ public:
// WebIDL
already_AddRefed<SVGAnimatedEnumeration> ClipPathUnits();
+ // This is an internal method that does not flush style, and thus
+ // the answer may be out of date if there's a pending style flush.
+ bool IsUnitsObjectBoundingBox() const;
+
protected:
enum { CLIPPATHUNITS };
diff --git a/dom/svg/SVGTextContentElement.h b/dom/svg/SVGTextContentElement.h
index 905468228..5f126c811 100644
--- a/dom/svg/SVGTextContentElement.h
+++ b/dom/svg/SVGTextContentElement.h
@@ -29,6 +29,7 @@ typedef SVGGraphicsElement SVGTextContentElementBase;
class SVGTextContentElement : public SVGTextContentElementBase
{
+ friend class ::SVGTextFrame;
public:
using FragmentOrElement::TextLength;
diff --git a/dom/system/OSFileConstants.cpp b/dom/system/OSFileConstants.cpp
index 945233f4c..86377e75a 100644
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -924,16 +924,6 @@ bool DefineOSFileConstants(JSContext *cx, JS::Handle<JSObject*> global)
return false;
}
-#if defined(MOZ_WIDGET_GONK)
- JSString* strVersion = JS_NewStringCopyZ(cx, "Gonk");
- if (!strVersion){
- return false;
- }
- JS::Rooted<JS::Value> valVersion(cx, JS::StringValue(strVersion));
- if (!JS_SetProperty(cx, objSys, "Name", valVersion)) {
- return false;
- }
-#else
nsCOMPtr<nsIXULRuntime> runtime = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
if (runtime) {
nsAutoCString os;
@@ -950,7 +940,6 @@ bool DefineOSFileConstants(JSContext *cx, JS::Handle<JSObject*> global)
return false;
}
}
-#endif // defined(MOZ_WIDGET_GONK)
#if defined(DEBUG)
JS::Rooted<JS::Value> valDebug(cx, JS::TrueValue());
diff --git a/dom/system/gonk/AudioChannelManager.cpp b/dom/system/gonk/AudioChannelManager.cpp
deleted file mode 100644
index 977715a29..000000000
--- a/dom/system/gonk/AudioChannelManager.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDocument.h"
-#include "nsIDOMClassInfo.h"
-#include "nsIDOMEvent.h"
-#include "nsIDOMEventListener.h"
-#include "nsPIDOMWindow.h"
-#include "nsIDocShell.h"
-#include "nsIPermissionManager.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "AudioChannelManager.h"
-#include "mozilla/dom/AudioChannelManagerBinding.h"
-#include "mozilla/dom/nsBrowserElement.h"
-#include "mozilla/Services.h"
-
-namespace mozilla {
-namespace dom {
-namespace system {
-
-NS_IMPL_QUERY_INTERFACE_INHERITED(AudioChannelManager, DOMEventTargetHelper,
- nsIDOMEventListener)
-NS_IMPL_ADDREF_INHERITED(AudioChannelManager, DOMEventTargetHelper)
-NS_IMPL_RELEASE_INHERITED(AudioChannelManager, DOMEventTargetHelper)
-
-AudioChannelManager::AudioChannelManager()
- : mVolumeChannel(-1)
-{
- hal::RegisterSwitchObserver(hal::SWITCH_HEADPHONES, this);
-}
-
-AudioChannelManager::~AudioChannelManager()
-{
- hal::UnregisterSwitchObserver(hal::SWITCH_HEADPHONES, this);
-
- nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner());
- NS_ENSURE_TRUE_VOID(target);
-
- target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
- this,
- /* useCapture = */ true);
-}
-
-void
-AudioChannelManager::Init(nsPIDOMWindowInner* aWindow)
-{
- BindToOwner(aWindow);
-
- nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
- NS_ENSURE_TRUE_VOID(target);
-
- target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
- this,
- /* useCapture = */ true,
- /* wantsUntrusted = */ false);
-}
-
-JSObject*
-AudioChannelManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
- return AudioChannelManagerBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-AudioChannelManager::Notify(const hal::SwitchEvent& aEvent)
-{
- mState = Some(aEvent.status());
-
- DispatchTrustedEvent(NS_LITERAL_STRING("headphoneschange"));
-}
-
-bool
-AudioChannelManager::SetVolumeControlChannel(const nsAString& aChannel)
-{
- if (aChannel.EqualsASCII("publicnotification")) {
- return false;
- }
-
- AudioChannel newChannel = AudioChannelService::GetAudioChannel(aChannel);
-
- // Only normal channel doesn't need permission.
- if (newChannel != AudioChannel::Normal) {
- nsCOMPtr<nsIPermissionManager> permissionManager =
- services::GetPermissionManager();
- if (!permissionManager) {
- return false;
- }
- uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
- permissionManager->TestPermissionFromWindow(GetOwner(),
- nsCString(NS_LITERAL_CSTRING("audio-channel-") +
- NS_ConvertUTF16toUTF8(aChannel)).get(), &perm);
- if (perm != nsIPermissionManager::ALLOW_ACTION) {
- return false;
- }
- }
-
- if (mVolumeChannel == (int32_t)newChannel) {
- return true;
- }
-
- mVolumeChannel = (int32_t)newChannel;
-
- NotifyVolumeControlChannelChanged();
- return true;
-}
-
-bool
-AudioChannelManager::GetVolumeControlChannel(nsAString & aChannel)
-{
- if (mVolumeChannel >= 0) {
- AudioChannelService::GetAudioChannelString(
- static_cast<AudioChannel>(mVolumeChannel),
- aChannel);
- } else {
- aChannel.AssignASCII("");
- }
-
- return true;
-}
-
-void
-AudioChannelManager::NotifyVolumeControlChannelChanged()
-{
- nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
- NS_ENSURE_TRUE_VOID(docshell);
-
- bool isActive = false;
- docshell->GetIsActive(&isActive);
-
- RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
- if (!service) {
- return;
- }
-
- if (isActive) {
- service->SetDefaultVolumeControlChannel(mVolumeChannel, isActive);
- } else {
- service->SetDefaultVolumeControlChannel(-1, isActive);
- }
-}
-
-NS_IMETHODIMP
-AudioChannelManager::HandleEvent(nsIDOMEvent* aEvent)
-{
- nsAutoString type;
- aEvent->GetType(type);
-
- if (type.EqualsLiteral("visibilitychange")) {
- NotifyVolumeControlChannelChanged();
- }
- return NS_OK;
-}
-
-void
-AudioChannelManager::GetAllowedAudioChannels(
- nsTArray<RefPtr<BrowserElementAudioChannel>>& aAudioChannels,
- ErrorResult& aRv)
-{
- MOZ_ASSERT(aAudioChannels.IsEmpty());
-
- // Only main process is supported.
- if (XRE_GetProcessType() != GeckoProcessType_Default) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
-
- nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
- if (NS_WARN_IF(!window)) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
-
- nsBrowserElement::GenerateAllowedAudioChannels(window, nullptr, nullptr,
- aAudioChannels, aRv);
- NS_WARNING_ASSERTION(!aRv.Failed(), "GenerateAllowedAudioChannels failed");
-}
-
-} // namespace system
-} // namespace dom
-} // namespace mozilla
diff --git a/dom/system/gonk/AudioChannelManager.h b/dom/system/gonk/AudioChannelManager.h
deleted file mode 100644
index a460651e7..000000000
--- a/dom/system/gonk/AudioChannelManager.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_system_AudioChannelManager_h
-#define mozilla_dom_system_AudioChannelManager_h
-
-#include "mozilla/dom/BrowserElementAudioChannel.h"
-#include "mozilla/DOMEventTargetHelper.h"
-#include "mozilla/Hal.h"
-#include "mozilla/HalTypes.h"
-#include "mozilla/Maybe.h"
-#include "AudioChannelService.h"
-
-namespace mozilla {
-namespace hal {
-class SwitchEvent;
-typedef Observer<SwitchEvent> SwitchObserver;
-} // namespace hal
-
-namespace dom {
-namespace system {
-
-class AudioChannelManager final
- : public DOMEventTargetHelper
- , public hal::SwitchObserver
- , public nsIDOMEventListener
-{
-public:
- AudioChannelManager();
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIDOMEVENTLISTENER
-
- void Notify(const hal::SwitchEvent& aEvent);
-
- void Init(nsPIDOMWindowInner* aWindow);
-
- /**
- * WebIDL Interface
- */
-
- nsPIDOMWindowInner* GetParentObject() const
- {
- return GetOwner();
- }
-
- virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
- bool Headphones()
- {
- // Bug 929139 - Remove the assert check for SWITCH_STATE_UNKNOWN.
- // If any devices (ex: emulator) didn't have the corresponding sys node for
- // headset switch state then GonkSwitch will report the unknown state.
- // So it is possible to get unknown state here.
- if (mState.isNothing()) {
- mState = Some(hal::GetCurrentSwitchState(hal::SWITCH_HEADPHONES));
- }
- return mState.value() != hal::SWITCH_STATE_OFF &&
- mState.value() != hal::SWITCH_STATE_UNKNOWN;
- }
-
- bool SetVolumeControlChannel(const nsAString& aChannel);
-
- bool GetVolumeControlChannel(nsAString& aChannel);
-
- IMPL_EVENT_HANDLER(headphoneschange)
-
- void GetAllowedAudioChannels(
- nsTArray<RefPtr<mozilla::dom::BrowserElementAudioChannel>>& aAudioChannels,
- mozilla::ErrorResult& aRv);
-
-protected:
- virtual ~AudioChannelManager();
-
-private:
- void NotifyVolumeControlChannelChanged();
-
- Maybe<hal::SwitchState> mState;
- int32_t mVolumeChannel;
-};
-
-} // namespace system
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_system_AudioChannelManager_h
diff --git a/dom/system/gonk/AudioManager.cpp b/dom/system/gonk/AudioManager.cpp
deleted file mode 100644
index 88dff13f7..000000000
--- a/dom/system/gonk/AudioManager.cpp
+++ /dev/null
@@ -1,1412 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/log.h>
-#include <cutils/properties.h>
-#include <binder/IServiceManager.h>
-
-#include "AudioChannelService.h"
-#include "AudioManager.h"
-
-#include "nsIObserverService.h"
-#include "nsISettingsService.h"
-#include "nsPrintfCString.h"
-
-#include "mozilla/Hal.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/MozPromise.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "base/message_loop.h"
-
-#include "BluetoothCommon.h"
-#include "BluetoothHfpManagerBase.h"
-
-#include "nsJSUtils.h"
-#include "nsThreadUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentUtils.h"
-#include "nsXULAppAPI.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/SettingChangeNotificationBinding.h"
-
-using namespace mozilla::dom;
-using namespace mozilla::dom::gonk;
-using namespace android;
-using namespace mozilla;
-using namespace mozilla::dom::bluetooth;
-
-#undef LOG
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args)
-
-#define HEADPHONES_STATUS_HEADSET u"headset"
-#define HEADPHONES_STATUS_HEADPHONE u"headphone"
-#define HEADPHONES_STATUS_OFF u"off"
-#define HEADPHONES_STATUS_UNKNOWN u"unknown"
-#define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
-#define MOZ_SETTINGS_CHANGE_ID "mozsettings-changed"
-#define AUDIO_CHANNEL_PROCESS_CHANGED "audio-channel-process-changed"
-#define AUDIO_POLICY_SERVICE_NAME "media.audio_policy"
-#define SETTINGS_SERVICE "@mozilla.org/settingsService;1"
-
-// Refer AudioService.java from Android
-static const uint32_t sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
- 5, // voice call
- 15, // system
- 15, // ring
- 15, // music
- 15, // alarm
- 15, // notification
- 15, // BT SCO
- 15, // enforced audible
- 15, // DTMF
- 15, // TTS
-#if ANDROID_VERSION < 19
- 15, // FM
-#endif
-};
-
-static const uint32_t sDefaultStreamVolumeTbl[AUDIO_STREAM_CNT] = {
- 3, // voice call
- 8, // system
- 8, // ring
- 8, // music
- 8, // alarm
- 8, // notification
- 8, // BT SCO
- 15, // enforced audible // XXX Handle as fixed maximum audio setting
- 8, // DTMF
- 8, // TTS
-#if ANDROID_VERSION < 19
- 8, // FM
-#endif
-};
-
-static const int32_t sStreamVolumeAliasTbl[AUDIO_STREAM_CNT] = {
- AUDIO_STREAM_VOICE_CALL, // voice call
- AUDIO_STREAM_NOTIFICATION, // system
- AUDIO_STREAM_NOTIFICATION, // ring
- AUDIO_STREAM_MUSIC, // music
- AUDIO_STREAM_ALARM, // alarm
- AUDIO_STREAM_NOTIFICATION, // notification
- AUDIO_STREAM_BLUETOOTH_SCO, // BT SCO
- AUDIO_STREAM_ENFORCED_AUDIBLE,// enforced audible
- AUDIO_STREAM_DTMF, // DTMF
- AUDIO_STREAM_TTS, // TTS
-#if ANDROID_VERSION < 19
- AUDIO_STREAM_MUSIC, // FM
-#endif
-};
-
-static const uint32_t sChannelStreamTbl[NUMBER_OF_AUDIO_CHANNELS] = {
- AUDIO_STREAM_MUSIC, // AudioChannel::Normal
- AUDIO_STREAM_MUSIC, // AudioChannel::Content
- AUDIO_STREAM_NOTIFICATION, // AudioChannel::Notification
- AUDIO_STREAM_ALARM, // AudioChannel::Alarm
- AUDIO_STREAM_VOICE_CALL, // AudioChannel::Telephony
- AUDIO_STREAM_RING, // AudioChannel::Ringer
- AUDIO_STREAM_ENFORCED_AUDIBLE,// AudioChannel::Publicnotification
- AUDIO_STREAM_SYSTEM, // AudioChannel::System
-};
-
-
-struct AudioDeviceInfo {
- /** The string the value maps to */
- const char* tag;
- /** The enum value that maps to this string */
- uint32_t value;
-};
-
-// Mappings audio output devices to strings.
-static const AudioDeviceInfo kAudioDeviceInfos[] = {
- { "earpiece", AUDIO_DEVICE_OUT_EARPIECE },
- { "speaker", AUDIO_DEVICE_OUT_SPEAKER },
- { "wired_headset", AUDIO_DEVICE_OUT_WIRED_HEADSET },
- { "wired_headphone", AUDIO_DEVICE_OUT_WIRED_HEADPHONE },
- { "bt_scoheadset", AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET },
- { "bt_a2dp", AUDIO_DEVICE_OUT_BLUETOOTH_A2DP },
-};
-
-static const int kBtSampleRate = 8000;
-
-typedef MozPromise<bool, const char*, true> VolumeInitPromise;
-
-namespace mozilla {
-namespace dom {
-namespace gonk {
-
-/**
- * We have five sound volume settings from UX spec,
- * You can see more informations in Bug1068219.
- * (1) Media : music, video, FM ...
- * (2) Notification : ringer, notification ...
- * (3) Alarm : alarm
- * (4) Telephony : GSM call, WebRTC call
- * (5) Bluetooth SCO : SCO call
- **/
-struct VolumeData {
- const char* mChannelName;
- int32_t mStreamType;
-};
-
-static const VolumeData gVolumeData[] = {
- {"audio.volume.content", AUDIO_STREAM_MUSIC},
- {"audio.volume.notification", AUDIO_STREAM_NOTIFICATION},
- {"audio.volume.alarm", AUDIO_STREAM_ALARM},
- {"audio.volume.telephony", AUDIO_STREAM_VOICE_CALL},
- {"audio.volume.bt_sco", AUDIO_STREAM_BLUETOOTH_SCO}
-};
-
-class RunnableCallTask : public Runnable
-{
-public:
- explicit RunnableCallTask(nsIRunnable* aRunnable)
- : mRunnable(aRunnable) {}
-
- NS_IMETHOD Run() override
- {
- return mRunnable->Run();
- }
-protected:
- nsCOMPtr<nsIRunnable> mRunnable;
-};
-
-nsCOMPtr<nsISettingsServiceLock>
-GetSettingServiceLock()
-{
- nsresult rv;
- nsCOMPtr<nsISettingsService> service = do_GetService(SETTINGS_SERVICE, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
- }
-
- nsCOMPtr<nsISettingsServiceLock> lock;
- rv = service->CreateLock(nullptr, getter_AddRefs(lock));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
- }
- return lock.forget();
-}
-
-#if ANDROID_VERSION >= 21
-class GonkAudioPortCallback : public AudioSystem::AudioPortCallback
-{
-public:
- virtual void onAudioPortListUpdate()
- {
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([]() {
- MOZ_ASSERT(NS_IsMainThread());
- RefPtr<AudioManager> audioManager = AudioManager::GetInstance();
- NS_ENSURE_TRUE(audioManager.get(), );
- audioManager->UpdateCachedActiveDevicesForStreams();
- audioManager->MaybeUpdateVolumeSettingToDatabase();
- });
- NS_DispatchToMainThread(runnable);
- }
- virtual void onAudioPatchListUpdate() { }
- virtual void onServiceDied() { }
-};
-#endif
-
-void
-AudioManager::HandleAudioFlingerDied()
-{
- //Disable volume change notification
- mIsVolumeInited = false;
-
- uint32_t attempt;
- for (attempt = 0; attempt < 50; attempt++) {
- if (defaultServiceManager()->checkService(String16(AUDIO_POLICY_SERVICE_NAME)) != 0) {
- break;
- }
- LOG("AudioPolicyService is dead! attempt=%d", attempt);
- usleep(1000 * 200);
- }
-
- MOZ_RELEASE_ASSERT(attempt < 50);
-
- // Indicate to audio HAL that we start the reconfiguration phase after a media
- // server crash
- AudioSystem::setParameters(0, String8("restarting=true"));
-
- // Restore device connection states
- SetAllDeviceConnectionStates();
-
- // Restore call state
-#if ANDROID_VERSION < 17
- AudioSystem::setPhoneState(mPhoneState);
-#else
- AudioSystem::setPhoneState(static_cast<audio_mode_t>(mPhoneState));
-#endif
-
- // Restore master volume
- AudioSystem::setMasterVolume(1.0);
-
- // Restore stream volumes
- for (uint32_t streamType = 0; streamType < AUDIO_STREAM_CNT; ++streamType) {
- mStreamStates[streamType]->InitStreamVolume();
- mStreamStates[streamType]->RestoreVolumeIndexToAllDevices();
- }
-
- // Indicate the end of reconfiguration phase to audio HAL
- AudioSystem::setParameters(0, String8("restarting=true"));
-
- // Enable volume change notification
- mIsVolumeInited = true;
- mAudioOutDevicesUpdated = 0;
- MaybeUpdateVolumeSettingToDatabase(true);
-}
-
-class VolumeInitCallback final : public nsISettingsServiceCallback
-{
-public:
- NS_DECL_ISUPPORTS
-
- VolumeInitCallback()
- : mInitCounter(0)
- {
- mPromise = mPromiseHolder.Ensure(__func__);
- }
-
- RefPtr<VolumeInitPromise> GetPromise() const
- {
- return mPromise;
- }
-
- NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
- {
- RefPtr<AudioManager> audioManager = AudioManager::GetInstance();
- MOZ_ASSERT(audioManager);
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- NS_ConvertASCIItoUTF16 volumeType(gVolumeData[idx].mChannelName);
- if (StringBeginsWith(aName, volumeType)) {
- uint32_t device = GetDeviceFromSettingName(aName);
- MOZ_ASSERT(device != AUDIO_DEVICE_NONE);
- if (aResult.isInt32()) {
- int32_t stream = gVolumeData[idx].mStreamType;
- uint32_t volIndex = aResult.toInt32();
- nsresult rv = audioManager->ValidateVolumeIndex(stream, volIndex);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- mPromiseHolder.Reject("Error : invalid volume index.", __func__);
- return rv;
- }
- audioManager->SetStreamVolumeForDevice(stream, volIndex, device);
- }
-
- if (++mInitCounter == MOZ_ARRAY_LENGTH(kAudioDeviceInfos) * MOZ_ARRAY_LENGTH(gVolumeData)) {
- mPromiseHolder.Resolve(true, __func__);
- }
- return NS_OK;
- }
- }
- mPromiseHolder.Reject("Error : unexpected audio init event.", __func__);
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(const nsAString& aName)
- {
- mPromiseHolder.Reject(NS_ConvertUTF16toUTF8(aName).get(), __func__);
- return NS_OK;
- }
-
-protected:
- ~VolumeInitCallback() {}
-
- uint32_t GetDeviceFromSettingName(const nsAString& aName) const
- {
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(kAudioDeviceInfos); ++idx) {
- NS_ConvertASCIItoUTF16 device(kAudioDeviceInfos[idx].tag);
- if (StringEndsWith(aName, device)) {
- return kAudioDeviceInfos[idx].value;
- }
- }
- return AUDIO_DEVICE_NONE;
- }
-
- RefPtr<VolumeInitPromise> mPromise;
- MozPromiseHolder<VolumeInitPromise> mPromiseHolder;
- uint32_t mInitCounter;
-};
-
-NS_IMPL_ISUPPORTS(VolumeInitCallback, nsISettingsServiceCallback)
-
-static void
-BinderDeadCallback(status_t aErr)
-{
- if (aErr != DEAD_OBJECT) {
- return;
- }
-
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([]() {
- MOZ_ASSERT(NS_IsMainThread());
- RefPtr<AudioManager> audioManager = AudioManager::GetInstance();
- NS_ENSURE_TRUE(audioManager.get(), );
- audioManager->HandleAudioFlingerDied();
- });
-
- NS_DispatchToMainThread(runnable);
-}
-
-bool
-AudioManager::IsFmOutConnected()
-{
- return mConnectedDevices.Get(AUDIO_DEVICE_OUT_FM, nullptr);
-}
-
-NS_IMPL_ISUPPORTS(AudioManager, nsIAudioManager, nsIObserver)
-
-void
-AudioManager::AudioOutDeviceUpdated(uint32_t aDevice)
-{
- MOZ_ASSERT(audio_is_output_device(aDevice));
- mAudioOutDevicesUpdated |= aDevice;
-}
-
-void
-AudioManager::UpdateHeadsetConnectionState(hal::SwitchState aState)
-{
- bool headphoneConnected = mConnectedDevices.Get(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
- nullptr);
- bool headsetConnected = mConnectedDevices.Get(AUDIO_DEVICE_OUT_WIRED_HEADSET,
- nullptr);
- if (aState == hal::SWITCH_STATE_HEADSET) {
- UpdateDeviceConnectionState(true,
- AUDIO_DEVICE_OUT_WIRED_HEADSET,
- NS_LITERAL_CSTRING(""));
- } else if (aState == hal::SWITCH_STATE_HEADPHONE) {
- UpdateDeviceConnectionState(true,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
- NS_LITERAL_CSTRING(""));
- } else if (aState == hal::SWITCH_STATE_OFF) {
- if (headsetConnected) {
- UpdateDeviceConnectionState(false,
- AUDIO_DEVICE_OUT_WIRED_HEADSET,
- NS_LITERAL_CSTRING(""));
- }
- if (headphoneConnected) {
- UpdateDeviceConnectionState(false,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
- NS_LITERAL_CSTRING(""));
- }
- }
-}
-
-void
-AudioManager::UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName)
-{
-#if ANDROID_VERSION >= 15
- bool isConnected = mConnectedDevices.Get(aDevice, nullptr);
- if (isConnected && !aIsConnected) {
- AudioSystem::setDeviceConnectionState(static_cast<audio_devices_t>(aDevice),
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- aDeviceName.get());
- mConnectedDevices.Remove(aDevice);
- } else if(!isConnected && aIsConnected) {
- AudioSystem::setDeviceConnectionState(static_cast<audio_devices_t>(aDevice),
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- aDeviceName.get());
- mConnectedDevices.Put(aDevice, aDeviceName);
- }
-#if ANDROID_VERSION < 21
- // Manually call it, since AudioPortCallback is not supported.
- // Current volumes might be changed by updating active devices in android
- // AudioPolicyManager.
- MaybeUpdateVolumeSettingToDatabase();
-#endif
-#else
- NS_NOTREACHED("Doesn't support audio routing on GB version");
-#endif
-}
-
-void
-AudioManager::SetAllDeviceConnectionStates()
-{
- for (auto iter = mConnectedDevices.Iter(); !iter.Done(); iter.Next()) {
- const uint32_t& device = iter.Key();
- nsCString& deviceAddress = iter.Data();
- AudioSystem::setDeviceConnectionState(static_cast<audio_devices_t>(device),
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- deviceAddress.get());
- }
-#if ANDROID_VERSION < 21
- // Manually call it, since AudioPortCallback is not supported.
- // Current volumes might be changed by updating active devices in android
- // AudioPolicyManager.
- MaybeUpdateVolumeSettingToDatabase(true);
-#endif
-}
-
-void
-AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject,
- const char* aTopic,
- const nsCString aAddress)
-{
-#ifdef MOZ_B2G_BT
- bool isConnected = false;
- if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
- BluetoothHfpManagerBase* hfp =
- static_cast<BluetoothHfpManagerBase*>(aSubject);
- isConnected = hfp->IsScoConnected();
- } else {
- BluetoothProfileManagerBase* profile =
- static_cast<BluetoothProfileManagerBase*>(aSubject);
- isConnected = profile->IsConnected();
- }
-
- if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
- if (isConnected) {
- String8 cmd;
- cmd.appendFormat("bt_samplerate=%d", kBtSampleRate);
- AudioSystem::setParameters(0, cmd);
- SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_BT_SCO);
- } else {
- int32_t force;
- GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &force);
- if (force == nsIAudioManager::FORCE_BT_SCO) {
- SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE);
- }
- }
- } else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) {
- if (!isConnected && mA2dpSwitchDone) {
- RefPtr<AudioManager> self = this;
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([self, isConnected, aAddress]() {
- if (self->mA2dpSwitchDone) {
- return;
- }
- self->UpdateDeviceConnectionState(isConnected,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- aAddress);
-
- String8 cmd("bluetooth_enabled=false");
- AudioSystem::setParameters(0, cmd);
- cmd.setTo("A2dpSuspended=true");
- AudioSystem::setParameters(0, cmd);
- self->mA2dpSwitchDone = true;
- });
- MessageLoop::current()->PostDelayedTask(
- MakeAndAddRef<RunnableCallTask>(runnable), 1000);
-
- mA2dpSwitchDone = false;
- } else {
- UpdateDeviceConnectionState(isConnected,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- aAddress);
- String8 cmd("bluetooth_enabled=true");
- AudioSystem::setParameters(0, cmd);
- cmd.setTo("A2dpSuspended=false");
- AudioSystem::setParameters(0, cmd);
- mA2dpSwitchDone = true;
-#if ANDROID_VERSION >= 17
- if (AudioSystem::getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_NO_BT_A2DP) {
- SetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_NONE);
- }
-#endif
- }
- mBluetoothA2dpEnabled = isConnected;
- } else if (!strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
- UpdateDeviceConnectionState(isConnected,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
- aAddress);
- UpdateDeviceConnectionState(isConnected,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
- aAddress);
- } else if (!strcmp(aTopic, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID)) {
- String8 cmd;
- BluetoothHfpManagerBase* hfp =
- static_cast<BluetoothHfpManagerBase*>(aSubject);
- if (hfp->IsNrecEnabled()) {
- cmd.setTo("bt_headset_name=<unknown>;bt_headset_nrec=on");
- AudioSystem::setParameters(0, cmd);
- } else {
- cmd.setTo("bt_headset_name=<unknown>;bt_headset_nrec=off");
- AudioSystem::setParameters(0, cmd);
- }
- }
-#endif
-}
-
-void
-AudioManager::HandleAudioChannelProcessChanged()
-{
- // Note: If the user answers a VoIP call (e.g. WebRTC calls) during the
- // telephony call (GSM/CDMA calls) the audio manager won't set the
- // PHONE_STATE_IN_COMMUNICATION audio state. Once the telephony call finishes
- // the RIL plumbing sets the PHONE_STATE_NORMAL audio state. This seems to be
- // an issue for the VoIP call but it is not. Once the RIL plumbing sets the
- // the PHONE_STATE_NORMAL audio state the AudioManager::mPhoneAudioAgent
- // member will call the NotifyStoppedPlaying() method causing that this function will
- // be called again and therefore the audio manager sets the
- // PHONE_STATE_IN_COMMUNICATION audio state.
-
- if ((mPhoneState == PHONE_STATE_IN_CALL) ||
- (mPhoneState == PHONE_STATE_RINGTONE)) {
- return;
- }
-
- RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
- bool telephonyChannelIsActive = service && service->TelephonyChannelIsActive();
- telephonyChannelIsActive ? SetPhoneState(PHONE_STATE_IN_COMMUNICATION) :
- SetPhoneState(PHONE_STATE_NORMAL);
-}
-
-nsresult
-AudioManager::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- if ((strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID) == 0) ||
- (strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID) == 0) ||
- (strcmp(aTopic, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID) == 0) ||
- (strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID) == 0)) {
- nsCString address = NS_ConvertUTF16toUTF8(nsDependentString(aData));
- if (address.IsEmpty()) {
- NS_WARNING(nsPrintfCString("Invalid address of %s", aTopic).get());
- return NS_ERROR_FAILURE;
- }
-
- HandleBluetoothStatusChanged(aSubject, aTopic, address);
- return NS_OK;
- }
-
- else if (!strcmp(aTopic, AUDIO_CHANNEL_PROCESS_CHANGED)) {
- HandleAudioChannelProcessChanged();
- return NS_OK;
- }
-
- // To process the volume control on each volume categories according to
- // change of settings
- else if (!strcmp(aTopic, MOZ_SETTINGS_CHANGE_ID)) {
- RootedDictionary<dom::SettingChangeNotification> setting(RootingCx());
- if (!WrappedJSToDictionary(aSubject, setting)) {
- return NS_OK;
- }
- if (!StringBeginsWith(setting.mKey, NS_LITERAL_STRING("audio.volume."))) {
- return NS_OK;
- }
- if (!setting.mValue.isNumber()) {
- return NS_OK;
- }
-
- uint32_t volIndex = setting.mValue.toNumber();
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- if (setting.mKey.EqualsASCII(gVolumeData[idx].mChannelName)) {
- SetStreamVolumeIndex(gVolumeData[idx].mStreamType, volIndex);
- return NS_OK;
- }
- }
- }
-
- NS_WARNING("Unexpected topic in AudioManager");
- return NS_ERROR_FAILURE;
-}
-
-static void
-NotifyHeadphonesStatus(hal::SwitchState aState)
-{
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- if (aState == hal::SWITCH_STATE_HEADSET) {
- obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_HEADSET);
- } else if (aState == hal::SWITCH_STATE_HEADPHONE) {
- obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_HEADPHONE);
- } else if (aState == hal::SWITCH_STATE_OFF) {
- obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_OFF);
- } else {
- obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_UNKNOWN);
- }
- }
-}
-
-class HeadphoneSwitchObserver : public hal::SwitchObserver
-{
-public:
- void Notify(const hal::SwitchEvent& aEvent) {
- RefPtr<AudioManager> audioManager = AudioManager::GetInstance();
- MOZ_ASSERT(audioManager);
- audioManager->HandleHeadphoneSwitchEvent(aEvent);
- }
-};
-
-void
-AudioManager::HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent)
-{
- NotifyHeadphonesStatus(aEvent.status());
- // When user pulled out the headset, a delay of routing here can avoid the leakage of audio from speaker.
- if (aEvent.status() == hal::SWITCH_STATE_OFF && mSwitchDone) {
-
- RefPtr<AudioManager> self = this;
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([self]() {
- if (self->mSwitchDone) {
- return;
- }
- self->UpdateHeadsetConnectionState(hal::SWITCH_STATE_OFF);
- self->mSwitchDone = true;
- });
- MessageLoop::current()->PostDelayedTask(
- MakeAndAddRef<RunnableCallTask>(runnable), 1000);
- mSwitchDone = false;
- } else if (aEvent.status() != hal::SWITCH_STATE_OFF) {
- UpdateHeadsetConnectionState(aEvent.status());
- mSwitchDone = true;
- }
- // Handle the coexistence of a2dp / headset device, latest one wins.
-#if ANDROID_VERSION >= 17
- int32_t forceUse = 0;
- GetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, &forceUse);
- if (aEvent.status() != hal::SWITCH_STATE_OFF && mBluetoothA2dpEnabled) {
- SetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_NO_BT_A2DP);
- } else if (forceUse == AUDIO_POLICY_FORCE_NO_BT_A2DP) {
- SetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_NONE);
- }
-#endif
-}
-
-AudioManager::AudioManager()
- : mPhoneState(PHONE_STATE_CURRENT)
- , mIsVolumeInited(false)
- , mAudioOutDevicesUpdated(0)
- , mSwitchDone(true)
-#if defined(MOZ_B2G_BT) || ANDROID_VERSION >= 17
- , mBluetoothA2dpEnabled(false)
-#endif
-#ifdef MOZ_B2G_BT
- , mA2dpSwitchDone(true)
-#endif
- , mObserver(new HeadphoneSwitchObserver())
-{
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(kAudioDeviceInfos); ++idx) {
- mAudioDeviceTableIdMaps.Put(kAudioDeviceInfos[idx].value, idx);
- }
-
- AudioSystem::setErrorCallback(BinderDeadCallback);
-#if ANDROID_VERSION >= 21
- android::sp<GonkAudioPortCallback> callback = new GonkAudioPortCallback();
- AudioSystem::setAudioPortCallback(callback);
-#endif
-
- // Create VolumeStreamStates
- for (uint32_t loop = 0; loop < AUDIO_STREAM_CNT; ++loop) {
- VolumeStreamState* streamState =
- new VolumeStreamState(*this, static_cast<audio_stream_type_t>(loop));
- mStreamStates.AppendElement(streamState);
- }
- // Initialize stream volumes with default values
- for (int32_t streamType = 0; streamType < AUDIO_STREAM_MAX; streamType++) {
- uint32_t volIndex = sDefaultStreamVolumeTbl[streamType];
- SetStreamVolumeForDevice(streamType, volIndex, AUDIO_DEVICE_OUT_DEFAULT);
- }
- UpdateCachedActiveDevicesForStreams();
-
- RegisterSwitchObserver(hal::SWITCH_HEADPHONES, mObserver);
- // Initialize headhone/heaset status
- UpdateHeadsetConnectionState(hal::GetCurrentSwitchState(hal::SWITCH_HEADPHONES));
- NotifyHeadphonesStatus(hal::GetCurrentSwitchState(hal::SWITCH_HEADPHONES));
-
- // Get the initial volume index from settings DB during boot up.
- InitVolumeFromDatabase();
-
- // Gecko only control stream volume not master so set to default value
- // directly.
- AudioSystem::setMasterVolume(1.0);
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- NS_ENSURE_TRUE_VOID(obs);
- if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_SCO_STATUS_CHANGED_ID, false))) {
- NS_WARNING("Failed to add bluetooth sco status changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_A2DP_STATUS_CHANGED_ID, false))) {
- NS_WARNING("Failed to add bluetooth a2dp status changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID, false))) {
- NS_WARNING("Failed to add bluetooth hfp status changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID, false))) {
- NS_WARNING("Failed to add bluetooth hfp NREC status changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, MOZ_SETTINGS_CHANGE_ID, false))) {
- NS_WARNING("Failed to add mozsettings-changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, AUDIO_CHANNEL_PROCESS_CHANGED, false))) {
- NS_WARNING("Failed to add audio-channel-process-changed observer!");
- }
-
-}
-
-AudioManager::~AudioManager() {
- AudioSystem::setErrorCallback(nullptr);
-#if ANDROID_VERSION >= 21
- AudioSystem::setAudioPortCallback(nullptr);
-#endif
- hal::UnregisterSwitchObserver(hal::SWITCH_HEADPHONES, mObserver);
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- NS_ENSURE_TRUE_VOID(obs);
- if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_SCO_STATUS_CHANGED_ID))) {
- NS_WARNING("Failed to remove bluetooth sco status changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_A2DP_STATUS_CHANGED_ID))) {
- NS_WARNING("Failed to remove bluetooth a2dp status changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID))) {
- NS_WARNING("Failed to remove bluetooth hfp status changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID))) {
- NS_WARNING("Failed to remove bluetooth hfp NREC status changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, MOZ_SETTINGS_CHANGE_ID))) {
- NS_WARNING("Failed to remove mozsettings-changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, AUDIO_CHANNEL_PROCESS_CHANGED))) {
- NS_WARNING("Failed to remove audio-channel-process-changed!");
- }
-}
-
-static StaticRefPtr<AudioManager> sAudioManager;
-
-already_AddRefed<AudioManager>
-AudioManager::GetInstance()
-{
- // Avoid createing AudioManager from content process.
- if (!XRE_IsParentProcess()) {
- MOZ_CRASH("Non-chrome processes should not get here.");
- }
-
- // Avoid createing multiple AudioManager instance inside main process.
- if (!sAudioManager) {
- sAudioManager = new AudioManager();
- ClearOnShutdown(&sAudioManager);
- }
-
- RefPtr<AudioManager> audioMgr = sAudioManager.get();
- return audioMgr.forget();
-}
-
-NS_IMETHODIMP
-AudioManager::GetMicrophoneMuted(bool* aMicrophoneMuted)
-{
-
- if (AudioSystem::isMicrophoneMuted(aMicrophoneMuted)) {
- return NS_ERROR_FAILURE;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-AudioManager::SetMicrophoneMuted(bool aMicrophoneMuted)
-{
- if (!AudioSystem::muteMicrophone(aMicrophoneMuted)) {
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-AudioManager::GetPhoneState(int32_t* aState)
-{
- *aState = mPhoneState;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-AudioManager::SetPhoneState(int32_t aState)
-{
- if (mPhoneState == aState) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (obs) {
- nsString state;
- state.AppendInt(aState);
- obs->NotifyObservers(nullptr, "phone-state-changed", state.get());
- }
-
-#if ANDROID_VERSION < 17
- if (AudioSystem::setPhoneState(aState)) {
-#else
- if (AudioSystem::setPhoneState(static_cast<audio_mode_t>(aState))) {
-#endif
- return NS_ERROR_FAILURE;
- }
-
-#if ANDROID_VERSION < 21
- // Manually call it, since AudioPortCallback is not supported.
- // Current volumes might be changed by updating active devices in android
- // AudioPolicyManager.
- MaybeUpdateVolumeSettingToDatabase();
-#endif
- mPhoneState = aState;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-AudioManager::SetForceForUse(int32_t aUsage, int32_t aForce)
-{
-#if ANDROID_VERSION >= 15
- status_t status = AudioSystem::setForceUse(
- (audio_policy_force_use_t)aUsage,
- (audio_policy_forced_cfg_t)aForce);
-#if ANDROID_VERSION < 21
- // Manually call it, since AudioPortCallback is not supported.
- // Current volumes might be changed by updating active devices in android
- // AudioPolicyManager.
- MaybeUpdateVolumeSettingToDatabase();
-#endif
- return status ? NS_ERROR_FAILURE : NS_OK;
-#else
- NS_NOTREACHED("Doesn't support force routing on GB version");
- return NS_ERROR_UNEXPECTED;
-#endif
-}
-
-NS_IMETHODIMP
-AudioManager::GetForceForUse(int32_t aUsage, int32_t* aForce) {
-#if ANDROID_VERSION >= 15
- *aForce = AudioSystem::getForceUse((audio_policy_force_use_t)aUsage);
- return NS_OK;
-#else
- NS_NOTREACHED("Doesn't support force routing on GB version");
- return NS_ERROR_UNEXPECTED;
-#endif
-}
-
-NS_IMETHODIMP
-AudioManager::SetAudioChannelVolume(uint32_t aChannel, uint32_t aIndex)
-{
- if (aChannel >= NUMBER_OF_AUDIO_CHANNELS) {
- return NS_ERROR_INVALID_ARG;
- }
-
- return SetStreamVolumeIndex(sChannelStreamTbl[aChannel], aIndex);
-}
-
-NS_IMETHODIMP
-AudioManager::GetAudioChannelVolume(uint32_t aChannel, uint32_t* aIndex)
-{
- if (aChannel >= NUMBER_OF_AUDIO_CHANNELS) {
- return NS_ERROR_INVALID_ARG;
- }
-
- if (!aIndex) {
- return NS_ERROR_NULL_POINTER;
- }
-
- return GetStreamVolumeIndex(sChannelStreamTbl[aChannel], aIndex);
-}
-
-NS_IMETHODIMP
-AudioManager::GetMaxAudioChannelVolume(uint32_t aChannel, uint32_t* aMaxIndex)
-{
- if (aChannel >= NUMBER_OF_AUDIO_CHANNELS) {
- return NS_ERROR_INVALID_ARG;
- }
-
- if (!aMaxIndex) {
- return NS_ERROR_NULL_POINTER;
- }
-
- *aMaxIndex = mStreamStates[sChannelStreamTbl[aChannel]]->GetMaxIndex();
- return NS_OK;
-}
-
-nsresult
-AudioManager::ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const
-{
- if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
- return NS_ERROR_INVALID_ARG;
- }
-
- uint32_t maxIndex = mStreamStates[aStream]->GetMaxIndex();
- if (aIndex > maxIndex) {
- return NS_ERROR_FAILURE;
- }
- return NS_OK;
-}
-
-nsresult
-AudioManager::SetStreamVolumeForDevice(int32_t aStream,
- uint32_t aIndex,
- uint32_t aDevice)
-{
- if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
- return NS_ERROR_INVALID_ARG;
- }
-
- int32_t streamAlias = sStreamVolumeAliasTbl[aStream];
- VolumeStreamState* streamState = mStreamStates[streamAlias].get();
- return streamState->SetVolumeIndexToAliasStreams(aIndex, aDevice);
-}
-
-nsresult
-AudioManager::SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex)
-{
- if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
- return NS_ERROR_INVALID_ARG;
- }
-
- int32_t streamAlias = sStreamVolumeAliasTbl[aStream];
-
- nsresult rv;
- for (int32_t streamType = 0; streamType < AUDIO_STREAM_MAX; streamType++) {
- if (streamAlias == sStreamVolumeAliasTbl[streamType]) {
- rv = mStreamStates[streamType]->SetVolumeIndexToActiveDevices(aIndex);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- // AUDIO_STREAM_FM is not used on recent gonk.
- // AUDIO_STREAM_MUSIC is used for FM radio volume control.
-#if ANDROID_VERSION < 19
- if (streamAlias == AUDIO_STREAM_MUSIC && IsFmOutConnected()) {
- rv = mStreamStates[AUDIO_STREAM_FM]->
- SetVolumeIndex(aIndex, AUDIO_DEVICE_OUT_FM);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
-#endif
-
- MaybeUpdateVolumeSettingToDatabase();
- return NS_OK;
-}
-
-nsresult
-AudioManager::GetStreamVolumeIndex(int32_t aStream, uint32_t *aIndex)
-{
- if (!aIndex) {
- return NS_ERROR_INVALID_ARG;
- }
-
- if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
- return NS_ERROR_INVALID_ARG;
- }
-
- *aIndex = mStreamStates[aStream]->GetVolumeIndex();
- return NS_OK;
-}
-
-nsAutoCString
-AudioManager::AppendDeviceToVolumeSetting(const char* aName, uint32_t aDevice)
-{
- nsAutoCString topic;
- topic.Assign(aName);
- topic.Append(".");
- uint32_t index = 0;
- DebugOnly<bool> exist = mAudioDeviceTableIdMaps.Get(aDevice, &index);
- MOZ_ASSERT(exist);
- topic.Append(kAudioDeviceInfos[index].tag);
- return topic;
-}
-
-void
-AudioManager::InitVolumeFromDatabase()
-{
- nsresult rv;
- nsCOMPtr<nsISettingsService> service = do_GetService(SETTINGS_SERVICE, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- nsCOMPtr<nsISettingsServiceLock> lock;
- rv = service->CreateLock(nullptr, getter_AddRefs(lock));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- RefPtr<VolumeInitCallback> callback = new VolumeInitCallback();
- MOZ_ASSERT(callback);
- callback->GetPromise()->Then(AbstractThread::MainThread(), __func__, this,
- &AudioManager::InitDeviceVolumeSucceeded,
- &AudioManager::InitDeviceVolumeFailed);
-
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- for (uint32_t idx2 = 0; idx2 < MOZ_ARRAY_LENGTH(kAudioDeviceInfos); ++idx2) {
- lock->Get(AppendDeviceToVolumeSetting(gVolumeData[idx].mChannelName,
- kAudioDeviceInfos[idx2].value).get(),
- callback);
- }
- }
-}
-
-void
-AudioManager::InitDeviceVolumeSucceeded()
-{
- mIsVolumeInited = true;
- MaybeUpdateVolumeSettingToDatabase(true);
-}
-
-void
-AudioManager::InitDeviceVolumeFailed(const char* aError)
-{
- // Default volume of AUDIO_DEVICE_OUT_DEFAULT is already set.
- mIsVolumeInited = true;
- MaybeUpdateVolumeSettingToDatabase(true);
- NS_WARNING(aError);
-}
-
-void
-AudioManager::MaybeUpdateVolumeSettingToDatabase(bool aForce)
-{
- if (!mIsVolumeInited) {
- return;
- }
-
- nsCOMPtr<nsISettingsServiceLock> lock = GetSettingServiceLock();
- if (NS_WARN_IF(!lock)) {
- return;
- }
-
- // Send events to update the Gaia volumes
- JS::Rooted<JS::Value> value(RootingCx());
- uint32_t volume = 0;
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- int32_t streamType = gVolumeData[idx].mStreamType;
- VolumeStreamState* streamState = mStreamStates[streamType].get();
- if(!aForce && !streamState->IsDevicesChanged()) {
- continue;
- }
- // Get volume index of active device.
- volume = streamState->GetVolumeIndex();
- value.setInt32(volume);
- lock->Set(gVolumeData[idx].mChannelName, value, nullptr, nullptr);
- }
-
- // For reducing the code dependency, Gaia doesn't need to know the
- // device volume, it only need to care about different volume categories.
- // However, we need to send the setting volume to the permanent database,
- // so that we can store the volume setting even if the phone reboots.
-
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- int32_t streamType = gVolumeData[idx].mStreamType;
- VolumeStreamState* streamState = mStreamStates[streamType].get();
-
- if(!streamState->IsVolumeIndexesChanged()) {
- continue;
- }
-
- uint32_t remainingDevices = mAudioOutDevicesUpdated;
- for (uint32_t i = 0; remainingDevices != 0; i++) {
- uint32_t device = (1 << i);
- if ((device & remainingDevices) == 0) {
- continue;
- }
- remainingDevices &= ~device;
- if (!mAudioDeviceTableIdMaps.Get(device, nullptr)) {
- continue;
- }
- volume = streamState->GetVolumeIndex(device);
- value.setInt32(volume);
- lock->Set(AppendDeviceToVolumeSetting(gVolumeData[idx].mChannelName,
- device).get(),
- value, nullptr, nullptr);
- }
- }
-
- // Clear changed flags
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- int32_t streamType = gVolumeData[idx].mStreamType;
- mStreamStates[streamType]->ClearDevicesChanged();
- mStreamStates[streamType]->ClearVolumeIndexesChanged();
- }
- // Clear mAudioOutDevicesUpdated
- mAudioOutDevicesUpdated = 0;
-}
-
-void
-AudioManager::UpdateCachedActiveDevicesForStreams()
-{
- // This function updates cached active devices for streams.
- // It is used for optimization of GetDevicesForStream() since L.
- // AudioManager could know when active devices
- // are changed in AudioPolicyManager by onAudioPortListUpdate().
- // Except it, AudioManager normally do not need to ask AuidoPolicyManager
- // about current active devices of streams and could use cached values.
- // Before L, onAudioPortListUpdate() does not exist and GetDevicesForStream()
- // does not use the cache. Therefore this function do nothing.
-#if ANDROID_VERSION >= 21
- for (int32_t streamType = 0; streamType < AUDIO_STREAM_MAX; streamType++) {
- // Update cached active devices of stream
- mStreamStates[streamType]->IsDevicesChanged(false /* aFromCache */);
- }
-#endif
-}
-
-uint32_t
-AudioManager::GetDevicesForStream(int32_t aStream, bool aFromCache)
-{
-#if ANDROID_VERSION >= 21
- // Since Lollipop, devices update could be notified by AudioPortCallback.
- // Cached values can be used if there is no update.
- if (aFromCache) {
- return mStreamStates[aStream]->GetLastDevices();
- }
-#endif
-
-#if ANDROID_VERSION >= 17
- audio_devices_t devices =
- AudioSystem::getDevicesForStream(static_cast<audio_stream_type_t>(aStream));
-
- return static_cast<uint32_t>(devices);
-#else
- // Per audio out device volume is not supported.
- // Use AUDIO_DEVICE_OUT_SPEAKER just to store audio volume to DB.
- return AUDIO_DEVICE_OUT_SPEAKER;
-#endif
-}
-
-uint32_t
-AudioManager::GetDeviceForStream(int32_t aStream)
-{
- uint32_t devices =
- GetDevicesForStream(static_cast<audio_stream_type_t>(aStream));
- uint32_t device = SelectDeviceFromDevices(devices);
- return device;
-}
-
-/* static */ uint32_t
-AudioManager::SelectDeviceFromDevices(uint32_t aOutDevices)
-{
- uint32_t device = aOutDevices;
-
- // See android AudioService.getDeviceForStream().
- // AudioPolicyManager expects it.
- // See also android AudioPolicyManager::getDeviceForVolume().
- if ((device & (device - 1)) != 0) {
- // Multiple device selection.
- if ((device & AUDIO_DEVICE_OUT_SPEAKER) != 0) {
- device = AUDIO_DEVICE_OUT_SPEAKER;
-#if ANDROID_VERSION >= 21
- } else if ((device & AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
- device = AUDIO_DEVICE_OUT_HDMI_ARC;
- } else if ((device & AUDIO_DEVICE_OUT_SPDIF) != 0) {
- device = AUDIO_DEVICE_OUT_SPDIF;
- } else if ((device & AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
- device = AUDIO_DEVICE_OUT_AUX_LINE;
-#endif
- } else {
- device &= AUDIO_DEVICE_OUT_ALL_A2DP;
- }
- }
- MOZ_ASSERT(audio_is_output_device(device));
- return device;
-}
-AudioManager::VolumeStreamState::VolumeStreamState(AudioManager& aManager,
- int32_t aStreamType)
- : mManager(aManager)
- , mStreamType(aStreamType)
- , mLastDevices(0)
- , mIsDevicesChanged(true)
- , mIsVolumeIndexesChanged(true)
-{
- InitStreamVolume();
-}
-
-bool
-AudioManager::VolumeStreamState::IsDevicesChanged(bool aFromCache)
-{
- uint32_t devices = mManager.GetDevicesForStream(mStreamType, aFromCache);
- if (devices != mLastDevices) {
- mLastDevices = devices;
- mIsDevicesChanged = true;
- }
- return mIsDevicesChanged;
-}
-
-void
-AudioManager::VolumeStreamState::ClearDevicesChanged()
-{
- mIsDevicesChanged = false;
-}
-
-bool
-AudioManager::VolumeStreamState::IsVolumeIndexesChanged()
-{
- return mIsVolumeIndexesChanged;
-}
-
-void
-AudioManager::VolumeStreamState::ClearVolumeIndexesChanged()
-{
- mIsVolumeIndexesChanged = false;
-}
-
-void
-AudioManager::VolumeStreamState::InitStreamVolume()
-{
- AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(mStreamType),
- 0,
- GetMaxIndex());
-}
-
-uint32_t
-AudioManager::VolumeStreamState::GetMaxIndex()
-{
- return sMaxStreamVolumeTbl[mStreamType];
-}
-
-uint32_t
-AudioManager::VolumeStreamState::GetDefaultIndex()
-{
- return sDefaultStreamVolumeTbl[mStreamType];
-}
-
-uint32_t
-AudioManager::VolumeStreamState::GetVolumeIndex()
-{
- uint32_t device = mManager.GetDeviceForStream(mStreamType);
- return GetVolumeIndex(device);
-}
-
-uint32_t
-AudioManager::VolumeStreamState::GetVolumeIndex(uint32_t aDevice)
-{
- uint32_t index = 0;
- bool ret = mVolumeIndexes.Get(aDevice, &index);
- if (!ret) {
- index = mVolumeIndexes.Get(AUDIO_DEVICE_OUT_DEFAULT);
- }
- return index;
-}
-
-nsresult
-AudioManager::VolumeStreamState::SetVolumeIndexToActiveDevices(uint32_t aIndex)
-{
- uint32_t device = mManager.GetDeviceForStream(mStreamType);
-
- // Update volume index for device
- uint32_t oldVolumeIndex = 0;
- bool exist = mVolumeIndexes.Get(device, &oldVolumeIndex);
- if (exist && aIndex == oldVolumeIndex) {
- // No update
- return NS_OK;
- }
-
- // AudioPolicyManager::setStreamVolumeIndex() set volumes of all active
- // devices for stream.
- nsresult rv;
- rv = SetVolumeIndexToConsistentDeviceIfNeeded(aIndex, device);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- return NS_OK;
-}
-
-nsresult
-AudioManager::VolumeStreamState::SetVolumeIndexToAliasStreams(uint32_t aIndex,
- uint32_t aDevice)
-{
- uint32_t oldVolumeIndex = 0;
- bool exist = mVolumeIndexes.Get(aDevice, &oldVolumeIndex);
- if (exist && aIndex == oldVolumeIndex) {
- // No update
- return NS_OK;
- }
-
- nsresult rv = SetVolumeIndexToConsistentDeviceIfNeeded(aIndex, aDevice);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- for (int32_t streamType = 0; streamType < AUDIO_STREAM_MAX; streamType++) {
- if ((streamType != mStreamType) &&
- sStreamVolumeAliasTbl[streamType] == mStreamType) {
- // Rescaling of index is not necessary.
- rv = mManager.mStreamStates[streamType]->
- SetVolumeIndexToAliasStreams(aIndex, aDevice);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-AudioManager::VolumeStreamState::SetVolumeIndexToConsistentDeviceIfNeeded(uint32_t aIndex, uint32_t aDevice)
-{
- nsresult rv;
- if (aDevice == AUDIO_DEVICE_OUT_SPEAKER || aDevice == AUDIO_DEVICE_OUT_EARPIECE) {
- // Set AUDIO_DEVICE_OUT_SPEAKER and AUDIO_DEVICE_OUT_EARPIECE to same volume.
- rv = SetVolumeIndex(aIndex, AUDIO_DEVICE_OUT_SPEAKER);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rv = SetVolumeIndex(aIndex, AUDIO_DEVICE_OUT_EARPIECE);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- // No alias device
- rv = SetVolumeIndex(aIndex, aDevice);
- }
- return rv;
-}
-
-nsresult
-AudioManager::VolumeStreamState::SetVolumeIndex(uint32_t aIndex,
- uint32_t aDevice,
- bool aUpdateCache)
-{
- status_t rv;
-#if ANDROID_VERSION >= 17
- if (aUpdateCache) {
- mVolumeIndexes.Put(aDevice, aIndex);
- mIsVolumeIndexesChanged = true;
- mManager.AudioOutDeviceUpdated(aDevice);
- }
-
- rv = AudioSystem::setStreamVolumeIndex(
- static_cast<audio_stream_type_t>(mStreamType),
- aIndex,
- aDevice);
- return rv ? NS_ERROR_FAILURE : NS_OK;
-#else
- if (aUpdateCache) {
- // Per audio out device volume is not supported.
- // Use AUDIO_DEVICE_OUT_SPEAKER just to store audio volume to DB.
- mVolumeIndexes.Put(AUDIO_DEVICE_OUT_SPEAKER, aIndex);
- mIsVolumeIndexesChanged = true;
- mManager.AudioOutDeviceUpdated(AUDIO_DEVICE_OUT_SPEAKER);
- }
- rv = AudioSystem::setStreamVolumeIndex(
- static_cast<audio_stream_type_t>(mStreamType),
- aIndex);
- return rv ? NS_ERROR_FAILURE : NS_OK;
-#endif
-}
-
-void
-AudioManager::VolumeStreamState::RestoreVolumeIndexToAllDevices()
-{
- for (auto iter = mVolumeIndexes.Iter(); !iter.Done(); iter.Next()) {
- const uint32_t& key = iter.Key();
- uint32_t& index = iter.Data();
- SetVolumeIndex(key, index, /* aUpdateCache */ false);
- }
-}
-
-} /* namespace gonk */
-} /* namespace dom */
-} /* namespace mozilla */
diff --git a/dom/system/gonk/AudioManager.h b/dom/system/gonk/AudioManager.h
deleted file mode 100644
index f56eaad6c..000000000
--- a/dom/system/gonk/AudioManager.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef mozilla_dom_system_b2g_audiomanager_h__
-#define mozilla_dom_system_b2g_audiomanager_h__
-
-#include "mozilla/HalTypes.h"
-#include "mozilla/Observer.h"
-#include "mozilla/UniquePtr.h"
-#include "nsAutoPtr.h"
-#include "nsDataHashtable.h"
-#include "nsIAudioManager.h"
-#include "nsIObserver.h"
-#include "android_audio/AudioSystem.h"
-
-// {b2b51423-502d-4d77-89b3-7786b562b084}
-#define NS_AUDIOMANAGER_CID {0x94f6fd70, 0x7615, 0x4af9, \
- {0x89, 0x10, 0xf9, 0x3c, 0x55, 0xe6, 0x62, 0xec}}
-#define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
-
-class nsISettingsServiceLock;
-
-namespace mozilla {
-namespace hal {
-class SwitchEvent;
-typedef Observer<SwitchEvent> SwitchObserver;
-} // namespace hal
-
-namespace dom {
-namespace gonk {
-
-class VolumeInitCallback;
-
-class AudioManager final : public nsIAudioManager
- , public nsIObserver
-{
-public:
- static already_AddRefed<AudioManager> GetInstance();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIAUDIOMANAGER
- NS_DECL_NSIOBSERVER
-
- // Validate whether the volume index is within the range
- nsresult ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const;
-
- // Called when android AudioFlinger in mediaserver is died
- void HandleAudioFlingerDied();
-
- void HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent);
-
- class VolumeStreamState {
- public:
- explicit VolumeStreamState(AudioManager& aManager, int32_t aStreamType);
- int32_t GetStreamType()
- {
- return mStreamType;
- }
- bool IsDevicesChanged(bool aFromCache = true);
- void ClearDevicesChanged();
- uint32_t GetLastDevices()
- {
- return mLastDevices;
- }
- bool IsVolumeIndexesChanged();
- void ClearVolumeIndexesChanged();
- void InitStreamVolume();
- uint32_t GetMaxIndex();
- uint32_t GetDefaultIndex();
- uint32_t GetVolumeIndex();
- uint32_t GetVolumeIndex(uint32_t aDevice);
- void ClearCurrentVolumeUpdated();
- // Set volume index to all active devices.
- // Active devices are chosen by android AudioPolicyManager.
- nsresult SetVolumeIndexToActiveDevices(uint32_t aIndex);
- // Set volume index to all alias streams for device. Alias streams have same volume.
- nsresult SetVolumeIndexToAliasStreams(uint32_t aIndex, uint32_t aDevice);
- nsresult SetVolumeIndexToConsistentDeviceIfNeeded(uint32_t aIndex, uint32_t aDevice);
- nsresult SetVolumeIndex(uint32_t aIndex, uint32_t aDevice, bool aUpdateCache = true);
- // Restore volume index to all devices. Called when AudioFlinger is restarted.
- void RestoreVolumeIndexToAllDevices();
- private:
- AudioManager& mManager;
- const int32_t mStreamType;
- uint32_t mLastDevices;
- bool mIsDevicesChanged;
- bool mIsVolumeIndexesChanged;
- nsDataHashtable<nsUint32HashKey, uint32_t> mVolumeIndexes;
- };
-
-protected:
- int32_t mPhoneState;
-
- bool mIsVolumeInited;
-
- // A bitwise variable for volume update of audio output devices,
- // clear it after store the value into database.
- uint32_t mAudioOutDevicesUpdated;
-
- // Connected devices that are controlled by setDeviceConnectionState()
- nsDataHashtable<nsUint32HashKey, nsCString> mConnectedDevices;
-
- nsDataHashtable<nsUint32HashKey, uint32_t> mAudioDeviceTableIdMaps;
-
- bool mSwitchDone;
-
-#if defined(MOZ_B2G_BT) || ANDROID_VERSION >= 17
- bool mBluetoothA2dpEnabled;
-#endif
-#ifdef MOZ_B2G_BT
- bool mA2dpSwitchDone;
-#endif
- nsTArray<UniquePtr<VolumeStreamState> > mStreamStates;
- uint32_t mLastChannelVolume[AUDIO_STREAM_CNT];
-
- bool IsFmOutConnected();
-
- nsresult SetStreamVolumeForDevice(int32_t aStream,
- uint32_t aIndex,
- uint32_t aDevice);
- nsresult SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex);
- nsresult GetStreamVolumeIndex(int32_t aStream, uint32_t* aIndex);
-
- void UpdateCachedActiveDevicesForStreams();
- uint32_t GetDevicesForStream(int32_t aStream, bool aFromCache = true);
- uint32_t GetDeviceForStream(int32_t aStream);
- // Choose one device as representative of active devices.
- static uint32_t SelectDeviceFromDevices(uint32_t aOutDevices);
-
-private:
- nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
-
- void HandleBluetoothStatusChanged(nsISupports* aSubject,
- const char* aTopic,
- const nsCString aAddress);
- void HandleAudioChannelProcessChanged();
-
- // Append the audio output device to the volume setting string.
- nsAutoCString AppendDeviceToVolumeSetting(const char* aName,
- uint32_t aDevice);
-
- // We store the volume setting in the database, these are related functions.
- void InitVolumeFromDatabase();
- void MaybeUpdateVolumeSettingToDatabase(bool aForce = false);
-
- // Promise functions.
- void InitDeviceVolumeSucceeded();
- void InitDeviceVolumeFailed(const char* aError);
-
- void AudioOutDeviceUpdated(uint32_t aDevice);
-
- void UpdateHeadsetConnectionState(hal::SwitchState aState);
- void UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName);
- void SetAllDeviceConnectionStates();
-
- AudioManager();
- ~AudioManager();
-
- friend class VolumeInitCallback;
- friend class VolumeStreamState;
- friend class GonkAudioPortCallback;
-};
-
-} /* namespace gonk */
-} /* namespace dom */
-} /* namespace mozilla */
-
-#endif // mozilla_dom_system_b2g_audiomanager_h__
diff --git a/dom/system/gonk/AutoMounter.cpp b/dom/system/gonk/AutoMounter.cpp
deleted file mode 100644
index 52c4554fb..000000000
--- a/dom/system/gonk/AutoMounter.cpp
+++ /dev/null
@@ -1,1496 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <signal.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-#include <sys/statfs.h>
-
-#include <arpa/inet.h>
-#include <linux/types.h>
-#include <linux/netlink.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <android/log.h>
-#include <cutils/properties.h>
-
-#include "AutoMounter.h"
-#include "nsVolumeService.h"
-#include "AutoMounterSetting.h"
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "mozilla/AutoRestore.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/Hal.h"
-#include "mozilla/StaticPtr.h"
-#include "MozMtpServer.h"
-#include "MozMtpStorage.h"
-#include "nsCharSeparatedTokenizer.h"
-#include "nsMemory.h"
-#include "nsString.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-#include "OpenFileFinder.h"
-#include "Volume.h"
-#include "VolumeManager.h"
-#include "nsIStatusReporter.h"
-
-USING_MTP_NAMESPACE
-
-/**************************************************************************
-*
-* The following "switch" files are available for monitoring usb
-* connections:
-*
-* /sys/devices/virtual/switch/usb_connected/state
-* /sys/devices/virtual/switch/usb_configuration/state
-*
-* Under gingerbread, only the usb_configuration seems to be available.
-* Starting with honeycomb, usb_connected was also added.
-*
-* When a cable insertion/removal occurs, then a uevent similar to the
-* following will be generted:
-*
-* change@/devices/virtual/switch/usb_configuration
-* ACTION=change
-* DEVPATH=/devices/virtual/switch/usb_configuration
-* SUBSYSTEM=switch
-* SWITCH_NAME=usb_configuration
-* SWITCH_STATE=0
-* SEQNUM=5038
-*
-* SWITCH_STATE will be 0 after a removal and 1 after an insertion
-*
-**************************************************************************/
-
-#define USB_CONFIGURATION_SWITCH_NAME NS_LITERAL_STRING("usb_configuration")
-
-#define GB_SYS_UMS_ENABLE "/sys/devices/virtual/usb_composite/usb_mass_storage/enable"
-#define GB_SYS_USB_CONFIGURED "/sys/devices/virtual/switch/usb_configuration/state"
-
-#define ICS_SYS_USB_FUNCTIONS "/sys/devices/virtual/android_usb/android0/functions"
-#define ICS_SYS_UMS_DIRECTORY "/sys/devices/virtual/android_usb/android0/f_mass_storage"
-#define ICS_SYS_MTP_DIRECTORY "/sys/devices/virtual/android_usb/android0/f_mtp"
-#define ICS_SYS_USB_STATE "/sys/devices/virtual/android_usb/android0/state"
-
-#undef USE_DEBUG // MozMtpDatabase.h also defines USE_DEBUG
-#define USE_DEBUG 0
-
-#undef LOG
-#undef LOGW
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounter", ## args)
-#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "AutoMounter", ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounter", ## args)
-
-#undef DBG
-#if USE_DEBUG
-#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "AutoMounter" , ## args)
-#else
-#define DBG(args...)
-#endif
-
-namespace mozilla {
-namespace system {
-
-#define SYS_USB_CONFIG "sys.usb.config"
-#define PERSIST_SYS_USB_CONFIG "persist.sys.usb.config"
-
-#define USB_FUNC_ADB "adb"
-#define USB_FUNC_MTP "mtp"
-#define USB_FUNC_NONE "none"
-#define USB_FUNC_RNDIS "rndis"
-#define USB_FUNC_UMS "mass_storage"
-#define USB_FUNC_DEFAULT "default"
-
-class AutoMounter;
-
-static void SetAutoMounterStatus(int32_t aStatus);
-
-/***************************************************************************/
-
-inline const char* SwitchStateStr(const hal::SwitchEvent& aEvent)
-{
- return aEvent.status() == hal::SWITCH_STATE_ON ? "plugged" : "unplugged";
-}
-
-/***************************************************************************/
-
-static bool
-IsUsbCablePluggedIn()
-{
-#if 0
- // Use this code when bug 745078 gets fixed (or use whatever the
- // appropriate method is)
- return GetCurrentSwitchEvent(SWITCH_USB) == hal::SWITCH_STATE_ON;
-#else
- // Until then, just go read the file directly
- if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
- char usbState[20];
- if (ReadSysFile(ICS_SYS_USB_STATE, usbState, sizeof(usbState))) {
- DBG("IsUsbCablePluggedIn: state = '%s'", usbState);
- return strcmp(usbState, "CONFIGURED") == 0 ||
- strcmp(usbState, "CONNECTED") == 0;
- }
- ERR("Error reading file '%s': %s", ICS_SYS_USB_STATE, strerror(errno));
- return false;
- }
- bool configured;
- if (ReadSysFile(GB_SYS_USB_CONFIGURED, &configured)) {
- return configured;
- }
- ERR("Error reading file '%s': %s", GB_SYS_USB_CONFIGURED, strerror(errno));
- return false;
-#endif
-}
-
-static bool
-IsUsbConfigured()
-{
- if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
- char usbState[20];
- if (ReadSysFile(ICS_SYS_USB_STATE, usbState, sizeof(usbState))) {
- DBG("IsUsbConfigured: state = '%s'", usbState);
- return strcmp(usbState, "CONFIGURED") == 0;
- }
- ERR("Error reading file '%s': %s", ICS_SYS_USB_STATE, strerror(errno));
- return false;
- }
- bool configured;
- if (ReadSysFile(GB_SYS_USB_CONFIGURED, &configured)) {
- return configured;
- }
- ERR("Error reading file '%s': %s", GB_SYS_USB_CONFIGURED, strerror(errno));
- return false;
-}
-
-/***************************************************************************/
-
-// The AutoVolumeManagerStateObserver allows the AutoMounter to know when
-// the volume manager changes state (i.e. it has finished initialization)
-class AutoVolumeManagerStateObserver : public VolumeManager::StateObserver
-{
-public:
- virtual void Notify(const VolumeManager::StateChangedEvent& aEvent);
-};
-
-// The AutoVolumeEventObserver allows the AutoMounter to know about card
-// insertion and removal, as well as state changes in the volume.
-class AutoVolumeEventObserver : public Volume::EventObserver
-{
-public:
- virtual void Notify(Volume* const& aEvent);
-};
-
-class AutoMounterResponseCallback : public VolumeResponseCallback
-{
-public:
- AutoMounterResponseCallback()
- : mErrorCount(0)
- {
- }
-
-protected:
- virtual void ResponseReceived(const VolumeCommand* aCommand);
-
-private:
- const static int kMaxErrorCount = 3; // Max number of errors before we give up
-
- int mErrorCount;
-};
-
-/***************************************************************************/
-
-class AutoMounter
-{
-public:
- NS_INLINE_DECL_REFCOUNTING(AutoMounter)
-
- typedef nsTArray<RefPtr<Volume>> VolumeArray;
-
- AutoMounter()
- : mState(STATE_IDLE),
- mResponseCallback(new AutoMounterResponseCallback),
- mMode(AUTOMOUNTER_DISABLE)
- {
- VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
- Volume::RegisterVolumeObserver(&mVolumeEventObserver, "AutoMounter");
-
- // It's possible that the VolumeManager is already in the READY state,
- // so we call CheckVolumeSettings here to cover that case. Otherwise,
- // we'll pick it up when the VolumeManage state changes to VOLUMES_READY.
- CheckVolumeSettings();
-
- DBG("Calling UpdateState from constructor");
- UpdateState();
- }
-
- void CheckVolumeSettings()
- {
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- DBG("CheckVolumeSettings: VolumeManager is NOT READY yet");
- return;
- }
- DBG("CheckVolumeSettings: VolumeManager is READY");
-
- // The VolumeManager knows about all of the volumes from vold. We now
- // know the names of all of the volumes, so we can find out what the
- // initial sharing settings are set to.
-
- VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- VolumeManager::VolumeArray::index_type i;
- for (i = 0; i < numVolumes; i++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(i);
- if (vol) {
- // We need to pick up the intial value of the
- // ums.volume.NAME.enabled setting.
- AutoMounterSetting::CheckVolumeSettings(vol->Name());
-
- // Note: eventually CheckVolumeSettings will call
- // AutoMounter::SetSharingMode, which will in turn call
- // UpdateState if needed.
- }
- }
- }
-
- void UpdateState();
- void GetStatus(bool& umsAvail, bool& umsConfigured, bool& umsEnabled, bool& mtpAvail,
- bool& mtpConfigured, bool& mtpEnabled, bool& rndisConfigured);
-
- nsresult Dump(nsACString& desc);
-
- void ConfigureUsbFunction(const char* aUsbFunc);
-
- bool StartMtpServer();
- void StopMtpServer();
-
- void StartUmsSharing();
- void StopUmsSharing();
-
-
- const char* ModeStr(int32_t aMode)
- {
- switch (aMode) {
- case AUTOMOUNTER_DISABLE: return "Disable";
- case AUTOMOUNTER_ENABLE_UMS: return "Enable-UMS";
- case AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED: return "DisableWhenUnplugged";
- case AUTOMOUNTER_ENABLE_MTP: return "Enable-MTP";
- }
- return "??? Unknown ???";
- }
-
- bool IsModeEnabled(int32_t aMode)
- {
- return aMode == AUTOMOUNTER_ENABLE_MTP ||
- aMode == AUTOMOUNTER_ENABLE_UMS;
- }
-
- void SetMode(int32_t aMode)
- {
- if ((aMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) &&
- (mMode == AUTOMOUNTER_DISABLE)) {
- // If it's already disabled, then leave it as disabled.
- // AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED implies "enabled until unplugged"
- aMode = AUTOMOUNTER_DISABLE;
- }
-
- if (aMode == AUTOMOUNTER_DISABLE &&
- mMode == AUTOMOUNTER_ENABLE_UMS && IsUsbCablePluggedIn()) {
- // On many devices (esp non-Samsung), we can't force the disable, so we
- // need to defer until the USB cable is actually unplugged.
- // See bug 777043.
- //
- // Otherwise our attempt to disable it will fail, and we'll wind up in a bad
- // state where the AutoMounter thinks that Sharing has been turned off, but
- // the files are actually still being Shared because the attempt to unshare
- // failed.
- LOG("Attempting to disable UMS. Deferring until USB cable is unplugged.");
- aMode = AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED;
- }
-
- if (aMode != mMode) {
- LOG("Changing mode from '%s' to '%s'", ModeStr(mMode), ModeStr(aMode));
- mMode = aMode;
- DBG("Calling UpdateState due to mode set to %d", mMode);
- UpdateState();
- }
- }
-
- void SetSharingMode(const nsACString& aVolumeName, bool aAllowSharing)
- {
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol) {
- return;
- }
- if (vol->IsSharingEnabled() == aAllowSharing) {
- return;
- }
- vol->SetUnmountRequested(false);
- vol->SetMountRequested(false);
- vol->SetSharingEnabled(aAllowSharing);
- DBG("Calling UpdateState due to volume %s sharing set to %d",
- vol->NameStr(), (int)aAllowSharing);
- UpdateState();
- }
-
- void FormatVolume(const nsACString& aVolumeName)
- {
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol) {
- return;
- }
- if (vol->IsFormatRequested()) {
- return;
- }
- vol->SetUnmountRequested(false);
- vol->SetMountRequested(false);
- vol->SetFormatRequested(true);
- DBG("Calling UpdateState due to volume %s formatting set to %d",
- vol->NameStr(), (int)vol->IsFormatRequested());
- UpdateState();
- }
-
- void MountVolume(const nsACString& aVolumeName)
- {
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol) {
- return;
- }
- vol->SetUnmountRequested(false);
- if (vol->IsMountRequested() || vol->mState == nsIVolume::STATE_MOUNTED) {
- return;
- }
- vol->SetMountRequested(true);
- DBG("Calling UpdateState due to volume %s mounting set to %d",
- vol->NameStr(), (int)vol->IsMountRequested());
- UpdateState();
- }
-
- void UnmountVolume(const nsACString& aVolumeName)
- {
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol) {
- return;
- }
- if (vol->IsUnmountRequested()) {
- return;
- }
- vol->SetMountRequested(false);
- vol->SetUnmountRequested(true);
- DBG("Calling UpdateState due to volume %s unmounting set to %d",
- vol->NameStr(), (int)vol->IsUnmountRequested());
- UpdateState();
- }
-
-protected:
- ~AutoMounter()
- {
- Volume::UnregisterVolumeObserver(&mVolumeEventObserver, "AutoMounter");
- VolumeManager::UnregisterStateObserver(&mVolumeManagerStateObserver);
- }
-
-private:
-
- enum STATE
- {
- // IDLE - Nothing is being shared
- STATE_IDLE,
-
- // We've detected that conditions are right to enable mtp. So we've
- // set sys.usb.config to include mtp, and we're waiting for the USB
- // subsystem to be "configured". Once mtp shows up in
- // then we know
- // that its been configured and we can open /dev/mtp_usb
- STATE_MTP_CONFIGURING,
-
- // mtp has been configured (i.e. mtp now shows up in
- // /sys/devices/virtual/android_usb/android0/functions so we can start
- // the mtp server.
- STATE_MTP_STARTED,
-
- // The mtp server has reported sessionStarted. We'll leave this state
- // when we receive sessionEnded.
- STATE_MTP_CONNECTED,
-
- // We've added mass_storage (aka UMS) to sys.usb.config and we're waiting for
- // mass_storage to appear in /sys/devices/virtual/android_usb/android0/functions
- STATE_UMS_CONFIGURING,
-
- // mass_storage has been configured and we can start sharing once the user
- // enables it.
- STATE_UMS_CONFIGURED,
-
- // USB Tethering is enabled
- STATE_RNDIS_CONFIGURED,
- };
-
- const char *StateStr(STATE aState)
- {
- switch (aState) {
- case STATE_IDLE: return "IDLE";
- case STATE_MTP_CONFIGURING: return "MTP_CONFIGURING";
- case STATE_MTP_CONNECTED: return "MTP_CONNECTED";
- case STATE_MTP_STARTED: return "MTP_STARTED";
- case STATE_UMS_CONFIGURING: return "UMS_CONFIGURING";
- case STATE_UMS_CONFIGURED: return "UMS_CONFIGURED";
- case STATE_RNDIS_CONFIGURED: return "RNDIS_CONFIGURED";
- }
- return "STATE_???";
- }
-
- void SetState(STATE aState)
- {
- const char *oldStateStr = StateStr(mState);
- mState = aState;
- const char *newStateStr = StateStr(mState);
- LOG("AutoMounter state changed from %s to %s", oldStateStr, newStateStr);
- }
-
- STATE mState;
-
- AutoVolumeEventObserver mVolumeEventObserver;
- AutoVolumeManagerStateObserver mVolumeManagerStateObserver;
- RefPtr<VolumeResponseCallback> mResponseCallback;
- int32_t mMode;
- MozMtpStorage::Array mMozMtpStorage;
-};
-
-static StaticRefPtr<AutoMounter> sAutoMounter;
-static StaticRefPtr<MozMtpServer> sMozMtpServer;
-
-// The following is for status reporter
-enum STATE_REPORTER_STATE
-{
- REPORTER_UNREGISTERED,
- REPORTER_REGISTERED
-};
-
-static int status_reporter_progress = REPORTER_UNREGISTERED;
-nsresult getState(nsACString &desc)
-{
- sAutoMounter->Dump(desc);
- return NS_OK;
-}
-NS_STATUS_REPORTER_IMPLEMENT(AutoMounter, "AutoMounter", getState);
-
-/***************************************************************************/
-
-void
-AutoVolumeManagerStateObserver::Notify(const VolumeManager::StateChangedEvent &)
-{
- LOG("VolumeManager state changed event: %s", VolumeManager::StateStr());
-
- if (!sAutoMounter) {
- return;
- }
-
- // In the event that the VolumeManager just entered the VOLUMES_READY state,
- // we call CheckVolumeSettings here (it's possible that this method never
- // gets called if the VolumeManager was already in the VOLUMES_READY state
- // by the time the AutoMounter was constructed).
- sAutoMounter->CheckVolumeSettings();
-
- DBG("Calling UpdateState due to VolumeManagerStateObserver");
- sAutoMounter->UpdateState();
-}
-
-void
-AutoVolumeEventObserver::Notify(Volume * const &)
-{
- if (!sAutoMounter) {
- return;
- }
- DBG("Calling UpdateState due to VolumeEventStateObserver");
- sAutoMounter->UpdateState();
-}
-
-void
-AutoMounterResponseCallback::ResponseReceived(const VolumeCommand* aCommand)
-{
-
- if (WasSuccessful()) {
- DBG("Calling UpdateState due to Volume::OnSuccess");
- mErrorCount = 0;
- sAutoMounter->UpdateState();
- return;
- }
- ERR("Command '%s' failed: %d '%s'",
- aCommand->CmdStr(), ResponseCode(), ResponseStr().get());
-
- if (++mErrorCount < kMaxErrorCount) {
- DBG("Calling UpdateState due to VolumeResponseCallback::OnError");
- sAutoMounter->UpdateState();
- }
-}
-
-static bool
-IsUsbFunctionEnabled(const char* aConfig, const char* aUsbFunc)
-{
- nsAutoCString config(aConfig);
- nsCCharSeparatedTokenizer tokenizer(config, ',');
-
- while (tokenizer.hasMoreTokens()) {
- nsAutoCString token(tokenizer.nextToken());
- if (token.Equals(aUsbFunc)) {
- DBG("IsUsbFunctionEnabled('%s', '%s'): returning true", aConfig, aUsbFunc);
- return true;
- }
- }
- DBG("IsUsbFunctionEnabled('%s', '%s'): returning false", aConfig, aUsbFunc);
- return false;
-}
-
-static void
-SetUsbFunction(const char* aUsbFunc)
-{
- char oldSysUsbConfig[PROPERTY_VALUE_MAX];
- property_get(SYS_USB_CONFIG, oldSysUsbConfig, "");
-
- if (strcmp(oldSysUsbConfig, USB_FUNC_NONE) == 0) {
- // It's quite possible that sys.usb.config may have the value "none". We
- // convert that to an empty string here, and at the end we convert the
- // empty string back to "none".
- oldSysUsbConfig[0] = '\0';
- }
-
- if (IsUsbFunctionEnabled(oldSysUsbConfig, aUsbFunc)) {
- // The function is already configured. Nothing else to do.
- DBG("SetUsbFunction('%s') - already set - nothing to do", aUsbFunc);
- return;
- }
-
- char newSysUsbConfig[PROPERTY_VALUE_MAX];
-
- if (strcmp(aUsbFunc, USB_FUNC_MTP) == 0) {
- // We're enabling MTP. For this we'll wind up using mtp, or mtp,adb
- strlcpy(newSysUsbConfig, USB_FUNC_MTP, sizeof(newSysUsbConfig));
- } else if (strcmp(aUsbFunc, USB_FUNC_UMS) == 0) {
- // We're enabling UMS. For this we make the assumption that the persisted
- // property has mass_storage enabled.
- property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, "");
- } else if (strcmp(aUsbFunc, USB_FUNC_DEFAULT) == 0) {
- // Set the property as PERSIST_SYS_USB_CONFIG
- property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, "");
- } else {
- printf_stderr("AutoMounter::SetUsbFunction Unrecognized aUsbFunc '%s'\n", aUsbFunc);
- MOZ_ASSERT(0);
- return;
- }
-
- // Make sure the new value that we write into sys.usb.config keeps the adb
- // (or non-adb) of the current string.
-
- if (IsUsbFunctionEnabled(oldSysUsbConfig, USB_FUNC_ADB)) {
- // ADB was turned on - keep it on.
- if (!IsUsbFunctionEnabled(newSysUsbConfig, USB_FUNC_ADB)) {
- // Add adb to the new string
- strlcat(newSysUsbConfig, ",", sizeof(newSysUsbConfig));
- strlcat(newSysUsbConfig, USB_FUNC_ADB, sizeof(newSysUsbConfig));
- }
- } else {
- // ADB was turned off - keep it off
- if (IsUsbFunctionEnabled(newSysUsbConfig, USB_FUNC_ADB)) {
- // Remove ADB from the new string.
- if (strcmp(newSysUsbConfig, USB_FUNC_ADB) == 0) {
- newSysUsbConfig[0] = '\0';
- } else {
- nsAutoCString withoutAdb(newSysUsbConfig);
- withoutAdb.ReplaceSubstring( "," USB_FUNC_ADB, "");
- strlcpy(newSysUsbConfig, withoutAdb.get(), sizeof(newSysUsbConfig));
- }
- }
- }
-
- // If the persisted function didn't have mass_storage (this happens on
- // the nexus 4/5, then we can get to here and have oldSysUsbConfig equal
- // to newSysUsbConfig. So we need to check for that.
-
- if (strcmp(oldSysUsbConfig, newSysUsbConfig) == 0) {
- DBG("SetUsbFunction('%s') %s is already set to '%s' - nothing to do",
- aUsbFunc, SYS_USB_CONFIG, newSysUsbConfig);
- return;
- }
-
- if (newSysUsbConfig[0] == '\0') {
- // Convert the empty string back to the string "none"
- strlcpy(newSysUsbConfig, USB_FUNC_NONE, sizeof(newSysUsbConfig));
- }
- LOG("SetUsbFunction(%s) %s from '%s' to '%s'", aUsbFunc, SYS_USB_CONFIG,
- oldSysUsbConfig, newSysUsbConfig);
- property_set(SYS_USB_CONFIG, newSysUsbConfig);
-}
-
-bool
-AutoMounter::StartMtpServer()
-{
- if (sMozMtpServer) {
- // Mtp Server is already running - nothing to do
- return true;
- }
- LOG("Starting MtpServer");
-
- // For debugging, Change the #if 0 to #if 1, and then attach gdb during
- // the 5 second interval below. Otherwise, configuring MTP will cause adb
- // (and thus gdb) to get bounced.
-#if 0
- LOG("Sleeping");
- PRTime now = PR_Now();
- PRTime stopTime = now + 5000000;
- while (PR_Now() < stopTime) {
- LOG("Sleeping...");
- sleep(1);
- }
- LOG("Sleep done");
-#endif
-
- sMozMtpServer = new MozMtpServer();
- if (!sMozMtpServer->Init()) {
- sMozMtpServer = nullptr;
- return false;
- }
-
- VolumeArray::index_type volIndex;
- VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- RefPtr<MozMtpStorage> storage = new MozMtpStorage(vol, sMozMtpServer);
- mMozMtpStorage.AppendElement(storage);
- }
-
- sMozMtpServer->Run();
- return true;
-}
-
-void
-AutoMounter::StopMtpServer()
-{
- LOG("Stopping MtpServer");
-
- mMozMtpStorage.Clear();
- sMozMtpServer = nullptr;
-}
-
-/***************************************************************************/
-
-void
-AutoMounter::UpdateState()
-{
- static bool inUpdateState = false;
- if (inUpdateState) {
- // When UpdateState calls SetISharing, this causes a volume state
- // change to occur, which would normally cause UpdateState to be called
- // again. We want the volume state change to go out (so that device
- // storage will see the change in sharing state), but since we're
- // already in UpdateState we just want to prevent recursion from screwing
- // things up.
- return;
- }
- AutoRestore<bool> inUpdateStateDetector(inUpdateState);
- inUpdateState = true;
-
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // If the following preconditions are met:
- // - UMS is available (i.e. compiled into the kernel)
- // - UMS is enabled
- // - AutoMounter is enabled
- // - USB cable is plugged in
- // then we will try to unmount and share
- // otherwise we will try to unshare and mount.
-
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- // The volume manager isn't in a ready state, so there
- // isn't anything else that we can do.
- LOG("UpdateState: VolumeManager not ready yet");
- return;
- }
-
- if (mResponseCallback->IsPending()) {
- // We only deal with one outstanding volume command at a time,
- // so we need to wait for it to finish.
- return;
- }
-
- // Calling setprop sys.usb.config mtp,adb (or adding mass_storage) will
- // cause /sys/devices/virtual/android_usb/android0/state to go:
- // CONFIGURED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- //
- // Since IsUsbCablePluggedIn returns state == CONFIGURED, it will look
- // like a cable pull and replugin.
- bool umsAvail, umsConfigured, umsEnabled;
- bool mtpAvail, mtpConfigured, mtpEnabled;
- bool rndisConfigured;
- bool usbCablePluggedIn = IsUsbCablePluggedIn();
- GetStatus(umsAvail, umsConfigured, umsEnabled, mtpAvail,
- mtpConfigured, mtpEnabled, rndisConfigured);
- bool enabled = mtpEnabled || umsEnabled;
-
- if (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) {
- // DISABLE_WHEN_UNPLUGGED implies already enabled.
- enabled = usbCablePluggedIn;
- if (!usbCablePluggedIn) {
- mMode = AUTOMOUNTER_DISABLE;
- mtpEnabled = false;
- umsEnabled = false;
- }
- }
-
- DBG("UpdateState: ums:A%dC%dE%d mtp:A%dC%dE%d rndis:%d mode:%d usb:%d mState:%s",
- umsAvail, umsConfigured, umsEnabled,
- mtpAvail, mtpConfigured, mtpEnabled, rndisConfigured,
- mMode, usbCablePluggedIn, StateStr(mState));
-
- switch (mState) {
-
- case STATE_IDLE:
- if (!usbCablePluggedIn) {
- // Stay in the IDLE state. We'll get a CONNECTED or CONFIGURED
- // UEvent when the usb cable is plugged in.
- break;
- }
- if (rndisConfigured) {
- // USB Tethering uses RNDIS. We'll just wait until its turned off.
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- if (mtpEnabled) {
- if (mtpConfigured) {
- // The USB layer has already been configured. Now we can go ahead
- // and start the MTP server. This particular codepath will not
- // normally be taken, but it could happen if you stop and restart
- // b2g while sys.usb.config is set to enable mtp.
- if (StartMtpServer()) {
- SetState(STATE_MTP_STARTED);
- } else {
- if (umsAvail) {
- // Unable to start MTP. Go back to UMS.
- LOG("UpdateState: StartMtpServer failed, switch to UMS");
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- } else {
- LOG("UpdateState: StartMtpServer failed, keep idle state");
- SetUsbFunction(USB_FUNC_DEFAULT);
- }
- }
- } else {
- // We need to configure USB to use mtp. Wait for it to be configured
- // before we start the MTP server.
- SetUsbFunction(USB_FUNC_MTP);
- SetState(STATE_MTP_CONFIGURING);
- }
- } else if (umsConfigured) {
- // UMS is already configured.
- SetState(STATE_UMS_CONFIGURED);
- } else if (umsAvail) {
- // We do this whether or not UMS is enabled. With UMS, it's the
- // sharing of the volume which is significant. What is important
- // is that we don't leave it in MTP mode when MTP isn't enabled.
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- }
- break;
-
- case STATE_MTP_CONFIGURING:
- // While configuring, the USB configuration state will change from
- // CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- // so we don't check for cable unplugged here.
- if (mtpEnabled && mtpConfigured) {
- // The USB layer has been configured. Now we can go ahead and start
- // the MTP server.
- if (StartMtpServer()) {
- SetState(STATE_MTP_STARTED);
- } else {
- // Unable to start MTP. Go back to UMS.
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- }
- break;
- }
- if (rndisConfigured) {
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- break;
-
- case STATE_MTP_STARTED:
- if (usbCablePluggedIn && mtpConfigured && mtpEnabled) {
- // Everything is still good. Leave the MTP server running
- break;
- }
- DBG("STATE_MTP_STARTED: About to StopMtpServer "
- "mtpConfigured = %d mtpEnabled = %d usbCablePluggedIn: %d",
- mtpConfigured, mtpEnabled, usbCablePluggedIn);
- StopMtpServer();
- if (rndisConfigured) {
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- if (umsAvail) {
- // Switch back to UMS
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- break;
- }
-
- // if ums/rndis is not available and mtp is disable,
- // restore the usb function as PERSIST_SYS_USB_CONFIG.
- SetUsbFunction(USB_FUNC_DEFAULT);
- SetState(STATE_IDLE);
- break;
-
- case STATE_UMS_CONFIGURING:
- if (mtpEnabled) {
- // MTP was enabled. Start reconfiguring.
- SetState(STATE_MTP_CONFIGURING);
- SetUsbFunction(USB_FUNC_MTP);
- break;
- }
- if (rndisConfigured) {
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- // While configuring, the USB configuration state will change from
- // CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- // so we don't check for cable unplugged here. However, having said
- // that, we'll often sit in this state while the cable is unplugged,
- // since we might not get any events until the cable gets plugged back
- // in. This is why we need to check for mtpEnabled once we get the
- // configured event.
- if (umsConfigured) {
- SetState(STATE_UMS_CONFIGURED);
- }
- break;
-
- case STATE_UMS_CONFIGURED:
- if (usbCablePluggedIn) {
- if (mtpEnabled) {
- // MTP was enabled. Start reconfiguring.
- SetState(STATE_MTP_CONFIGURING);
- SetUsbFunction(USB_FUNC_MTP);
- break;
- }
- if (umsConfigured && umsEnabled) {
- // This is the normal state when UMS is enabled.
- break;
- }
- }
- if (rndisConfigured) {
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- SetState(STATE_IDLE);
- break;
-
- case STATE_RNDIS_CONFIGURED:
- if (usbCablePluggedIn && rndisConfigured) {
- // Normal state when RNDIS is enabled.
- break;
- }
- SetState(STATE_IDLE);
- break;
-
- default:
- SetState(STATE_IDLE);
- break;
- }
-
- bool tryToShare = umsEnabled && usbCablePluggedIn;
- LOG("UpdateState: ums:A%dC%dE%d mtp:A%dC%dE%d mode:%d usb:%d tryToShare:%d state:%s",
- umsAvail, umsConfigured, umsEnabled,
- mtpAvail, mtpConfigured, mtpEnabled,
- mMode, usbCablePluggedIn, tryToShare, StateStr(mState));
-
- bool filesOpen = false;
- static unsigned filesOpenDelayCount = 0;
- VolumeArray::index_type volIndex;
- VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- Volume::STATE volState = vol->State();
-
- if (vol->State() == nsIVolume::STATE_MOUNTED) {
- LOG("UpdateState: Volume %s is %s and %s @ %s gen %d locked %d sharing %s",
- vol->NameStr(), vol->StateStr(),
- vol->MediaPresent() ? "inserted" : "missing",
- vol->MountPoint().get(), vol->MountGeneration(),
- (int)vol->IsMountLocked(),
- vol->CanBeShared() ? (vol->IsSharingEnabled() ?
- (vol->IsSharing() ? "en-y" : "en-n") : "dis") : "x");
- if (vol->IsSharing() && !usbCablePluggedIn) {
- // We call SetIsSharing(true) below to indicate intent to share. This
- // causes a state change which notifys apps, and they'll close any
- // open files, which will initiate the change away from the mounted
- // state and into the sharing state. Normally, when the volume
- // transitions back to the mounted state, then vol->mIsSharing gets set
- // to false. However, if the user pulls the USB cable before we
- // actually start sharing, then the volume never actually leaves
- // the mounted state (and hence never transitions from
- // sharing -> mounted), and mIsSharing never gets set back to false.
- // So we clear mIsSharing here.
- vol->SetIsSharing(false);
- }
- } else {
- LOG("UpdateState: Volume %s is %s and %s", vol->NameStr(), vol->StateStr(),
- vol->MediaPresent() ? "inserted" : "missing");
- }
- if (!vol->MediaPresent()) {
- // No media - nothing we can do
- continue;
- }
-
- if (vol->State() == nsIVolume::STATE_CHECKMNT) {
- // vold reports the volume is "Mounted". Need to check if the volume is
- // accessible by statfs(). Once it can be accessed, set the volume as
- // STATE_MOUNTED, otherwise, post a delay task of UpdateState to check it
- // again.
- struct statfs fsbuf;
- int rc = MOZ_TEMP_FAILURE_RETRY(statfs(vol->MountPoint().get(), &fsbuf));
- if (rc == -1) {
- // statfs() failed. Stay in STATE_CHECKMNT. Any failures here
- // are probably non-recoverable, so we need to wait until
- // something else changes the state back to IDLE/UNMOUNTED, etc.
- ERR("statfs failed for '%s': errno = %d (%s)", vol->NameStr(), errno, strerror(errno));
- continue;
- }
- static int delay = 250;
- if (fsbuf.f_blocks == 0) {
- if (delay <= 4000) {
- LOG("UpdateState: Volume '%s' is inaccessible, checking again in %d msec", vol->NameStr(), delay);
- MessageLoopForIO::current()->
- PostDelayedTask(NewRunnableMethod(this, &AutoMounter::UpdateState),
- delay);
- delay *= 2;
- } else {
- LOG("UpdateState: Volume '%s' is inaccessible, giving up", vol->NameStr());
- }
- continue;
- } else {
- delay = 250;
- vol->SetState(nsIVolume::STATE_MOUNTED);
- }
- }
-
- if ((tryToShare && vol->IsSharingEnabled()) ||
- vol->IsFormatRequested() ||
- vol->IsUnmountRequested()) {
- switch (volState) {
- // We're going to try to unmount the volume
- case nsIVolume::STATE_MOUNTED: {
- if (vol->IsMountLocked()) {
- // The volume is currently locked, so leave it in the mounted
- // state.
- LOGW("UpdateState: Mounted volume %s is locked, not sharing or formatting",
- vol->NameStr());
- break;
- }
-
- // Mark the volume as if we've started sharing/formatting/unmmounting.
- // This will cause apps which watch device storage notifications to see
- // the volume go into the different state, and prompt them to close any
- // open files that they might have.
- if (tryToShare && vol->IsSharingEnabled()) {
- vol->SetIsSharing(true);
- } else if (vol->IsFormatRequested()){
- vol->SetIsFormatting(true);
- } else if (vol->IsUnmountRequested()){
- vol->SetIsUnmounting(true);
- }
-
- // Check to see if there are any open files on the volume and
- // don't initiate the unmount while there are open files.
- OpenFileFinder::Info fileInfo;
- OpenFileFinder fileFinder(vol->MountPoint());
- if (fileFinder.First(&fileInfo)) {
- LOGW("The following files are open under '%s'",
- vol->MountPoint().get());
- do {
- LOGW(" PID: %d file: '%s' app: '%s' comm: '%s' exe: '%s'\n",
- fileInfo.mPid,
- fileInfo.mFileName.get(),
- fileInfo.mAppName.get(),
- fileInfo.mComm.get(),
- fileInfo.mExe.get());
- } while (fileFinder.Next(&fileInfo));
- LOGW("UpdateState: Mounted volume %s has open files, not sharing or formatting",
- vol->NameStr());
-
- // Check again in a few seconds to see if the files are closed.
- // Since we're trying to share the volume, this implies that we're
- // plugged into the PC via USB and this in turn implies that the
- // battery is charging, so we don't need to be too concerned about
- // wasting battery here.
- //
- // If we just detected that there were files open, then we use
- // a short timer. We will have told the apps that we're trying
- // trying to share, and they'll be closing their files. This makes
- // the sharing more responsive. If after a few seconds, the apps
- // haven't closed their files, then we back off.
-
- int delay = 1000;
- if (filesOpenDelayCount > 10) {
- delay = 5000;
- }
- MessageLoopForIO::current()->
- PostDelayedTask(NewRunnableMethod(this, &AutoMounter::UpdateState),
- delay);
- filesOpen = true;
- break;
- }
-
- // Volume is mounted, we need to unmount before
- // we can share.
- LOG("UpdateState: Unmounting %s", vol->NameStr());
- vol->StartUnmount(mResponseCallback);
- return; // UpdateState will be called again when the Unmount command completes
- }
- case nsIVolume::STATE_IDLE:
- case nsIVolume::STATE_MOUNT_FAIL: {
- LOG("UpdateState: Volume %s is %s", vol->NameStr(), vol->StateStr());
- if (vol->IsFormatting() && !vol->IsFormatRequested()) {
- vol->SetFormatRequested(false);
- if (!(tryToShare && vol->IsSharingEnabled()) && volState == nsIVolume::STATE_IDLE) {
- LOG("UpdateState: Mounting %s", vol->NameStr());
- vol->StartMount(mResponseCallback);
- break;
- }
- }
-
- // If there are format and share requests in the same time,
- // we should do format first then share.
- if (vol->IsFormatRequested()) {
- // Volume is unmounted. We can go ahead and format.
- LOG("UpdateState: Formatting %s", vol->NameStr());
- vol->StartFormat(mResponseCallback);
- } else if (tryToShare && vol->IsSharingEnabled() && volState == nsIVolume::STATE_IDLE) {
- // Volume is unmounted. We can go ahead and share.
- LOG("UpdateState: Sharing %s", vol->NameStr());
- vol->StartShare(mResponseCallback);
- }
- return; // UpdateState will be called again when the Share/Format command completes
- }
- default: {
- // Not in a state that we can do anything about.
- break;
- }
- }
- } else {
- // We're going to try and unshare and remount the volumes
- switch (volState) {
- case nsIVolume::STATE_SHARED: {
- // Volume is shared. We can go ahead and unshare.
- LOG("UpdateState: Unsharing %s", vol->NameStr());
- vol->StartUnshare(mResponseCallback);
- return; // UpdateState will be called again when the Unshare command completes
- }
- case nsIVolume::STATE_IDLE: {
- if (!vol->IsUnmountRequested()) {
- // Volume is unmounted and mount-requested, try to mount.
-
- LOG("UpdateState: Mounting %s", vol->NameStr());
- vol->StartMount(mResponseCallback);
- }
- return; // UpdateState will be called again when Mount command completes
- }
- default: {
- // Not in a state that we can do anything about.
- break;
- }
- }
- }
- }
-
- int32_t status = AUTOMOUNTER_STATUS_DISABLED;
- if (filesOpen) {
- filesOpenDelayCount++;
- status = AUTOMOUNTER_STATUS_FILES_OPEN;
- } else if (enabled) {
- filesOpenDelayCount = 0;
- status = AUTOMOUNTER_STATUS_ENABLED;
- }
- SetAutoMounterStatus(status);
-}
-
-/***************************************************************************/
-
-void AutoMounter::GetStatus(bool& umsAvail, bool& umsConfigured, bool& umsEnabled,
- bool& mtpAvail, bool& mtpConfigured, bool& mtpEnabled,
- bool& rndisConfigured)
-{
- umsAvail = false;
- umsConfigured = false;
- umsEnabled = false;
- mtpAvail = false;
- mtpConfigured = false;
- mtpEnabled = false;
- rndisConfigured = false;
-
- if (access(ICS_SYS_USB_FUNCTIONS, F_OK) != 0) {
- return;
- }
-
- char functionsStr[60];
- if (!ReadSysFile(ICS_SYS_USB_FUNCTIONS, functionsStr, sizeof(functionsStr))) {
- ERR("Error reading file '%s': %s", ICS_SYS_USB_FUNCTIONS, strerror(errno));
- functionsStr[0] = '\0';
- }
- DBG("GetStatus: USB functions: '%s'", functionsStr);
-
- bool usbConfigured = IsUsbConfigured();
-
- // On the Nexus 4/5, it advertises that the UMS usb function is available,
- // but we have a further requirement that mass_storage be in the
- // persist.sys.usb.config property.
- char persistSysUsbConfig[PROPERTY_VALUE_MAX];
- property_get(PERSIST_SYS_USB_CONFIG, persistSysUsbConfig, "");
- if (IsUsbFunctionEnabled(persistSysUsbConfig, USB_FUNC_UMS)) {
- umsAvail = (access(ICS_SYS_UMS_DIRECTORY, F_OK) == 0);
- }
- if (umsAvail) {
- umsConfigured = usbConfigured && strstr(functionsStr, USB_FUNC_UMS) != nullptr;
- umsEnabled = (mMode == AUTOMOUNTER_ENABLE_UMS) ||
- ((mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) && umsConfigured);
- } else {
- umsConfigured = false;
- umsEnabled = false;
- }
-
- mtpAvail = (access(ICS_SYS_MTP_DIRECTORY, F_OK) == 0);
- if (mtpAvail) {
- mtpConfigured = usbConfigured && strstr(functionsStr, USB_FUNC_MTP) != nullptr;
- mtpEnabled = (mMode == AUTOMOUNTER_ENABLE_MTP) ||
- ((mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) && mtpConfigured);
- } else {
- mtpConfigured = false;
- mtpEnabled = false;
- }
-
- rndisConfigured = strstr(functionsStr, USB_FUNC_RNDIS) != nullptr;
-}
-
-
-nsresult AutoMounter::Dump(nsACString& desc)
-{
- DBG("GetState!");
- bool umsAvail, umsConfigured, umsEnabled;
- bool mtpAvail, mtpConfigured, mtpEnabled;
- bool rndisConfigured;
- GetStatus(umsAvail, umsConfigured, umsEnabled, mtpAvail,
- mtpConfigured, mtpEnabled, rndisConfigured);
- if (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) {
- // DISABLE_WHEN_UNPLUGGED implies already enabled.
- if (!IsUsbCablePluggedIn()) {
- mMode = AUTOMOUNTER_DISABLE;
- mtpEnabled = false;
- umsEnabled = false;
- }
- }
-
- // Automounter information
- desc += "Current Mode:";
- desc += ModeStr(mMode);
- desc += "|";
-
-
- desc += "Current State:";
- desc += StateStr(mState);
- desc += "|";
-
- desc += "UMS Status:";
- if (umsAvail) {
- desc += "Available";
- } else {
- desc += "UnAvailable";
- }
- desc += ",";
- if (umsConfigured) {
- desc += "Configured";
- } else {
- desc += "Un-Configured";
- }
- desc += ",";
- if (umsEnabled) {
- desc += "Enabled";
- } else {
- desc += "Disabled";
- }
- desc += "|";
-
-
- desc += "MTP Status:";
- if (mtpAvail) {
- desc += "Available";
- } else {
- desc += "UnAvailable";
- }
- desc += ",";
- if (mtpConfigured) {
- desc += "Configured";
- } else {
- desc += "Un-Configured";
- }
- desc += ",";
- if (mtpEnabled) {
- desc += "Enabled";
- } else {
- desc += "Disabled";
- }
-
-
- // Volume information
- VolumeArray::index_type volIndex;
- VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
-
- desc += "|";
- desc += vol->NameStr();
- desc += ":";
- desc += vol->StateStr();
- desc += "@";
- desc += vol->MountPoint().get();
-
- if (!vol->MediaPresent()) {
- continue;
- }
-
- if (vol->CanBeShared()) {
- desc += ",CanBeShared";
- }
- if (vol->CanBeFormatted()) {
- desc += ",CanBeFormatted";
- }
- if (vol->CanBeMounted()) {
- desc += ",CanBeMounted";
- }
- if (vol->IsRemovable()) {
- desc += ",Removable";
- }
- if (vol->IsHotSwappable()) {
- desc += ",HotSwappable";
- }
- }
-
- return NS_OK;
-}
-
-
-static void
-InitAutoMounterIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(!sAutoMounter);
-
- sAutoMounter = new AutoMounter();
-}
-
-static void
-ShutdownAutoMounterIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- sAutoMounter = nullptr;
- ShutdownVolumeManager();
-}
-
-static void
-SetAutoMounterModeIOThread(const int32_t& aMode)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->SetMode(aMode);
-}
-
-static void
-SetAutoMounterSharingModeIOThread(const nsCString& aVolumeName, const bool& aAllowSharing)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->SetSharingMode(aVolumeName, aAllowSharing);
-}
-
-static void
-AutoMounterFormatVolumeIOThread(const nsCString& aVolumeName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->FormatVolume(aVolumeName);
-}
-
-static void
-AutoMounterMountVolumeIOThread(const nsCString& aVolumeName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->MountVolume(aVolumeName);
-}
-
-static void
-AutoMounterUnmountVolumeIOThread(const nsCString& aVolumeName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->UnmountVolume(aVolumeName);
-}
-
-static void
-UsbCableEventIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (!sAutoMounter) {
- return;
- }
- DBG("Calling UpdateState due to USBCableEvent");
- sAutoMounter->UpdateState();
-}
-
-/**************************************************************************
-*
-* Public API
-*
-* Since the AutoMounter runs in IO Thread context, we need to switch
-* to IOThread context before we can do anything.
-*
-**************************************************************************/
-
-class UsbCableObserver final : public hal::SwitchObserver
-{
- ~UsbCableObserver()
- {
- hal::UnregisterSwitchObserver(hal::SWITCH_USB, this);
- }
-
-public:
- NS_INLINE_DECL_REFCOUNTING(UsbCableObserver)
-
- UsbCableObserver()
- {
- hal::RegisterSwitchObserver(hal::SWITCH_USB, this);
- }
-
- virtual void Notify(const hal::SwitchEvent& aEvent)
- {
- DBG("UsbCable switch device: %d state: %s\n",
- aEvent.device(), SwitchStateStr(aEvent));
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(UsbCableEventIOThread));
- }
-};
-
-static StaticRefPtr<UsbCableObserver> sUsbCableObserver;
-static StaticRefPtr<AutoMounterSetting> sAutoMounterSetting;
-
-void
-InitAutoMounter()
-{
- InitVolumeManager();
- sAutoMounterSetting = new AutoMounterSetting();
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(InitAutoMounterIOThread));
-
- // Switch Observers need to run on the main thread, so we need to
- // start it here and have it send events to the AutoMounter running
- // on the IO Thread.
- sUsbCableObserver = new UsbCableObserver();
-
- // Register status reporter into reporter manager
- if(status_reporter_progress == REPORTER_UNREGISTERED) {
- NS_RegisterStatusReporter(new NS_STATUS_REPORTER_NAME(AutoMounter));
- }
- status_reporter_progress = REPORTER_REGISTERED;
-}
-
-int32_t
-GetAutoMounterStatus()
-{
- if (sAutoMounterSetting) {
- return sAutoMounterSetting->GetStatus();
- }
- return AUTOMOUNTER_STATUS_DISABLED;
-}
-
-//static
-void
-SetAutoMounterStatus(int32_t aStatus)
-{
- if (sAutoMounterSetting) {
- sAutoMounterSetting->SetStatus(aStatus);
- }
-}
-
-void
-SetAutoMounterMode(int32_t aMode)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(SetAutoMounterModeIOThread, aMode));
-}
-
-void
-SetAutoMounterSharingMode(const nsCString& aVolumeName, bool aAllowSharing)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(SetAutoMounterSharingModeIOThread,
- aVolumeName, aAllowSharing));
-}
-
-void
-AutoMounterFormatVolume(const nsCString& aVolumeName)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(AutoMounterFormatVolumeIOThread,
- aVolumeName));
-}
-
-void
-AutoMounterMountVolume(const nsCString& aVolumeName)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(AutoMounterMountVolumeIOThread,
- aVolumeName));
-}
-
-void
-AutoMounterUnmountVolume(const nsCString& aVolumeName)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(AutoMounterUnmountVolumeIOThread,
- aVolumeName));
-}
-
-void
-ShutdownAutoMounter()
-{
- if (sAutoMounter) {
- DBG("ShutdownAutoMounter: About to StopMtpServer");
- sAutoMounter->StopMtpServer();
- // Unregister status reporter into reporter manager
- if(status_reporter_progress == REPORTER_REGISTERED) {
- NS_UnregisterStatusReporter(new NS_STATUS_REPORTER_NAME(AutoMounter));
- }
- status_reporter_progress = REPORTER_UNREGISTERED;
- }
- sAutoMounterSetting = nullptr;
- sUsbCableObserver = nullptr;
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(ShutdownAutoMounterIOThread));
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/AutoMounter.h b/dom/system/gonk/AutoMounter.h
deleted file mode 100644
index ea98cadf1..000000000
--- a/dom/system/gonk/AutoMounter.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_automounter_h__
-#define mozilla_system_automounter_h__
-
-#include <stdint.h>
-
-class nsCString;
-
-namespace mozilla {
-namespace system {
-
-// AutoMounter modes
-#define AUTOMOUNTER_DISABLE 0
-#define AUTOMOUNTER_ENABLE_UMS 1
-#define AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED 2
-#define AUTOMOUNTER_ENABLE_MTP 3
-
-// Automounter statuses
-#define AUTOMOUNTER_STATUS_DISABLED 0
-#define AUTOMOUNTER_STATUS_ENABLED 1
-#define AUTOMOUNTER_STATUS_FILES_OPEN 2
-
-/**
- * Initialize the automounter. This causes some of the phone's
- * directories to show up on the host when the phone is plugged
- * into the host via USB.
- *
- * When the AutoMounter starts, it will poll the current state
- * of affairs (usb cable plugged in, automounter enabled, etc)
- * and try to make the state of the volumes match.
- */
-void
-InitAutoMounter();
-
-/**
- * Sets the enabled state of the automounter.
- *
- * This will in turn cause the automounter to re-evaluate
- * whether it should mount/unmount/share/unshare volumes.
- */
-void
-SetAutoMounterMode(int32_t aMode);
-
-/**
- * Reports the status of the automounter.
- */
-int32_t
-GetAutoMounterStatus();
-
-/**
- * Sets the sharing mode of an individual volume.
- *
- * If a volume is enabled for sharing, and the autmounter
- * is in a state to share, then the volume will be shared
- * with the PC.
- */
-void
-SetAutoMounterSharingMode(const nsCString& aVolumeName, bool aAllowSharing);
-
-/**
- * Formats the volume with specified volume name.
- *
- * If the volume is ready to format, automounter
- * will unmount it, format it and then mount it again.
- */
-void
-AutoMounterFormatVolume(const nsCString& aVolumeName);
-
-/**
- * Mounts the volume with specified volume name.
- *
- * If the volume is already unmounted, automounter
- * will mount it. Otherwise automounter will skip this.
- */
-void
-AutoMounterMountVolume(const nsCString& aVolumeName);
-
-/**
- * Unmounts the volume with specified volume name.
- *
- * If the volume is already mounted, automounter
- * will unmount it. Otherwise automounter will skip this.
- */
-void
-AutoMounterUnmountVolume(const nsCString& aVolumeName);
-
-/**
- * Shuts down the automounter.
- *
- * This leaves the volumes in whatever state they're in.
- */
-void
-ShutdownAutoMounter();
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_automounter_h__
diff --git a/dom/system/gonk/AutoMounterSetting.cpp b/dom/system/gonk/AutoMounterSetting.cpp
deleted file mode 100644
index 606bcce04..000000000
--- a/dom/system/gonk/AutoMounterSetting.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "AutoMounter.h"
-#include "AutoMounterSetting.h"
-
-#include "base/message_loop.h"
-#include "jsapi.h"
-#include "mozilla/Services.h"
-#include "nsCOMPtr.h"
-#include "nsContentUtils.h"
-#include "nsDebug.h"
-#include "nsIObserverService.h"
-#include "nsISettingsService.h"
-#include "nsJSUtils.h"
-#include "nsPrintfCString.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "nsThreadUtils.h"
-#include "xpcpublic.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/SettingChangeNotificationBinding.h"
-
-#undef LOG
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounterSetting" , ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounterSetting" , ## args)
-
-#define UMS_MODE "ums.mode"
-#define UMS_STATUS "ums.status"
-#define UMS_VOLUME_ENABLED_PREFIX "ums.volume."
-#define UMS_VOLUME_ENABLED_SUFFIX ".enabled"
-#define MOZSETTINGS_CHANGED "mozsettings-changed"
-
-using namespace mozilla::dom;
-
-namespace mozilla {
-namespace system {
-
-class SettingsServiceCallback final : public nsISettingsServiceCallback
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
-
- SettingsServiceCallback() {}
-
- NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
- {
- if (aResult.isInt32()) {
- int32_t mode = aResult.toInt32();
- SetAutoMounterMode(mode);
- }
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(const nsAString& aName)
- {
- ERR("SettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
- return NS_OK;
- }
-
-protected:
- ~SettingsServiceCallback() {}
-};
-
-NS_IMPL_ISUPPORTS(SettingsServiceCallback, nsISettingsServiceCallback)
-
-class CheckVolumeSettingsCallback final : public nsISettingsServiceCallback
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
-
- CheckVolumeSettingsCallback(const nsACString& aVolumeName)
- : mVolumeName(aVolumeName) {}
-
- NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
- {
- if (aResult.isBoolean()) {
- bool isSharingEnabled = aResult.toBoolean();
- SetAutoMounterSharingMode(mVolumeName, isSharingEnabled);
- }
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(const nsAString& aName)
- {
- ERR("CheckVolumeSettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
- return NS_OK;
- }
-
-protected:
- ~CheckVolumeSettingsCallback() {}
-
-private:
- nsCString mVolumeName;
-};
-
-NS_IMPL_ISUPPORTS(CheckVolumeSettingsCallback, nsISettingsServiceCallback)
-
-AutoMounterSetting::AutoMounterSetting()
- : mStatus(AUTOMOUNTER_STATUS_DISABLED)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // Setup an observer to watch changes to the setting
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (!observerService) {
- ERR("GetObserverService failed");
- return;
- }
- nsresult rv;
- rv = observerService->AddObserver(this, MOZSETTINGS_CHANGED, false);
- if (NS_FAILED(rv)) {
- ERR("AddObserver failed");
- return;
- }
-
- // Force ums.mode to be 0 initially. We do this because settings are persisted.
- // We don't want UMS to be enabled until such time as the phone is unlocked,
- // and gaia/apps/system/js/storage.js takes care of detecting when the phone
- // becomes unlocked and changes ums.mode appropriately.
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- if (!settingsService) {
- ERR("Failed to get settingsLock service!");
- return;
- }
- nsCOMPtr<nsISettingsServiceLock> lock;
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- nsCOMPtr<nsISettingsServiceCallback> callback = new SettingsServiceCallback();
- JS::Rooted<JS::Value> value(RootingCx());
- value.setInt32(AUTOMOUNTER_DISABLE);
- lock->Set(UMS_MODE, value, callback, nullptr);
- value.setInt32(mStatus);
- lock->Set(UMS_STATUS, value, nullptr, nullptr);
-}
-
-AutoMounterSetting::~AutoMounterSetting()
-{
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (observerService) {
- observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
- }
-}
-
-NS_IMPL_ISUPPORTS(AutoMounterSetting, nsIObserver)
-
-const char *
-AutoMounterSetting::StatusStr(int32_t aStatus)
-{
- switch (aStatus) {
- case AUTOMOUNTER_STATUS_DISABLED: return "Disabled";
- case AUTOMOUNTER_STATUS_ENABLED: return "Enabled";
- case AUTOMOUNTER_STATUS_FILES_OPEN: return "FilesOpen";
- }
- return "??? Unknown ???";
-}
-
-class CheckVolumeSettingsRunnable : public Runnable
-{
-public:
- CheckVolumeSettingsRunnable(const nsACString& aVolumeName)
- : mVolumeName(aVolumeName) {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- NS_ENSURE_TRUE(settingsService, NS_ERROR_FAILURE);
- nsCOMPtr<nsISettingsServiceLock> lock;
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- nsCOMPtr<nsISettingsServiceCallback> callback =
- new CheckVolumeSettingsCallback(mVolumeName);
- nsPrintfCString setting(UMS_VOLUME_ENABLED_PREFIX "%s" UMS_VOLUME_ENABLED_SUFFIX,
- mVolumeName.get());
- lock->Get(setting.get(), callback);
- return NS_OK;
- }
-
-private:
- nsCString mVolumeName;
-};
-
-//static
-void
-AutoMounterSetting::CheckVolumeSettings(const nsACString& aVolumeName)
-{
- NS_DispatchToMainThread(new CheckVolumeSettingsRunnable(aVolumeName));
-}
-
-class SetStatusRunnable : public Runnable
-{
-public:
- SetStatusRunnable(int32_t aStatus) : mStatus(aStatus) {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- NS_ENSURE_TRUE(settingsService, NS_ERROR_FAILURE);
- nsCOMPtr<nsISettingsServiceLock> lock;
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- // lock may be null if this gets called during shutdown.
- if (lock) {
- JS::Rooted<JS::Value> value(RootingCx(),
- JS::Int32Value(mStatus));
- lock->Set(UMS_STATUS, value, nullptr, nullptr);
- }
- return NS_OK;
- }
-
-private:
- int32_t mStatus;
-};
-
-//static
-void
-AutoMounterSetting::SetStatus(int32_t aStatus)
-{
- if (aStatus != mStatus) {
- LOG("Changing status from '%s' to '%s'",
- StatusStr(mStatus), StatusStr(aStatus));
- mStatus = aStatus;
- NS_DispatchToMainThread(new SetStatusRunnable(aStatus));
- }
-}
-
-NS_IMETHODIMP
-AutoMounterSetting::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
- return NS_OK;
- }
-
- // Note that this function gets called for any and all settings changes,
- // so we need to carefully check if we have the one we're interested in.
- //
- // The string that we're interested in will be a JSON string that looks like:
- // {"key":"ums.autoMount","value":true}
-
- RootedDictionary<SettingChangeNotification> setting(RootingCx());
- if (!WrappedJSToDictionary(aSubject, setting)) {
- return NS_OK;
- }
-
- // Check for ums.mode changes
- if (setting.mKey.EqualsASCII(UMS_MODE)) {
- if (!setting.mValue.isInt32()) {
- return NS_OK;
- }
- int32_t mode = setting.mValue.toInt32();
- SetAutoMounterMode(mode);
- return NS_OK;
- }
-
- // Check for ums.volume.NAME.enabled
- if (StringBeginsWith(setting.mKey, NS_LITERAL_STRING(UMS_VOLUME_ENABLED_PREFIX)) &&
- StringEndsWith(setting.mKey, NS_LITERAL_STRING(UMS_VOLUME_ENABLED_SUFFIX))) {
- if (!setting.mValue.isBoolean()) {
- return NS_OK;
- }
- const size_t prefixLen = sizeof(UMS_VOLUME_ENABLED_PREFIX) - 1;
- const size_t suffixLen = sizeof(UMS_VOLUME_ENABLED_SUFFIX) - 1;
- nsDependentSubstring volumeName =
- Substring(setting.mKey, prefixLen, setting.mKey.Length() - prefixLen - suffixLen);
- bool isSharingEnabled = setting.mValue.toBoolean();
- SetAutoMounterSharingMode(NS_LossyConvertUTF16toASCII(volumeName), isSharingEnabled);
- return NS_OK;
- }
-
- return NS_OK;
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/AutoMounterSetting.h b/dom/system/gonk/AutoMounterSetting.h
deleted file mode 100644
index 7972de379..000000000
--- a/dom/system/gonk/AutoMounterSetting.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_automountersetting_h__
-#define mozilla_system_automountersetting_h__
-
-#include "nsIObserver.h"
-
-namespace mozilla {
-namespace system {
-
-class AutoMounterSetting : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- AutoMounterSetting();
-
- static void CheckVolumeSettings(const nsACString& aVolumeName);
-
- int32_t GetStatus() { return mStatus; }
- void SetStatus(int32_t aStatus);
- const char *StatusStr(int32_t aStatus);
-
-protected:
- virtual ~AutoMounterSetting();
-
-private:
- int32_t mStatus;
-};
-
-} // namespace system
-} // namespace mozilla
-
-#endif // mozilla_system_automountersetting_h__
-
diff --git a/dom/system/gonk/DataCallInterfaceService.js b/dom/system/gonk/DataCallInterfaceService.js
deleted file mode 100644
index 0f0e7101c..000000000
--- a/dom/system/gonk/DataCallInterfaceService.js
+++ /dev/null
@@ -1,276 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const DATACALLINTERFACE_CONTRACTID = "@mozilla.org/datacall/interface;1";
-const DATACALLINTERFACESERVICE_CONTRACTID =
- "@mozilla.org/datacall/interfaceservice;1";
-const DATACALLINTERFACE_CID =
- Components.ID("{ff669306-4390-462a-989b-ba37fc42153f}");
-const DATACALLINTERFACESERVICE_CID =
- Components.ID("{e23e9337-592d-40b9-8cef-7bd47c28b72e}");
-
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const PREF_RIL_DEBUG_ENABLED = "ril.debugging.enabled";
-
-XPCOMUtils.defineLazyGetter(this, "RIL", function () {
- let obj = {};
- Cu.import("resource://gre/modules/ril_consts.js", obj);
- return obj;
-});
-
-XPCOMUtils.defineLazyServiceGetter(this, "gRil",
- "@mozilla.org/ril;1",
- "nsIRadioInterfaceLayer");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIMobileConnectionService");
-
-var DEBUG = RIL.DEBUG_RIL;
-
-function updateDebugFlag() {
- // Read debug setting from pref
- let debugPref;
- try {
- debugPref = Services.prefs.getBoolPref(PREF_RIL_DEBUG_ENABLED);
- } catch (e) {
- debugPref = false;
- }
- DEBUG = debugPref || RIL.DEBUG_RIL;
-}
-updateDebugFlag();
-
-function DataCall(aAttributes) {
- for (let key in aAttributes) {
- if (key === "pdpType") {
- // Convert pdp type into constant int value.
- this[key] = RIL.RIL_DATACALL_PDP_TYPES.indexOf(aAttributes[key]);
- continue;
- }
-
- this[key] = aAttributes[key];
- }
-}
-DataCall.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCall]),
-
- failCause: Ci.nsIDataCallInterface.DATACALL_FAIL_NONE,
- suggestedRetryTime: -1,
- cid: -1,
- active: -1,
- pdpType: -1,
- ifname: null,
- addreses: null,
- dnses: null,
- gateways: null,
- pcscf: null,
- mtu: -1
-};
-
-function DataCallInterfaceService() {
- this._dataCallInterfaces = [];
-
- let numClients = gRil.numRadioInterfaces;
- for (let i = 0; i < numClients; i++) {
- this._dataCallInterfaces.push(new DataCallInterface(i));
- }
-
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
- Services.prefs.addObserver(PREF_RIL_DEBUG_ENABLED, this, false);
-}
-DataCallInterfaceService.prototype = {
- classID: DATACALLINTERFACESERVICE_CID,
- classInfo: XPCOMUtils.generateCI({
- classID: DATACALLINTERFACESERVICE_CID,
- contractID: DATACALLINTERFACESERVICE_CONTRACTID,
- classDescription: "Data Call Interface Service",
- interfaces: [Ci.nsIDataCallInterfaceService,
- Ci.nsIGonkDataCallInterfaceService]
- }),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallInterfaceService,
- Ci.nsIGonkDataCallInterfaceService],
- Ci.nsIObserver),
-
- // An array of DataCallInterface instances.
- _dataCallInterfaces: null,
-
- debug: function(aMessage) {
- dump("-*- DataCallInterfaceService: " + aMessage + "\n");
- },
-
- // nsIDataCallInterfaceService
-
- getDataCallInterface: function(aClientId) {
- let dataCallInterface = this._dataCallInterfaces[aClientId];
- if (!dataCallInterface) {
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- return dataCallInterface;
- },
-
- // nsIGonkDataCallInterfaceService
-
- notifyDataCallListChanged: function(aClientId, aCount, aDataCalls) {
- let dataCallInterface = this.getDataCallInterface(aClientId);
- dataCallInterface.handleDataCallListChanged(aCount, aDataCalls);
- },
-
- // nsIObserver
-
- observe: function(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_PREF_CHANGED:
- if (aData === PREF_RIL_DEBUG_ENABLED) {
- updateDebugFlag();
- }
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- Services.prefs.removeObserver(PREF_RIL_DEBUG_ENABLED, this);
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- break;
- }
- },
-};
-
-function DataCallInterface(aClientId) {
- this._clientId = aClientId;
- this._radioInterface = gRil.getRadioInterface(aClientId);
- this._listeners = [];
-
- if (DEBUG) this.debug("DataCallInterface: " + aClientId);
-}
-DataCallInterface.prototype = {
- classID: DATACALLINTERFACE_CID,
- classInfo: XPCOMUtils.generateCI({classID: DATACALLINTERFACE_CID,
- contractID: DATACALLINTERFACE_CONTRACTID,
- classDescription: "Data Call Interface",
- interfaces: [Ci.nsIDataCallInterface]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallInterface]),
-
- debug: function(aMessage) {
- dump("-*- DataCallInterface[" + this._clientId + "]: " + aMessage + "\n");
- },
-
- _clientId: -1,
-
- _radioInterface: null,
-
- _listeners: null,
-
- // nsIDataCallInterface
-
- setupDataCall: function(aApn, aUsername, aPassword, aAuthType, aPdpType,
- aCallback) {
- let connection =
- gMobileConnectionService.getItemByServiceId(this._clientId);
- let dataInfo = connection && connection.data;
- let radioTechType = dataInfo.type;
- let radioTechnology = RIL.GECKO_RADIO_TECH.indexOf(radioTechType);
- // Convert pdp type into string value.
- let pdpType = RIL.RIL_DATACALL_PDP_TYPES[aPdpType];
-
- this._radioInterface.sendWorkerMessage("setupDataCall", {
- radioTech: radioTechnology,
- apn: aApn,
- user: aUsername,
- passwd: aPassword,
- chappap: aAuthType,
- pdptype: pdpType
- }, (aResponse) => {
- if (aResponse.errorMsg) {
- aCallback.notifyError(aResponse.errorMsg);
- } else {
- let dataCall = new DataCall(aResponse);
- aCallback.notifySetupDataCallSuccess(dataCall);
- }
- });
- },
-
- deactivateDataCall: function(aCid, aReason, aCallback) {
- this._radioInterface.sendWorkerMessage("deactivateDataCall", {
- cid: aCid,
- reason: aReason
- }, (aResponse) => {
- if (aResponse.errorMsg) {
- aCallback.notifyError(aResponse.errorMsg);
- } else {
- aCallback.notifySuccess();
- }
- });
- },
-
- getDataCallList: function(aCallback) {
- this._radioInterface.sendWorkerMessage("getDataCallList", null,
- (aResponse) => {
- if (aResponse.errorMsg) {
- aCallback.notifyError(aResponse.errorMsg);
- } else {
- let dataCalls = aResponse.datacalls.map(
- dataCall => new DataCall(dataCall));
- aCallback.notifyGetDataCallListSuccess(dataCalls.length, dataCalls);
- }
- });
- },
-
- setDataRegistration: function(aAttach, aCallback) {
- this._radioInterface.sendWorkerMessage("setDataRegistration", {
- attach: aAttach
- }, (aResponse) => {
- if (aResponse.errorMsg) {
- aCallback.notifyError(aResponse.errorMsg);
- } else {
- aCallback.notifySuccess();
- }
- });
- },
-
- handleDataCallListChanged: function(aCount, aDataCalls) {
- this._notifyAllListeners("notifyDataCallListChanged", [aCount, aDataCalls]);
- },
-
- _notifyAllListeners: function(aMethodName, aArgs) {
- let listeners = this._listeners.slice();
- for (let listener of listeners) {
- if (this._listeners.indexOf(listener) == -1) {
- // Listener has been unregistered in previous run.
- continue;
- }
-
- let handler = listener[aMethodName];
- try {
- handler.apply(listener, aArgs);
- } catch (e) {
- if (DEBUG) {
- this.debug("listener for " + aMethodName + " threw an exception: " + e);
- }
- }
- }
- },
-
- registerListener: function(aListener) {
- if (this._listeners.indexOf(aListener) >= 0) {
- return;
- }
-
- this._listeners.push(aListener);
- },
-
- unregisterListener: function(aListener) {
- let index = this._listeners.indexOf(aListener);
- if (index >= 0) {
- this._listeners.splice(index, 1);
- }
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataCallInterfaceService]); \ No newline at end of file
diff --git a/dom/system/gonk/DataCallInterfaceService.manifest b/dom/system/gonk/DataCallInterfaceService.manifest
deleted file mode 100644
index bf062c7e9..000000000
--- a/dom/system/gonk/DataCallInterfaceService.manifest
+++ /dev/null
@@ -1,6 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-component {e23e9337-592d-40b9-8cef-7bd47c28b72e} DataCallInterfaceService.js
-contract @mozilla.org/datacall/interfaceservice;1 {e23e9337-592d-40b9-8cef-7bd47c28b72e} \ No newline at end of file
diff --git a/dom/system/gonk/DataCallManager.js b/dom/system/gonk/DataCallManager.js
deleted file mode 100644
index 5411987cd..000000000
--- a/dom/system/gonk/DataCallManager.js
+++ /dev/null
@@ -1,1726 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIMobileConnectionService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
- "@mozilla.org/icc/iccservice;1",
- "nsIIccService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gDataCallInterfaceService",
- "@mozilla.org/datacall/interfaceservice;1",
- "nsIDataCallInterfaceService");
-
-XPCOMUtils.defineLazyGetter(this, "RIL", function() {
- let obj = {};
- Cu.import("resource://gre/modules/ril_consts.js", obj);
- return obj;
-});
-
-// Ril quirk to attach data registration on demand.
-var RILQUIRKS_DATA_REGISTRATION_ON_DEMAND =
- libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true";
-
-// Ril quirk to control the uicc/data subscription.
-var RILQUIRKS_SUBSCRIPTION_CONTROL =
- libcutils.property_get("ro.moz.ril.subscription_control", "false") == "true";
-
-// Ril quirk to enable IPv6 protocol/roaming protocol in APN settings.
-var RILQUIRKS_HAVE_IPV6 =
- libcutils.property_get("ro.moz.ril.ipv6", "false") == "true";
-
-const DATACALLMANAGER_CID =
- Components.ID("{35b9efa2-e42c-45ce-8210-0a13e6f4aadc}");
-const DATACALLHANDLER_CID =
- Components.ID("{132b650f-c4d8-4731-96c5-83785cb31dee}");
-const RILNETWORKINTERFACE_CID =
- Components.ID("{9574ee84-5d0d-4814-b9e6-8b279e03dcf4}");
-const RILNETWORKINFO_CID =
- Components.ID("{dd6cf2f0-f0e3-449f-a69e-7c34fdcb8d4b}");
-
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed";
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const TOPIC_DATA_CALL_ERROR = "data-call-error";
-const PREF_RIL_DEBUG_ENABLED = "ril.debugging.enabled";
-
-const NETWORK_TYPE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_TYPE_UNKNOWN;
-const NETWORK_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
-const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
-const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS;
-const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL;
-const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS;
-const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN;
-const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA;
-
-const NETWORK_STATE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN;
-const NETWORK_STATE_CONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTING;
-const NETWORK_STATE_CONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
-const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTING;
-const NETWORK_STATE_DISCONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
-
-const INT32_MAX = 2147483647;
-
-// set to true in ril_consts.js to see debug messages
-var DEBUG = RIL.DEBUG_RIL;
-
-function updateDebugFlag() {
- // Read debug setting from pref
- let debugPref;
- try {
- debugPref = Services.prefs.getBoolPref(PREF_RIL_DEBUG_ENABLED);
- } catch (e) {
- debugPref = false;
- }
- DEBUG = debugPref || RIL.DEBUG_RIL;
-}
-updateDebugFlag();
-
-function DataCallManager() {
- this._connectionHandlers = [];
-
- let numRadioInterfaces = gMobileConnectionService.numItems;
- for (let clientId = 0; clientId < numRadioInterfaces; clientId++) {
- this._connectionHandlers.push(new DataCallHandler(clientId));
- }
-
- let lock = gSettingsService.createLock();
- // Read the APN data from the settings DB.
- lock.get("ril.data.apnSettings", this);
- // Read the data enabled setting from DB.
- lock.get("ril.data.enabled", this);
- lock.get("ril.data.roaming_enabled", this);
- // Read the default client id for data call.
- lock.get("ril.data.defaultServiceId", this);
-
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
- Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false);
- Services.prefs.addObserver(PREF_RIL_DEBUG_ENABLED, this, false);
-}
-DataCallManager.prototype = {
- classID: DATACALLMANAGER_CID,
- classInfo: XPCOMUtils.generateCI({classID: DATACALLMANAGER_CID,
- classDescription: "Data Call Manager",
- interfaces: [Ci.nsIDataCallManager]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallManager,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- _connectionHandlers: null,
-
- // Flag to determine the data state to start with when we boot up. It
- // corresponds to the 'ril.data.enabled' setting from the UI.
- _dataEnabled: false,
-
- // Flag to record the default client id for data call. It corresponds to
- // the 'ril.data.defaultServiceId' setting from the UI.
- _dataDefaultClientId: -1,
-
- // Flag to record the current default client id for data call.
- // It differs from _dataDefaultClientId in that it is set only when
- // the switch of client id process is done.
- _currentDataClientId: -1,
-
- // Pending function to execute when we are notified that another data call has
- // been disconnected.
- _pendingDataCallRequest: null,
-
- debug: function(aMsg) {
- dump("-*- DataCallManager: " + aMsg + "\n");
- },
-
- get dataDefaultServiceId() {
- return this._dataDefaultClientId;
- },
-
- getDataCallHandler: function(aClientId) {
- let handler = this._connectionHandlers[aClientId]
- if (!handler) {
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- return handler;
- },
-
- _setDataRegistration: function(aDataCallInterface, aAttach) {
- return new Promise(function(aResolve, aReject) {
- let callback = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallCallback]),
- notifySuccess: function() {
- aResolve();
- },
- notifyError: function(aErrorMsg) {
- aReject(aErrorMsg);
- }
- };
-
- aDataCallInterface.setDataRegistration(aAttach, callback);
- });
- },
-
- _handleDataClientIdChange: function(aNewClientId) {
- if (this._dataDefaultClientId === aNewClientId) {
- return;
- }
- this._dataDefaultClientId = aNewClientId;
-
- // This is to handle boot up stage.
- if (this._currentDataClientId == -1) {
- this._currentDataClientId = this._dataDefaultClientId;
- let connHandler = this._connectionHandlers[this._currentDataClientId];
- let dcInterface = connHandler.dataCallInterface;
- if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
- RILQUIRKS_SUBSCRIPTION_CONTROL) {
- this._setDataRegistration(dcInterface, true);
- }
- if (this._dataEnabled) {
- let settings = connHandler.dataCallSettings;
- settings.oldEnabled = settings.enabled;
- settings.enabled = true;
- connHandler.updateRILNetworkInterface();
- }
- return;
- }
-
- let oldConnHandler = this._connectionHandlers[this._currentDataClientId];
- let oldIface = oldConnHandler.dataCallInterface;
- let oldSettings = oldConnHandler.dataCallSettings;
- let newConnHandler = this._connectionHandlers[this._dataDefaultClientId];
- let newIface = newConnHandler.dataCallInterface;
- let newSettings = newConnHandler.dataCallSettings;
-
- let applyPendingDataSettings = () => {
- if (DEBUG) {
- this.debug("Apply pending data registration and settings.");
- }
-
- if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
- RILQUIRKS_SUBSCRIPTION_CONTROL) {
- this._setDataRegistration(oldIface, false).then(() => {
- if (this._dataEnabled) {
- newSettings.oldEnabled = newSettings.enabled;
- newSettings.enabled = true;
- }
- this._currentDataClientId = this._dataDefaultClientId;
-
- this._setDataRegistration(newIface, true).then(() => {
- newConnHandler.updateRILNetworkInterface();
- });
- });
- return;
- }
-
- if (this._dataEnabled) {
- newSettings.oldEnabled = newSettings.enabled;
- newSettings.enabled = true;
- }
-
- this._currentDataClientId = this._dataDefaultClientId;
- newConnHandler.updateRILNetworkInterface();
- };
-
- if (this._dataEnabled) {
- oldSettings.oldEnabled = oldSettings.enabled;
- oldSettings.enabled = false;
- }
-
- oldConnHandler.deactivateDataCallsAndWait().then(() => {
- applyPendingDataSettings();
- });
- },
-
- _shutdown: function() {
- for (let handler of this._connectionHandlers) {
- handler.shutdown();
- }
- this._connectionHandlers = null;
- Services.prefs.removeObserver(PREF_RIL_DEBUG_ENABLED, this);
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
- },
-
- /**
- * nsISettingsServiceCallback
- */
- handle: function(aName, aResult) {
- switch (aName) {
- case "ril.data.apnSettings":
- if (DEBUG) {
- this.debug("'ril.data.apnSettings' is now " +
- JSON.stringify(aResult));
- }
- if (!aResult) {
- break;
- }
- for (let clientId in this._connectionHandlers) {
- let handler = this._connectionHandlers[clientId];
- let apnSetting = aResult[clientId];
- if (handler && apnSetting) {
- handler.updateApnSettings(apnSetting);
- }
- }
- break;
- case "ril.data.enabled":
- if (DEBUG) {
- this.debug("'ril.data.enabled' is now " + aResult);
- }
- if (this._dataEnabled === aResult) {
- break;
- }
- this._dataEnabled = aResult;
-
- if (DEBUG) {
- this.debug("Default id for data call: " + this._dataDefaultClientId);
- }
- if (this._dataDefaultClientId === -1) {
- // We haven't got the default id for data from db.
- break;
- }
-
- let connHandler = this._connectionHandlers[this._dataDefaultClientId];
- let settings = connHandler.dataCallSettings;
- settings.oldEnabled = settings.enabled;
- settings.enabled = aResult;
- connHandler.updateRILNetworkInterface();
- break;
- case "ril.data.roaming_enabled":
- if (DEBUG) {
- this.debug("'ril.data.roaming_enabled' is now " + aResult);
- this.debug("Default id for data call: " + this._dataDefaultClientId);
- }
- for (let clientId = 0; clientId < this._connectionHandlers.length; clientId++) {
- let connHandler = this._connectionHandlers[clientId];
- let settings = connHandler.dataCallSettings;
- settings.roamingEnabled = Array.isArray(aResult) ? aResult[clientId]
- : aResult;
- }
- if (this._dataDefaultClientId === -1) {
- // We haven't got the default id for data from db.
- break;
- }
- this._connectionHandlers[this._dataDefaultClientId].updateRILNetworkInterface();
- break;
- case "ril.data.defaultServiceId":
- aResult = aResult || 0;
- if (DEBUG) {
- this.debug("'ril.data.defaultServiceId' is now " + aResult);
- }
- this._handleDataClientIdChange(aResult);
- break;
- }
- },
-
- handleError: function(aErrorMessage) {
- if (DEBUG) {
- this.debug("There was an error while reading RIL settings.");
- }
- },
-
- /**
- * nsIObserver interface methods.
- */
- observe: function(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_MOZSETTINGS_CHANGED:
- if ("wrappedJSObject" in aSubject) {
- aSubject = aSubject.wrappedJSObject;
- }
- this.handle(aSubject.key, aSubject.value);
- break;
- case TOPIC_PREF_CHANGED:
- if (aData === PREF_RIL_DEBUG_ENABLED) {
- updateDebugFlag();
- }
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- this._shutdown();
- break;
- }
- },
-};
-
-function DataCallHandler(aClientId) {
- // Initial owning attributes.
- this.clientId = aClientId;
- this.dataCallSettings = {
- oldEnabled: false,
- enabled: false,
- roamingEnabled: false
- };
- this._dataCalls = [];
- this._listeners = [];
-
- // This map is used to collect all the apn types and its corresponding
- // RILNetworkInterface.
- this.dataNetworkInterfaces = new Map();
-
- this.dataCallInterface = gDataCallInterfaceService.getDataCallInterface(aClientId);
- this.dataCallInterface.registerListener(this);
-
- let mobileConnection = gMobileConnectionService.getItemByServiceId(aClientId);
- mobileConnection.registerListener(this);
-
- this._dataInfo = {
- state: mobileConnection.data.state,
- type: mobileConnection.data.type,
- roaming: mobileConnection.data.roaming
- }
-}
-DataCallHandler.prototype = {
- classID: DATACALLHANDLER_CID,
- classInfo: XPCOMUtils.generateCI({classID: DATACALLHANDLER_CID,
- classDescription: "Data Call Handler",
- interfaces: [Ci.nsIDataCallHandler]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallHandler,
- Ci.nsIDataCallInterfaceListener,
- Ci.nsIMobileConnectionListener]),
-
- clientId: 0,
- dataCallInterface: null,
- dataCallSettings: null,
- dataNetworkInterfaces: null,
- _dataCalls: null,
- _dataInfo: null,
-
- // Apn settings to be setup after data call are cleared.
- _pendingApnSettings: null,
-
- debug: function(aMsg) {
- dump("-*- DataCallHandler[" + this.clientId + "]: " + aMsg + "\n");
- },
-
- shutdown: function() {
- // Shutdown all RIL network interfaces
- this.dataNetworkInterfaces.forEach(function(networkInterface) {
- gNetworkManager.unregisterNetworkInterface(networkInterface);
- networkInterface.shutdown();
- networkInterface = null;
- });
- this.dataNetworkInterfaces.clear();
- this._dataCalls = [];
- this.clientId = null;
-
- this.dataCallInterface.unregisterListener(this);
- this.dataCallInterface = null;
-
- let mobileConnection =
- gMobileConnectionService.getItemByServiceId(this.clientId);
- mobileConnection.unregisterListener(this);
- },
-
- /**
- * Check if we get all necessary APN data.
- */
- _validateApnSetting: function(aApnSetting) {
- return (aApnSetting &&
- aApnSetting.apn &&
- aApnSetting.types &&
- aApnSetting.types.length);
- },
-
- _convertApnType: function(aApnType) {
- switch (aApnType) {
- case "default":
- return NETWORK_TYPE_MOBILE;
- case "mms":
- return NETWORK_TYPE_MOBILE_MMS;
- case "supl":
- return NETWORK_TYPE_MOBILE_SUPL;
- case "ims":
- return NETWORK_TYPE_MOBILE_IMS;
- case "dun":
- return NETWORK_TYPE_MOBILE_DUN;
- case "fota":
- return NETWORK_TYPE_MOBILE_FOTA;
- default:
- return NETWORK_TYPE_UNKNOWN;
- }
- },
-
- _compareDataCallOptions: function(aDataCall, aNewDataCall) {
- return aDataCall.apnProfile.apn == aNewDataCall.apnProfile.apn &&
- aDataCall.apnProfile.user == aNewDataCall.apnProfile.user &&
- aDataCall.apnProfile.password == aNewDataCall.apnProfile.passwd &&
- aDataCall.apnProfile.authType == aNewDataCall.apnProfile.authType &&
- aDataCall.apnProfile.protocol == aNewDataCall.apnProfile.protocol &&
- aDataCall.apnProfile.roaming_protocol == aNewDataCall.apnProfile.roaming_protocol;
- },
-
- /**
- * This function will do the following steps:
- * 1. Clear the cached APN settings in the RIL.
- * 2. Combine APN, user name, and password as the key of |byApn| object to
- * refer to the corresponding APN setting.
- * 3. Use APN type as the index of |byType| object to refer to the
- * corresponding APN setting.
- * 4. Create RilNetworkInterface for each APN setting created at step 2.
- */
- _setupApnSettings: function(aNewApnSettings) {
- if (!aNewApnSettings) {
- return;
- }
- if (DEBUG) this.debug("setupApnSettings: " + JSON.stringify(aNewApnSettings));
-
- // Shutdown all network interfaces and clear data calls.
- this.dataNetworkInterfaces.forEach(function(networkInterface) {
- gNetworkManager.unregisterNetworkInterface(networkInterface);
- networkInterface.shutdown();
- networkInterface = null;
- });
- this.dataNetworkInterfaces.clear();
- this._dataCalls = [];
-
- // Cache the APN settings by APNs and by types in the RIL.
- for (let inputApnSetting of aNewApnSettings) {
- if (!this._validateApnSetting(inputApnSetting)) {
- continue;
- }
-
- // Use APN type as the key of dataNetworkInterfaces to refer to the
- // corresponding RILNetworkInterface.
- for (let i = 0; i < inputApnSetting.types.length; i++) {
- let apnType = inputApnSetting.types[i];
- let networkType = this._convertApnType(apnType);
- if (networkType === NETWORK_TYPE_UNKNOWN) {
- if (DEBUG) this.debug("Invalid apn type: " + apnType);
- continue;
- }
-
- if (DEBUG) this.debug("Preparing RILNetworkInterface for type: " + apnType);
- // Create DataCall for RILNetworkInterface or reuse one that is shareable.
- let dataCall;
- for (let i = 0; i < this._dataCalls.length; i++) {
- if (this._dataCalls[i].canHandleApn(inputApnSetting)) {
- if (DEBUG) this.debug("Found shareable DataCall, reusing it.");
- dataCall = this._dataCalls[i];
- break;
- }
- }
-
- if (!dataCall) {
- if (DEBUG) this.debug("No shareable DataCall found, creating one.");
- dataCall = new DataCall(this.clientId, inputApnSetting, this);
- this._dataCalls.push(dataCall);
- }
-
- try {
- let networkInterface = new RILNetworkInterface(this, networkType,
- inputApnSetting,
- dataCall);
- gNetworkManager.registerNetworkInterface(networkInterface);
- this.dataNetworkInterfaces.set(networkType, networkInterface);
- } catch (e) {
- if (DEBUG) {
- this.debug("Error setting up RILNetworkInterface for type " +
- apnType + ": " + e);
- }
- }
- }
- }
- },
-
- /**
- * Check if all data is disconnected.
- */
- allDataDisconnected: function() {
- for (let i = 0; i < this._dataCalls.length; i++) {
- let dataCall = this._dataCalls[i];
- if (dataCall.state != NETWORK_STATE_UNKNOWN &&
- dataCall.state != NETWORK_STATE_DISCONNECTED) {
- return false;
- }
- }
- return true;
- },
-
- deactivateDataCallsAndWait: function() {
- return new Promise((aResolve, aReject) => {
- this.deactivateDataCalls({
- notifyDataCallsDisconnected: function() {
- aResolve();
- }
- });
- });
- },
-
- updateApnSettings: function(aNewApnSettings) {
- if (!aNewApnSettings) {
- return;
- }
- if (this._pendingApnSettings) {
- // Change of apn settings in process, just update to the newest.
- this._pengingApnSettings = aNewApnSettings;
- return;
- }
-
- this._pendingApnSettings = aNewApnSettings;
- this.deactivateDataCallsAndWait().then(() => {
- this._setupApnSettings(this._pendingApnSettings);
- this._pendingApnSettings = null;
- this.updateRILNetworkInterface();
- });
- },
-
- updateRILNetworkInterface: function() {
- let networkInterface = this.dataNetworkInterfaces.get(NETWORK_TYPE_MOBILE);
- if (!networkInterface) {
- if (DEBUG) {
- this.debug("No network interface for default data.");
- }
- return;
- }
-
- let connection =
- gMobileConnectionService.getItemByServiceId(this.clientId);
-
- // This check avoids data call connection if the radio is not ready
- // yet after toggling off airplane mode.
- let radioState = connection && connection.radioState;
- if (radioState != Ci.nsIMobileConnection.MOBILE_RADIO_STATE_ENABLED) {
- if (DEBUG) {
- this.debug("RIL is not ready for data connection: radio's not ready");
- }
- return;
- }
-
- // We only watch at "ril.data.enabled" flag changes for connecting or
- // disconnecting the data call. If the value of "ril.data.enabled" is
- // true and any of the remaining flags change the setting application
- // should turn this flag to false and then to true in order to reload
- // the new values and reconnect the data call.
- if (this.dataCallSettings.oldEnabled === this.dataCallSettings.enabled) {
- if (DEBUG) {
- this.debug("No changes for ril.data.enabled flag. Nothing to do.");
- }
- return;
- }
-
- let dataInfo = connection && connection.data;
- let isRegistered =
- dataInfo &&
- dataInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
- let haveDataConnection =
- dataInfo &&
- dataInfo.type != RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
- if (!isRegistered || !haveDataConnection) {
- if (DEBUG) {
- this.debug("RIL is not ready for data connection: Phone's not " +
- "registered or doesn't have data connection.");
- }
- return;
- }
- let wifi_active = false;
- if (gNetworkManager.activeNetworkInfo &&
- gNetworkManager.activeNetworkInfo.type == NETWORK_TYPE_WIFI) {
- wifi_active = true;
- }
-
- let defaultDataCallConnected = networkInterface.connected;
-
- // We have moved part of the decision making into DataCall, the rest will be
- // moved after Bug 904514 - [meta] NetworkManager enhancement.
- if (networkInterface.enabled &&
- (!this.dataCallSettings.enabled ||
- (dataInfo.roaming && !this.dataCallSettings.roamingEnabled))) {
- if (DEBUG) {
- this.debug("Data call settings: disconnect data call.");
- }
- networkInterface.disconnect();
- return;
- }
-
- if (networkInterface.enabled && wifi_active) {
- if (DEBUG) {
- this.debug("Disconnect data call when Wifi is connected.");
- }
- networkInterface.disconnect();
- return;
- }
-
- if (!this.dataCallSettings.enabled || defaultDataCallConnected) {
- if (DEBUG) {
- this.debug("Data call settings: nothing to do.");
- }
- return;
- }
- if (dataInfo.roaming && !this.dataCallSettings.roamingEnabled) {
- if (DEBUG) {
- this.debug("We're roaming, but data roaming is disabled.");
- }
- return;
- }
- if (wifi_active) {
- if (DEBUG) {
- this.debug("Don't connect data call when Wifi is connected.");
- }
- return;
- }
- if (this._pendingApnSettings) {
- if (DEBUG) this.debug("We're changing apn settings, ignore any changes.");
- return;
- }
-
- if (this._deactivatingDataCalls) {
- if (DEBUG) this.debug("We're deactivating all data calls, ignore any changes.");
- return;
- }
-
- if (DEBUG) {
- this.debug("Data call settings: connect data call.");
- }
- networkInterface.connect();
- },
-
- _isMobileNetworkType: function(aNetworkType) {
- if (aNetworkType === NETWORK_TYPE_MOBILE ||
- aNetworkType === NETWORK_TYPE_MOBILE_MMS ||
- aNetworkType === NETWORK_TYPE_MOBILE_SUPL ||
- aNetworkType === NETWORK_TYPE_MOBILE_IMS ||
- aNetworkType === NETWORK_TYPE_MOBILE_DUN ||
- aNetworkType === NETWORK_TYPE_MOBILE_FOTA) {
- return true;
- }
-
- return false;
- },
-
- getDataCallStateByType: function(aNetworkType) {
- if (!this._isMobileNetworkType(aNetworkType)) {
- if (DEBUG) this.debug(aNetworkType + " is not a mobile network type!");
- throw Cr.NS_ERROR_INVALID_ARG;
- }
-
- let networkInterface = this.dataNetworkInterfaces.get(aNetworkType);
- if (!networkInterface) {
- return NETWORK_STATE_UNKNOWN;
- }
- return networkInterface.info.state;
- },
-
- setupDataCallByType: function(aNetworkType) {
- if (DEBUG) {
- this.debug("setupDataCallByType: " + aNetworkType);
- }
-
- if (!this._isMobileNetworkType(aNetworkType)) {
- if (DEBUG) this.debug(aNetworkType + " is not a mobile network type!");
- throw Cr.NS_ERROR_INVALID_ARG;
- }
-
- let networkInterface = this.dataNetworkInterfaces.get(aNetworkType);
- if (!networkInterface) {
- if (DEBUG) {
- this.debug("No network interface for type: " + aNetworkType);
- }
- return;
- }
-
- networkInterface.connect();
- },
-
- deactivateDataCallByType: function(aNetworkType) {
- if (DEBUG) {
- this.debug("deactivateDataCallByType: " + aNetworkType);
- }
-
- if (!this._isMobileNetworkType(aNetworkType)) {
- if (DEBUG) this.debug(aNetworkType + " is not a mobile network type!");
- throw Cr.NS_ERROR_INVALID_ARG;
- }
-
- let networkInterface = this.dataNetworkInterfaces.get(aNetworkType);
- if (!networkInterface) {
- if (DEBUG) {
- this.debug("No network interface for type: " + aNetworkType);
- }
- return;
- }
-
- networkInterface.disconnect();
- },
-
- _deactivatingDataCalls: false,
-
- deactivateDataCalls: function(aCallback) {
- let dataDisconnecting = false;
- this.dataNetworkInterfaces.forEach(function(networkInterface) {
- if (networkInterface.enabled) {
- if (networkInterface.info.state != NETWORK_STATE_UNKNOWN &&
- networkInterface.info.state != NETWORK_STATE_DISCONNECTED) {
- dataDisconnecting = true;
- }
- networkInterface.disconnect();
- }
- });
-
- this._deactivatingDataCalls = dataDisconnecting;
- if (!dataDisconnecting) {
- aCallback.notifyDataCallsDisconnected();
- return;
- }
-
- let callback = {
- notifyAllDataDisconnected: () => {
- this._unregisterListener(callback);
- aCallback.notifyDataCallsDisconnected();
- }
- };
- this._registerListener(callback);
- },
-
- _listeners: null,
-
- _notifyListeners: function(aMethodName, aArgs) {
- let listeners = this._listeners.slice();
- for (let listener of listeners) {
- if (this._listeners.indexOf(listener) == -1) {
- // Listener has been unregistered in previous run.
- continue;
- }
-
- let handler = listener[aMethodName];
- try {
- handler.apply(listener, aArgs);
- } catch (e) {
- this.debug("listener for " + aMethodName + " threw an exception: " + e);
- }
- }
- },
-
- _registerListener: function(aListener) {
- if (this._listeners.indexOf(aListener) >= 0) {
- return;
- }
-
- this._listeners.push(aListener);
- },
-
- _unregisterListener: function(aListener) {
- let index = this._listeners.indexOf(aListener);
- if (index >= 0) {
- this._listeners.splice(index, 1);
- }
- },
-
- _findDataCallByCid: function(aCid) {
- if (aCid === undefined || aCid < 0) {
- return -1;
- }
-
- for (let i = 0; i < this._dataCalls.length; i++) {
- let datacall = this._dataCalls[i];
- if (datacall.linkInfo.cid != null &&
- datacall.linkInfo.cid == aCid) {
- return i;
- }
- }
-
- return -1;
- },
-
- /**
- * Notify about data call setup error, called from DataCall.
- */
- notifyDataCallError: function(aDataCall, aErrorMsg) {
- // Notify data call error only for data APN
- let networkInterface = this.dataNetworkInterfaces.get(NETWORK_TYPE_MOBILE);
- if (networkInterface && networkInterface.enabled) {
- let dataCall = networkInterface.dataCall;
- if (this._compareDataCallOptions(dataCall, aDataCall)) {
- Services.obs.notifyObservers(networkInterface.info,
- TOPIC_DATA_CALL_ERROR, aErrorMsg);
- }
- }
- },
-
- /**
- * Notify about data call changed, called from DataCall.
- */
- notifyDataCallChanged: function(aUpdatedDataCall) {
- // Process pending radio power off request after all data calls
- // are disconnected.
- if (aUpdatedDataCall.state == NETWORK_STATE_DISCONNECTED ||
- aUpdatedDataCall.state == NETWORK_STATE_UNKNOWN &&
- this.allDataDisconnected() && this._deactivatingDataCalls) {
- this._deactivatingDataCalls = false;
- this._notifyListeners("notifyAllDataDisconnected", {
- clientId: this.clientId
- });
- }
- },
-
- // nsIDataCallInterfaceListener
-
- notifyDataCallListChanged: function(aCount, aDataCallList) {
- let currentDataCalls = this._dataCalls.slice();
- for (let i = 0; i < aDataCallList.length; i++) {
- let dataCall = aDataCallList[i];
- let index = this._findDataCallByCid(dataCall.cid);
- if (index == -1) {
- if (DEBUG) {
- this.debug("Unexpected new data call: " + JSON.stringify(dataCall));
- }
- continue;
- }
- currentDataCalls[index].onDataCallChanged(dataCall);
- currentDataCalls[index] = null;
- }
-
- // If there is any CONNECTED DataCall left in currentDataCalls, means that
- // it is missing in dataCallList, we should send a DISCONNECTED event to
- // notify about this.
- for (let i = 0; i < currentDataCalls.length; i++) {
- let currentDataCall = currentDataCalls[i];
- if (currentDataCall && currentDataCall.linkInfo.cid != null &&
- currentDataCall.state == NETWORK_STATE_CONNECTED) {
- if (DEBUG) {
- this.debug("Expected data call missing: " + JSON.stringify(
- currentDataCall.apnProfile) + ", must have been DISCONNECTED.");
- }
- currentDataCall.onDataCallChanged({
- state: NETWORK_STATE_DISCONNECTED
- });
- }
- }
- },
-
- // nsIMobileConnectionListener
-
- notifyVoiceChanged: function() {},
-
- notifyDataChanged: function () {
- let connection = gMobileConnectionService.getItemByServiceId(this.clientId);
- let newDataInfo = connection.data;
-
- if (this._dataInfo.state == newDataInfo.state &&
- this._dataInfo.type == newDataInfo.type &&
- this._dataInfo.roaming == newDataInfo.roaming) {
- return;
- }
-
- this._dataInfo.state = newDataInfo.state;
- this._dataInfo.type = newDataInfo.type;
- this._dataInfo.roaming = newDataInfo.roaming;
- this.updateRILNetworkInterface();
- },
-
- notifyDataError: function (aMessage) {},
-
- notifyCFStateChanged: function(aAction, aReason, aNumber, aTimeSeconds, aServiceClass) {},
-
- notifyEmergencyCbModeChanged: function(aActive, aTimeoutMs) {},
-
- notifyOtaStatusChanged: function(aStatus) {},
-
- notifyRadioStateChanged: function() {},
-
- notifyClirModeChanged: function(aMode) {},
-
- notifyLastKnownNetworkChanged: function() {},
-
- notifyLastKnownHomeNetworkChanged: function() {},
-
- notifyNetworkSelectionModeChanged: function() {},
-
- notifyDeviceIdentitiesChanged: function() {}
-};
-
-function DataCall(aClientId, aApnSetting, aDataCallHandler) {
- this.clientId = aClientId;
- this.dataCallHandler = aDataCallHandler;
- this.apnProfile = {
- apn: aApnSetting.apn,
- user: aApnSetting.user,
- password: aApnSetting.password,
- authType: aApnSetting.authtype,
- protocol: aApnSetting.protocol,
- roaming_protocol: aApnSetting.roaming_protocol
- };
- this.linkInfo = {
- cid: null,
- ifname: null,
- addresses: [],
- dnses: [],
- gateways: [],
- pcscf: [],
- mtu: null
- };
- this.state = NETWORK_STATE_UNKNOWN;
- this.requestedNetworkIfaces = [];
-}
-DataCall.prototype = {
- /**
- * Standard values for the APN connection retry process
- * Retry funcion: time(secs) = A * numer_of_retries^2 + B
- */
- NETWORK_APNRETRY_FACTOR: 8,
- NETWORK_APNRETRY_ORIGIN: 3,
- NETWORK_APNRETRY_MAXRETRIES: 10,
-
- dataCallHandler: null,
-
- // Event timer for connection retries
- timer: null,
-
- // APN failed connections. Retry counter
- apnRetryCounter: 0,
-
- // Array to hold RILNetworkInterfaces that requested this DataCall.
- requestedNetworkIfaces: null,
-
- /**
- * @return "deactivate" if <ifname> changes or one of the aCurrentDataCall
- * addresses is missing in updatedDataCall, or "identical" if no
- * changes found, or "changed" otherwise.
- */
- _compareDataCallLink: function(aUpdatedDataCall, aCurrentDataCall) {
- // If network interface is changed, report as "deactivate".
- if (aUpdatedDataCall.ifname != aCurrentDataCall.ifname) {
- return "deactivate";
- }
-
- // If any existing address is missing, report as "deactivate".
- for (let i = 0; i < aCurrentDataCall.addresses.length; i++) {
- let address = aCurrentDataCall.addresses[i];
- if (aUpdatedDataCall.addresses.indexOf(address) < 0) {
- return "deactivate";
- }
- }
-
- if (aCurrentDataCall.addresses.length != aUpdatedDataCall.addresses.length) {
- // Since now all |aCurrentDataCall.addresses| are found in
- // |aUpdatedDataCall.addresses|, this means one or more new addresses are
- // reported.
- return "changed";
- }
-
- let fields = ["gateways", "dnses"];
- for (let i = 0; i < fields.length; i++) {
- // Compare <datacall>.<field>.
- let field = fields[i];
- let lhs = aUpdatedDataCall[field], rhs = aCurrentDataCall[field];
- if (lhs.length != rhs.length) {
- return "changed";
- }
- for (let i = 0; i < lhs.length; i++) {
- if (lhs[i] != rhs[i]) {
- return "changed";
- }
- }
- }
-
- if (aCurrentDataCall.mtu != aUpdatedDataCall.mtu) {
- return "changed";
- }
-
- return "identical";
- },
-
- _getGeckoDataCallState:function (aDataCall) {
- if (aDataCall.active == Ci.nsIDataCallInterface.DATACALL_STATE_ACTIVE_UP ||
- aDataCall.active == Ci.nsIDataCallInterface.DATACALL_STATE_ACTIVE_DOWN) {
- return NETWORK_STATE_CONNECTED;
- }
-
- return NETWORK_STATE_DISCONNECTED;
- },
-
- onSetupDataCallResult: function(aDataCall) {
- this.debug("onSetupDataCallResult: " + JSON.stringify(aDataCall));
- let errorMsg = aDataCall.errorMsg;
- if (aDataCall.failCause &&
- aDataCall.failCause != Ci.nsIDataCallInterface.DATACALL_FAIL_NONE) {
- errorMsg =
- RIL.RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[aDataCall.failCause];
- }
-
- if (errorMsg) {
- if (DEBUG) {
- this.debug("SetupDataCall error for apn " + this.apnProfile.apn + ": " +
- errorMsg + " (" + aDataCall.failCause + "), retry time: " +
- aDataCall.suggestedRetryTime);
- }
-
- this.state = NETWORK_STATE_DISCONNECTED;
-
- if (this.requestedNetworkIfaces.length === 0) {
- if (DEBUG) this.debug("This DataCall is not requested anymore.");
- return;
- }
-
- // Let DataCallHandler notify MobileConnectionService
- this.dataCallHandler.notifyDataCallError(this, errorMsg);
-
- // For suggestedRetryTime, the value of INT32_MAX(0x7fffffff) means no retry.
- if (aDataCall.suggestedRetryTime === INT32_MAX ||
- this.isPermanentFail(aDataCall.failCause, errorMsg)) {
- if (DEBUG) this.debug("Data call error: no retry needed.");
- return;
- }
-
- this.retry(aDataCall.suggestedRetryTime);
- return;
- }
-
- this.apnRetryCounter = 0;
- this.linkInfo.cid = aDataCall.cid;
-
- if (this.requestedNetworkIfaces.length === 0) {
- if (DEBUG) {
- this.debug("State is connected, but no network interface requested" +
- " this DataCall");
- }
- this.deactivate();
- return;
- }
-
- this.linkInfo.ifname = aDataCall.ifname;
- this.linkInfo.addresses = aDataCall.addresses ? aDataCall.addresses.split(" ") : [];
- this.linkInfo.gateways = aDataCall.gateways ? aDataCall.gateways.split(" ") : [];
- this.linkInfo.dnses = aDataCall.dnses ? aDataCall.dnses.split(" ") : [];
- this.linkInfo.pcscf = aDataCall.pcscf ? aDataCall.pcscf.split(" ") : [];
- this.linkInfo.mtu = aDataCall.mtu > 0 ? aDataCall.mtu : 0;
- this.state = this._getGeckoDataCallState(aDataCall);
-
- // Notify DataCallHandler about data call connected.
- this.dataCallHandler.notifyDataCallChanged(this);
-
- for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
- this.requestedNetworkIfaces[i].notifyRILNetworkInterface();
- }
- },
-
- onDeactivateDataCallResult: function() {
- if (DEBUG) this.debug("onDeactivateDataCallResult");
-
- this.reset();
-
- if (this.requestedNetworkIfaces.length > 0) {
- if (DEBUG) {
- this.debug("State is disconnected/unknown, but this DataCall is" +
- " requested.");
- }
- this.setup();
- return;
- }
-
- // Notify DataCallHandler about data call disconnected.
- this.dataCallHandler.notifyDataCallChanged(this);
- },
-
- onDataCallChanged: function(aUpdatedDataCall) {
- if (DEBUG) {
- this.debug("onDataCallChanged: " + JSON.stringify(aUpdatedDataCall));
- }
-
- if (this.state == NETWORK_STATE_CONNECTING ||
- this.state == NETWORK_STATE_DISCONNECTING) {
- if (DEBUG) {
- this.debug("We are in connecting/disconnecting state, ignore any " +
- "unsolicited event for now.");
- }
- return;
- }
-
- let dataCallState = this._getGeckoDataCallState(aUpdatedDataCall);
- if (this.state == dataCallState &&
- dataCallState != NETWORK_STATE_CONNECTED) {
- return;
- }
-
- let newLinkInfo = {
- ifname: aUpdatedDataCall.ifname,
- addresses: aUpdatedDataCall.addresses ? aUpdatedDataCall.addresses.split(" ") : [],
- dnses: aUpdatedDataCall.dnses ? aUpdatedDataCall.dnses.split(" ") : [],
- gateways: aUpdatedDataCall.gateways ? aUpdatedDataCall.gateways.split(" ") : [],
- pcscf: aUpdatedDataCall.pcscf ? aUpdatedDataCall.pcscf.split(" ") : [],
- mtu: aUpdatedDataCall.mtu > 0 ? aUpdatedDataCall.mtu : 0
- };
-
- switch (dataCallState) {
- case NETWORK_STATE_CONNECTED:
- if (this.state == NETWORK_STATE_CONNECTED) {
- let result =
- this._compareDataCallLink(newLinkInfo, this.linkInfo);
-
- if (result == "identical") {
- if (DEBUG) this.debug("No changes in data call.");
- return;
- }
- if (result == "deactivate") {
- if (DEBUG) this.debug("Data link changed, cleanup.");
- this.deactivate();
- return;
- }
- // Minor change, just update and notify.
- if (DEBUG) {
- this.debug("Data link minor change, just update and notify.");
- }
-
- this.linkInfo.addresses = newLinkInfo.addresses.slice();
- this.linkInfo.gateways = newLinkInfo.gateways.slice();
- this.linkInfo.dnses = newLinkInfo.dnses.slice();
- this.linkInfo.pcscf = newLinkInfo.pcscf.slice();
- this.linkInfo.mtu = newLinkInfo.mtu;
- }
- break;
- case NETWORK_STATE_DISCONNECTED:
- case NETWORK_STATE_UNKNOWN:
- if (this.state == NETWORK_STATE_CONNECTED) {
- // Notify first on unexpected data call disconnection.
- this.state = dataCallState;
- for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
- this.requestedNetworkIfaces[i].notifyRILNetworkInterface();
- }
- }
- this.reset();
-
- if (this.requestedNetworkIfaces.length > 0) {
- if (DEBUG) {
- this.debug("State is disconnected/unknown, but this DataCall is" +
- " requested.");
- }
- this.setup();
- return;
- }
- break;
- }
-
- this.state = dataCallState;
-
- // Notify DataCallHandler about data call changed.
- this.dataCallHandler.notifyDataCallChanged(this);
-
- for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
- this.requestedNetworkIfaces[i].notifyRILNetworkInterface();
- }
- },
-
- // Helpers
-
- debug: function(aMsg) {
- dump("-*- DataCall[" + this.clientId + ":" + this.apnProfile.apn + "]: " +
- aMsg + "\n");
- },
-
- get connected() {
- return this.state == NETWORK_STATE_CONNECTED;
- },
-
- isPermanentFail: function(aDataFailCause, aErrorMsg) {
- // Check ril.h for 'no retry' data call fail causes.
- if (aErrorMsg === RIL.GECKO_ERROR_RADIO_NOT_AVAILABLE ||
- aErrorMsg === RIL.GECKO_ERROR_INVALID_PARAMETER ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_OPERATOR_BARRED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_MISSING_UKNOWN_APN ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_USER_AUTHENTICATION ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_ACTIVATION_REJECT_GGSN ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_NSAPI_IN_USE ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_ONLY_IPV4_ALLOWED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_ONLY_IPV6_ALLOWED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_PROTOCOL_ERRORS ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_RADIO_POWER_OFF ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_TETHERED_CALL_ACTIVE) {
- return true;
- }
-
- return false;
- },
-
- inRequestedTypes: function(aType) {
- for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
- if (this.requestedNetworkIfaces[i].info.type == aType) {
- return true;
- }
- }
- return false;
- },
-
- canHandleApn: function(aApnSetting) {
- let isIdentical = this.apnProfile.apn == aApnSetting.apn &&
- (this.apnProfile.user || '') == (aApnSetting.user || '') &&
- (this.apnProfile.password || '') == (aApnSetting.password || '') &&
- (this.apnProfile.authType || '') == (aApnSetting.authtype || '');
-
- if (RILQUIRKS_HAVE_IPV6) {
- isIdentical = isIdentical &&
- (this.apnProfile.protocol || '') == (aApnSetting.protocol || '') &&
- (this.apnProfile.roaming_protocol || '') == (aApnSetting.roaming_protocol || '');
- }
-
- return isIdentical;
- },
-
- resetLinkInfo: function() {
- this.linkInfo.cid = null;
- this.linkInfo.ifname = null;
- this.linkInfo.addresses = [];
- this.linkInfo.dnses = [];
- this.linkInfo.gateways = [];
- this.linkInfo.pcscf = [];
- this.linkInfo.mtu = null;
- },
-
- reset: function() {
- this.resetLinkInfo();
-
- this.state = NETWORK_STATE_UNKNOWN;
- },
-
- connect: function(aNetworkInterface) {
- if (DEBUG) this.debug("connect: " + aNetworkInterface.info.type);
-
- if (this.requestedNetworkIfaces.indexOf(aNetworkInterface) == -1) {
- this.requestedNetworkIfaces.push(aNetworkInterface);
- }
-
- if (this.state == NETWORK_STATE_CONNECTING ||
- this.state == NETWORK_STATE_DISCONNECTING) {
- return;
- }
- if (this.state == NETWORK_STATE_CONNECTED) {
- // This needs to run asynchronously, to behave the same way as the case of
- // non-shared apn, see bug 1059110.
- Services.tm.currentThread.dispatch(() => {
- // Do not notify if state changed while this event was being dispatched,
- // the state probably was notified already or need not to be notified.
- if (aNetworkInterface.info.state == RIL.GECKO_NETWORK_STATE_CONNECTED) {
- aNetworkInterface.notifyRILNetworkInterface();
- }
- }, Ci.nsIEventTarget.DISPATCH_NORMAL);
- return;
- }
-
- // If retry mechanism is running on background, stop it since we are going
- // to setup data call now.
- if (this.timer) {
- this.timer.cancel();
- }
-
- this.setup();
- },
-
- setup: function() {
- if (DEBUG) {
- this.debug("Going to set up data connection with APN " +
- this.apnProfile.apn);
- }
-
- let connection =
- gMobileConnectionService.getItemByServiceId(this.clientId);
- let dataInfo = connection && connection.data;
- if (dataInfo == null ||
- dataInfo.state != RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED ||
- dataInfo.type == RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN) {
- return;
- }
-
- let radioTechType = dataInfo.type;
- let radioTechnology = RIL.GECKO_RADIO_TECH.indexOf(radioTechType);
- let authType = RIL.RIL_DATACALL_AUTH_TO_GECKO.indexOf(this.apnProfile.authType);
- // Use the default authType if the value in database is invalid.
- // For the case that user might not select the authentication type.
- if (authType == -1) {
- if (DEBUG) {
- this.debug("Invalid authType '" + this.apnProfile.authtype +
- "', using '" + RIL.GECKO_DATACALL_AUTH_DEFAULT + "'");
- }
- authType = RIL.RIL_DATACALL_AUTH_TO_GECKO.indexOf(RIL.GECKO_DATACALL_AUTH_DEFAULT);
- }
-
- let pdpType = Ci.nsIDataCallInterface.DATACALL_PDP_TYPE_IPV4;
- if (RILQUIRKS_HAVE_IPV6) {
- pdpType = !dataInfo.roaming
- ? RIL.RIL_DATACALL_PDP_TYPES.indexOf(this.apnProfile.protocol)
- : RIL.RIL_DATACALL_PDP_TYPES.indexOf(this.apnProfile.roaming_protocol);
- if (pdpType == -1) {
- if (DEBUG) {
- this.debug("Invalid pdpType '" + (!dataInfo.roaming
- ? this.apnProfile.protocol
- : this.apnProfile.roaming_protocol) +
- "', using '" + RIL.GECKO_DATACALL_PDP_TYPE_DEFAULT + "'");
- }
- pdpType = RIL.RIL_DATACALL_PDP_TYPES.indexOf(RIL.GECKO_DATACALL_PDP_TYPE_DEFAULT);
- }
- }
-
- let dcInterface = this.dataCallHandler.dataCallInterface;
- dcInterface.setupDataCall(
- this.apnProfile.apn, this.apnProfile.user, this.apnProfile.password,
- authType, pdpType, {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallCallback]),
- notifySetupDataCallSuccess: (aDataCall) => {
- this.onSetupDataCallResult(aDataCall);
- },
- notifyError: (aErrorMsg) => {
- this.onSetupDataCallResult({errorMsg: aErrorMsg});
- }
- });
- this.state = NETWORK_STATE_CONNECTING;
- },
-
- retry: function(aSuggestedRetryTime) {
- let apnRetryTimer;
-
- // We will retry the connection in increasing times
- // based on the function: time = A * numer_of_retries^2 + B
- if (this.apnRetryCounter >= this.NETWORK_APNRETRY_MAXRETRIES) {
- this.apnRetryCounter = 0;
- this.timer = null;
- if (DEBUG) this.debug("Too many APN Connection retries - STOP retrying");
- return;
- }
-
- // If there is a valid aSuggestedRetryTime, override the retry timer.
- if (aSuggestedRetryTime !== undefined && aSuggestedRetryTime >= 0) {
- apnRetryTimer = aSuggestedRetryTime / 1000;
- } else {
- apnRetryTimer = this.NETWORK_APNRETRY_FACTOR *
- (this.apnRetryCounter * this.apnRetryCounter) +
- this.NETWORK_APNRETRY_ORIGIN;
- }
- this.apnRetryCounter++;
- if (DEBUG) {
- this.debug("Data call - APN Connection Retry Timer (secs-counter): " +
- apnRetryTimer + "-" + this.apnRetryCounter);
- }
-
- if (this.timer == null) {
- // Event timer for connection retries
- this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- }
- this.timer.initWithCallback(this, apnRetryTimer * 1000,
- Ci.nsITimer.TYPE_ONE_SHOT);
- },
-
- disconnect: function(aNetworkInterface) {
- if (DEBUG) this.debug("disconnect: " + aNetworkInterface.info.type);
-
- let index = this.requestedNetworkIfaces.indexOf(aNetworkInterface);
- if (index != -1) {
- this.requestedNetworkIfaces.splice(index, 1);
-
- if (this.state == NETWORK_STATE_DISCONNECTED ||
- this.state == NETWORK_STATE_UNKNOWN) {
- if (this.timer) {
- this.timer.cancel();
- }
- this.reset();
- return;
- }
-
- // Notify the DISCONNECTED event immediately after network interface is
- // removed from requestedNetworkIfaces, to make the DataCall, shared or
- // not, to have the same behavior.
- Services.tm.currentThread.dispatch(() => {
- // Do not notify if state changed while this event was being dispatched,
- // the state probably was notified already or need not to be notified.
- if (aNetworkInterface.info.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) {
- aNetworkInterface.notifyRILNetworkInterface();
-
- // Clear link info after notifying NetworkManager.
- if (this.requestedNetworkIfaces.length === 0) {
- this.resetLinkInfo();
- }
- }
- }, Ci.nsIEventTarget.DISPATCH_NORMAL);
- }
-
- // Only deactivate data call if no more network interface needs this
- // DataCall and if state is CONNECTED, for other states, we simply remove
- // the network interface from requestedNetworkIfaces.
- if (this.requestedNetworkIfaces.length > 0 ||
- this.state != NETWORK_STATE_CONNECTED) {
- return;
- }
-
- this.deactivate();
- },
-
- deactivate: function() {
- let reason = Ci.nsIDataCallInterface.DATACALL_DEACTIVATE_NO_REASON;
- if (DEBUG) {
- this.debug("Going to disconnect data connection cid " + this.linkInfo.cid);
- }
-
- let dcInterface = this.dataCallHandler.dataCallInterface;
- dcInterface.deactivateDataCall(this.linkInfo.cid, reason, {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallCallback]),
- notifySuccess: () => {
- this.onDeactivateDataCallResult();
- },
- notifyError: (aErrorMsg) => {
- this.onDeactivateDataCallResult();
- }
- });
-
- this.state = NETWORK_STATE_DISCONNECTING;
- },
-
- // Entry method for timer events. Used to reconnect to a failed APN
- notify: function(aTimer) {
- this.setup();
- },
-
- shutdown: function() {
- if (this.timer) {
- this.timer.cancel();
- this.timer = null;
- }
- }
-};
-
-function RILNetworkInfo(aClientId, aType, aNetworkInterface)
-{
- this.serviceId = aClientId;
- this.type = aType;
-
- this.networkInterface = aNetworkInterface;
-}
-RILNetworkInfo.prototype = {
- classID: RILNETWORKINFO_CID,
- classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINFO_CID,
- classDescription: "RILNetworkInfo",
- interfaces: [Ci.nsINetworkInfo,
- Ci.nsIRilNetworkInfo]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo,
- Ci.nsIRilNetworkInfo]),
-
- networkInterface: null,
-
- getDataCall: function() {
- return this.networkInterface.dataCall;
- },
-
- getApnSetting: function() {
- return this.networkInterface.apnSetting;
- },
-
- debug: function(aMsg) {
- dump("-*- RILNetworkInfo[" + this.serviceId + ":" + this.type + "]: " +
- aMsg + "\n");
- },
-
- /**
- * nsINetworkInfo Implementation
- */
- get state() {
- let dataCall = this.getDataCall();
- if (!dataCall.inRequestedTypes(this.type)) {
- return NETWORK_STATE_DISCONNECTED;
- }
- return dataCall.state;
- },
-
- type: null,
-
- get name() {
- return this.getDataCall().linkInfo.ifname;
- },
-
- getAddresses: function(aIps, aPrefixLengths) {
- let addresses = this.getDataCall().linkInfo.addresses;
-
- let ips = [];
- let prefixLengths = [];
- for (let i = 0; i < addresses.length; i++) {
- let [ip, prefixLength] = addresses[i].split("/");
- ips.push(ip);
- prefixLengths.push(prefixLength);
- }
-
- aIps.value = ips.slice();
- aPrefixLengths.value = prefixLengths.slice();
-
- return ips.length;
- },
-
- getGateways: function(aCount) {
- let linkInfo = this.getDataCall().linkInfo;
-
- if (aCount) {
- aCount.value = linkInfo.gateways.length;
- }
-
- return linkInfo.gateways.slice();
- },
-
- getDnses: function(aCount) {
- let linkInfo = this.getDataCall().linkInfo;
-
- if (aCount) {
- aCount.value = linkInfo.dnses.length;
- }
-
- return linkInfo.dnses.slice();
- },
-
- /**
- * nsIRilNetworkInfo Implementation
- */
-
- serviceId: 0,
-
- get iccId() {
- let icc = gIccService.getIccByServiceId(this.serviceId);
- let iccInfo = icc && icc.iccInfo;
-
- return iccInfo && iccInfo.iccid;
- },
-
- get mmsc() {
- if (this.type != NETWORK_TYPE_MOBILE_MMS) {
- if (DEBUG) this.debug("Error! Only MMS network can get MMSC.");
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- return this.getApnSetting().mmsc || "";
- },
-
- get mmsProxy() {
- if (this.type != NETWORK_TYPE_MOBILE_MMS) {
- if (DEBUG) this.debug("Error! Only MMS network can get MMS proxy.");
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- return this.getApnSetting().mmsproxy || "";
- },
-
- get mmsPort() {
- if (this.type != NETWORK_TYPE_MOBILE_MMS) {
- if (DEBUG) this.debug("Error! Only MMS network can get MMS port.");
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- // Note: Port 0 is reserved, so we treat it as invalid as well.
- // See http://www.iana.org/assignments/port-numbers
- return this.getApnSetting().mmsport || -1;
- },
-
- getPcscf: function(aCount) {
- if (this.type != NETWORK_TYPE_MOBILE_IMS) {
- if (DEBUG) this.debug("Error! Only IMS network can get pcscf.");
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- let linkInfo = this.getDataCall().linkInfo;
-
- if (aCount) {
- aCount.value = linkInfo.pcscf.length;
- }
- return linkInfo.pcscf.slice();
- },
-};
-
-function RILNetworkInterface(aDataCallHandler, aType, aApnSetting, aDataCall) {
- if (!aDataCall) {
- throw new Error("No dataCall for RILNetworkInterface: " + type);
- }
-
- this.dataCallHandler = aDataCallHandler;
- this.enabled = false;
- this.dataCall = aDataCall;
- this.apnSetting = aApnSetting;
-
- this.info = new RILNetworkInfo(aDataCallHandler.clientId, aType, this);
-}
-
-RILNetworkInterface.prototype = {
- classID: RILNETWORKINTERFACE_CID,
- classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID,
- classDescription: "RILNetworkInterface",
- interfaces: [Ci.nsINetworkInterface]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
-
- // If this RILNetworkInterface type is enabled or not.
- enabled: null,
-
- apnSetting: null,
-
- dataCall: null,
-
- /**
- * nsINetworkInterface Implementation
- */
-
- info: null,
-
- get httpProxyHost() {
- return this.apnSetting.proxy || "";
- },
-
- get httpProxyPort() {
- return this.apnSetting.port || "";
- },
-
- get mtu() {
- // Value provided by network has higher priority than apn settings.
- return this.dataCall.linkInfo.mtu || this.apnSetting.mtu || -1;
- },
-
- // Helpers
-
- debug: function(aMsg) {
- dump("-*- RILNetworkInterface[" + this.dataCallHandler.clientId + ":" +
- this.info.type + "]: " + aMsg + "\n");
- },
-
- get connected() {
- return this.info.state == NETWORK_STATE_CONNECTED;
- },
-
- notifyRILNetworkInterface: function() {
- if (DEBUG) {
- this.debug("notifyRILNetworkInterface type: " + this.info.type +
- ", state: " + this.info.state);
- }
-
- gNetworkManager.updateNetworkInterface(this);
- },
-
- connect: function() {
- this.enabled = true;
-
- this.dataCall.connect(this);
- },
-
- disconnect: function() {
- if (!this.enabled) {
- return;
- }
- this.enabled = false;
-
- this.dataCall.disconnect(this);
- },
-
- shutdown: function() {
- this.dataCall.shutdown();
- this.dataCall = null;
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataCallManager]); \ No newline at end of file
diff --git a/dom/system/gonk/DataCallManager.manifest b/dom/system/gonk/DataCallManager.manifest
deleted file mode 100644
index 2a982415e..000000000
--- a/dom/system/gonk/DataCallManager.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-# DataCallManager.js
-component {35b9efa2-e42c-45ce-8210-0a13e6f4aadc} DataCallManager.js
-contract @mozilla.org/datacall/manager;1 {35b9efa2-e42c-45ce-8210-0a13e6f4aadc}
-category profile-after-change DataCallManager @mozilla.org/datacall/manager;1 \ No newline at end of file
diff --git a/dom/system/gonk/GeolocationUtil.cpp b/dom/system/gonk/GeolocationUtil.cpp
deleted file mode 100644
index 99d484a19..000000000
--- a/dom/system/gonk/GeolocationUtil.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GeolocationUtil.h"
-
-double CalculateDeltaInMeter(double aLat, double aLon, double aLastLat, double aLastLon)
-{
- // Use spherical law of cosines to calculate difference
- // Not quite as correct as the Haversine but simpler and cheaper
- const double radsInDeg = M_PI / 180.0;
- const double rNewLat = aLat * radsInDeg;
- const double rNewLon = aLon * radsInDeg;
- const double rOldLat = aLastLat * radsInDeg;
- const double rOldLon = aLastLon * radsInDeg;
- // WGS84 equatorial radius of earth = 6378137m
- double cosDelta = (sin(rNewLat) * sin(rOldLat)) +
- (cos(rNewLat) * cos(rOldLat) * cos(rOldLon - rNewLon));
- if (cosDelta > 1.0) {
- cosDelta = 1.0;
- } else if (cosDelta < -1.0) {
- cosDelta = -1.0;
- }
- return acos(cosDelta) * 6378137;
-}
-
diff --git a/dom/system/gonk/GeolocationUtil.h b/dom/system/gonk/GeolocationUtil.h
deleted file mode 100644
index fde337fb8..000000000
--- a/dom/system/gonk/GeolocationUtil.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef GEOLOCATIONUTIL_H
-#define GEOLOCATIONUTIL_H
-
-double CalculateDeltaInMeter(double aLat, double aLon, double aLastLat, double aLastLon);
-
-#endif
-
diff --git a/dom/system/gonk/GonkGPSGeolocationProvider.cpp b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
deleted file mode 100644
index 9ce6ce2e5..000000000
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ /dev/null
@@ -1,706 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GonkGPSGeolocationProvider.h"
-
-#include <cmath>
-#include <pthread.h>
-#include <hardware/gps.h>
-
-#include "base/task.h"
-#include "GeolocationUtil.h"
-#include "mozstumbler/MozStumbler.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Services.h"
-#include "nsContentUtils.h"
-#include "nsGeoPosition.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsINetworkInterface.h"
-#include "nsIObserverService.h"
-#include "nsJSUtils.h"
-#include "nsPrintfCString.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "prtime.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/SettingChangeNotificationBinding.h"
-
-#ifdef AGPS_TYPE_INVALID
-#define AGPS_HAVE_DUAL_APN
-#endif
-
-#define FLUSH_AIDE_DATA 0
-
-#undef LOG
-#undef ERR
-#undef DBG
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GonkGPSGeolocationProvider", ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "GonkGPSGeolocationProvider", ## args)
-#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "GonkGPSGeolocationProvider" , ## args)
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-static const int kDefaultPeriod = 1000; // ms
-static bool gDebug_isLoggingEnabled = false;
-static bool gDebug_isGPSLocationIgnored = false;
-static const char* kMozSettingsChangedTopic = "mozsettings-changed";
-// Both of these settings can be toggled in the Gaia Developer settings screen.
-static const char* kSettingDebugEnabled = "geolocation.debugging.enabled";
-static const char* kSettingDebugGpsIgnored = "geolocation.debugging.gps-locations-ignored";
-
-// While most methods of GonkGPSGeolocationProvider should only be
-// called from main thread, we deliberately put the Init and ShutdownGPS
-// methods off main thread to avoid blocking.
-NS_IMPL_ISUPPORTS(GonkGPSGeolocationProvider,
- nsIGeolocationProvider,
- nsIObserver,
- nsISettingsServiceCallback)
-
-/* static */ GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton = nullptr;
-GpsCallbacks GonkGPSGeolocationProvider::mCallbacks;
-
-
-void
-GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
-{
- if (gDebug_isGPSLocationIgnored) {
- return;
- }
-
- class UpdateLocationEvent : public Runnable {
- public:
- UpdateLocationEvent(nsGeoPosition* aPosition)
- : mPosition(aPosition)
- {}
- NS_IMETHOD Run() override {
- RefPtr<GonkGPSGeolocationProvider> provider =
- GonkGPSGeolocationProvider::GetSingleton();
- nsCOMPtr<nsIGeolocationUpdate> callback = provider->mLocationCallback;
- provider->mLastGPSPosition = mPosition;
- if (callback) {
- callback->Update(mPosition);
- }
- return NS_OK;
- }
- private:
- RefPtr<nsGeoPosition> mPosition;
- };
-
- MOZ_ASSERT(location);
-
- const float kImpossibleAccuracy_m = 0.001;
- if (location->accuracy < kImpossibleAccuracy_m) {
- return;
- }
-
- RefPtr<nsGeoPosition> somewhere = new nsGeoPosition(location->latitude,
- location->longitude,
- location->altitude,
- location->accuracy,
- location->accuracy,
- location->bearing,
- location->speed,
- PR_Now() / PR_USEC_PER_MSEC);
- // Note above: Can't use location->timestamp as the time from the satellite is a
- // minimum of 16 secs old (see http://leapsecond.com/java/gpsclock.htm).
- // All code from this point on expects the gps location to be timestamped with the
- // current time, most notably: the geolocation service which respects maximumAge
- // set in the DOM JS.
-
- if (gDebug_isLoggingEnabled) {
- DBG("geo: GPS got a fix (%f, %f). accuracy: %f",
- location->latitude,
- location->longitude,
- location->accuracy);
- }
-
- RefPtr<UpdateLocationEvent> event = new UpdateLocationEvent(somewhere);
- NS_DispatchToMainThread(event);
-
-}
-
-class NotifyObserversGPSTask final : public Runnable
-{
-public:
- explicit NotifyObserversGPSTask(const char16_t* aData)
- : mData(aData)
- {}
- NS_IMETHOD Run() override {
- RefPtr<nsIGeolocationProvider> provider =
- GonkGPSGeolocationProvider::GetSingleton();
- nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
- obsService->NotifyObservers(provider, "geolocation-device-events", mData);
- return NS_OK;
- }
-private:
- const char16_t* mData;
-};
-
-void
-GonkGPSGeolocationProvider::StatusCallback(GpsStatus* status)
-{
- const char* msgStream=0;
- switch (status->status) {
- case GPS_STATUS_NONE:
- msgStream = "geo: GPS_STATUS_NONE\n";
- break;
- case GPS_STATUS_SESSION_BEGIN:
- msgStream = "geo: GPS_STATUS_SESSION_BEGIN\n";
- break;
- case GPS_STATUS_SESSION_END:
- msgStream = "geo: GPS_STATUS_SESSION_END\n";
- break;
- case GPS_STATUS_ENGINE_ON:
- msgStream = "geo: GPS_STATUS_ENGINE_ON\n";
- NS_DispatchToMainThread(new NotifyObserversGPSTask(u"GPSStarting"));
- break;
- case GPS_STATUS_ENGINE_OFF:
- msgStream = "geo: GPS_STATUS_ENGINE_OFF\n";
- NS_DispatchToMainThread(new NotifyObserversGPSTask(u"GPSShutdown"));
- break;
- default:
- msgStream = "geo: Unknown GPS status\n";
- break;
- }
- if (gDebug_isLoggingEnabled){
- DBG("%s", msgStream);
- }
-}
-
-void
-GonkGPSGeolocationProvider::SvStatusCallback(GpsSvStatus* sv_info)
-{
- if (gDebug_isLoggingEnabled) {
- static int numSvs = 0;
- static uint32_t numEphemeris = 0;
- static uint32_t numAlmanac = 0;
- static uint32_t numUsedInFix = 0;
-
- unsigned int i = 1;
- uint32_t svAlmanacCount = 0;
- for (i = 1; i > 0; i <<= 1) {
- if (i & sv_info->almanac_mask) {
- svAlmanacCount++;
- }
- }
-
- uint32_t svEphemerisCount = 0;
- for (i = 1; i > 0; i <<= 1) {
- if (i & sv_info->ephemeris_mask) {
- svEphemerisCount++;
- }
- }
-
- uint32_t svUsedCount = 0;
- for (i = 1; i > 0; i <<= 1) {
- if (i & sv_info->used_in_fix_mask) {
- svUsedCount++;
- }
- }
-
- // Log the message only if the the status changed.
- if (sv_info->num_svs != numSvs ||
- svAlmanacCount != numAlmanac ||
- svEphemerisCount != numEphemeris ||
- svUsedCount != numUsedInFix) {
-
- LOG(
- "geo: Number of SVs have (visibility, almanac, ephemeris): (%d, %d, %d)."
- " %d of these SVs were used in fix.\n",
- sv_info->num_svs, svAlmanacCount, svEphemerisCount, svUsedCount);
-
- numSvs = sv_info->num_svs;
- numAlmanac = svAlmanacCount;
- numEphemeris = svEphemerisCount;
- numUsedInFix = svUsedCount;
- }
- }
-}
-
-void
-GonkGPSGeolocationProvider::NmeaCallback(GpsUtcTime timestamp, const char* nmea, int length)
-{
- if (gDebug_isLoggingEnabled) {
- DBG("NMEA: timestamp:\t%lld, length: %d, %s", timestamp, length, nmea);
- }
-}
-
-void
-GonkGPSGeolocationProvider::SetCapabilitiesCallback(uint32_t capabilities)
-{
- class UpdateCapabilitiesEvent : public Runnable {
- public:
- UpdateCapabilitiesEvent(uint32_t aCapabilities)
- : mCapabilities(aCapabilities)
- {}
- NS_IMETHOD Run() override {
- RefPtr<GonkGPSGeolocationProvider> provider =
- GonkGPSGeolocationProvider::GetSingleton();
-
- provider->mSupportsScheduling = mCapabilities & GPS_CAPABILITY_SCHEDULING;
- provider->mSupportsSingleShot = mCapabilities & GPS_CAPABILITY_SINGLE_SHOT;
-#ifdef GPS_CAPABILITY_ON_DEMAND_TIME
- provider->mSupportsTimeInjection = mCapabilities & GPS_CAPABILITY_ON_DEMAND_TIME;
-#endif
- return NS_OK;
- }
- private:
- uint32_t mCapabilities;
- };
-
- NS_DispatchToMainThread(new UpdateCapabilitiesEvent(capabilities));
-}
-
-void
-GonkGPSGeolocationProvider::AcquireWakelockCallback()
-{
-}
-
-void
-GonkGPSGeolocationProvider::ReleaseWakelockCallback()
-{
-}
-
-typedef void *(*pthread_func)(void *);
-
-/** Callback for creating a thread that can call into the JS codes.
- */
-pthread_t
-GonkGPSGeolocationProvider::CreateThreadCallback(const char* name, void (*start)(void *), void* arg)
-{
- pthread_t thread;
- pthread_attr_t attr;
-
- pthread_attr_init(&attr);
-
- /* Unfortunately pthread_create and the callback disagreed on what
- * start function should return.
- */
- pthread_create(&thread, &attr, reinterpret_cast<pthread_func>(start), arg);
-
- return thread;
-}
-
-void
-GonkGPSGeolocationProvider::RequestUtcTimeCallback()
-{
-}
-
-GonkGPSGeolocationProvider::GonkGPSGeolocationProvider()
- : mStarted(false)
- , mSupportsScheduling(false)
- , mObservingSettingsChange(false)
- , mSupportsSingleShot(false)
- , mSupportsTimeInjection(false)
- , mGpsInterface(nullptr)
-{
-}
-
-GonkGPSGeolocationProvider::~GonkGPSGeolocationProvider()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!mStarted, "Must call Shutdown before destruction");
-
- sSingleton = nullptr;
-}
-
-already_AddRefed<GonkGPSGeolocationProvider>
-GonkGPSGeolocationProvider::GetSingleton()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!sSingleton)
- sSingleton = new GonkGPSGeolocationProvider();
-
- RefPtr<GonkGPSGeolocationProvider> provider = sSingleton;
- return provider.forget();
-}
-
-const GpsInterface*
-GonkGPSGeolocationProvider::GetGPSInterface()
-{
- hw_module_t* module;
-
- if (hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module))
- return nullptr;
-
- hw_device_t* device;
- if (module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device))
- return nullptr;
-
- gps_device_t* gps_device = (gps_device_t *)device;
- const GpsInterface* result = gps_device->get_gps_interface(gps_device);
-
- if (result->size != sizeof(GpsInterface)) {
- return nullptr;
- }
- return result;
-}
-
-void
-GonkGPSGeolocationProvider::RequestSettingValue(const char* aKey)
-{
- MOZ_ASSERT(aKey);
- nsCOMPtr<nsISettingsService> ss = do_GetService("@mozilla.org/settingsService;1");
- if (!ss) {
- MOZ_ASSERT(ss);
- return;
- }
-
- nsCOMPtr<nsISettingsServiceLock> lock;
- nsresult rv = ss->CreateLock(nullptr, getter_AddRefs(lock));
- if (NS_FAILED(rv)) {
- ERR("error while createLock setting '%s': %d\n", aKey, uint32_t(rv));
- return;
- }
-
- rv = lock->Get(aKey, this);
- if (NS_FAILED(rv)) {
- ERR("error while get setting '%s': %d\n", aKey, uint32_t(rv));
- return;
- }
-}
-
-void
-GonkGPSGeolocationProvider::InjectLocation(double latitude,
- double longitude,
- float accuracy)
-{
- if (gDebug_isLoggingEnabled) {
- DBG("injecting location (%f, %f) accuracy: %f", latitude, longitude, accuracy);
- }
-
- MOZ_ASSERT(NS_IsMainThread());
- if (!mGpsInterface) {
- return;
- }
-
- mGpsInterface->inject_location(latitude, longitude, accuracy);
-}
-
-void
-GonkGPSGeolocationProvider::Init()
-{
- // Must not be main thread. Some GPS driver's first init takes very long.
- MOZ_ASSERT(!NS_IsMainThread());
-
- mGpsInterface = GetGPSInterface();
- if (!mGpsInterface) {
- return;
- }
-
- if (!mCallbacks.size) {
- mCallbacks.size = sizeof(GpsCallbacks);
- mCallbacks.location_cb = LocationCallback;
- mCallbacks.status_cb = StatusCallback;
- mCallbacks.sv_status_cb = SvStatusCallback;
- mCallbacks.nmea_cb = NmeaCallback;
- mCallbacks.set_capabilities_cb = SetCapabilitiesCallback;
- mCallbacks.acquire_wakelock_cb = AcquireWakelockCallback;
- mCallbacks.release_wakelock_cb = ReleaseWakelockCallback;
- mCallbacks.create_thread_cb = CreateThreadCallback;
-
-#ifdef GPS_CAPABILITY_ON_DEMAND_TIME
- mCallbacks.request_utc_time_cb = RequestUtcTimeCallback;
-#endif
-
- }
-
- if (mGpsInterface->init(&mCallbacks) != 0) {
- return;
- }
-
- NS_DispatchToMainThread(NewRunnableMethod(this, &GonkGPSGeolocationProvider::StartGPS));
-}
-
-void
-GonkGPSGeolocationProvider::StartGPS()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(mGpsInterface);
-
- int32_t update = Preferences::GetInt("geo.default.update", kDefaultPeriod);
-
- int positionMode = GPS_POSITION_MODE_STANDALONE;
-
- if (!mSupportsScheduling) {
- update = kDefaultPeriod;
- }
-
- mGpsInterface->set_position_mode(positionMode,
- GPS_POSITION_RECURRENCE_PERIODIC,
- update, 0, 0);
-#if FLUSH_AIDE_DATA
- // Delete cached data
- mGpsInterface->delete_aiding_data(GPS_DELETE_ALL);
-#endif
-
- mGpsInterface->start();
-}
-
-
-NS_IMPL_ISUPPORTS(GonkGPSGeolocationProvider::NetworkLocationUpdate,
- nsIGeolocationUpdate)
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::NetworkLocationUpdate::Update(nsIDOMGeoPosition *position)
-{
- RefPtr<GonkGPSGeolocationProvider> provider =
- GonkGPSGeolocationProvider::GetSingleton();
-
- nsCOMPtr<nsIDOMGeoPositionCoords> coords;
- position->GetCoords(getter_AddRefs(coords));
- if (!coords) {
- return NS_ERROR_FAILURE;
- }
-
- double lat, lon, acc;
- coords->GetLatitude(&lat);
- coords->GetLongitude(&lon);
- coords->GetAccuracy(&acc);
-
- double delta = -1.0;
-
- static double sLastMLSPosLat = 0;
- static double sLastMLSPosLon = 0;
-
- if (0 != sLastMLSPosLon || 0 != sLastMLSPosLat) {
- delta = CalculateDeltaInMeter(lat, lon, sLastMLSPosLat, sLastMLSPosLon);
- }
-
- sLastMLSPosLat = lat;
- sLastMLSPosLon = lon;
-
- // if the MLS coord change is smaller than this arbitrarily small value
- // assume the MLS coord is unchanged, and stick with the GPS location
- const double kMinMLSCoordChangeInMeters = 10;
-
- DOMTimeStamp time_ms = 0;
- if (provider->mLastGPSPosition) {
- provider->mLastGPSPosition->GetTimestamp(&time_ms);
- }
- const int64_t diff_ms = (PR_Now() / PR_USEC_PER_MSEC) - time_ms;
-
- // We want to distinguish between the GPS being inactive completely
- // and temporarily inactive. In the former case, we would use a low
- // accuracy network location; in the latter, we only want a network
- // location that appears to updating with movement.
-
- const bool isGPSFullyInactive = diff_ms > 1000 * 60 * 2; // two mins
- const bool isGPSTempInactive = diff_ms > 1000 * 10; // 10 secs
-
- if (provider->mLocationCallback) {
- if (isGPSFullyInactive ||
- (isGPSTempInactive && delta > kMinMLSCoordChangeInMeters))
- {
- if (gDebug_isLoggingEnabled) {
- DBG("Using MLS, GPS age:%fs, MLS Delta:%fm\n", diff_ms / 1000.0, delta);
- }
- provider->mLocationCallback->Update(position);
- } else if (provider->mLastGPSPosition) {
- if (gDebug_isLoggingEnabled) {
- DBG("Using old GPS age:%fs\n", diff_ms / 1000.0);
- }
-
- // This is a fallback case so that the GPS provider responds with its last
- // location rather than waiting for a more recent GPS or network location.
- // The service decides if the location is too old, not the provider.
- provider->mLocationCallback->Update(provider->mLastGPSPosition);
- }
- }
- provider->InjectLocation(lat, lon, acc);
- return NS_OK;
-}
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::NetworkLocationUpdate::NotifyError(uint16_t error)
-{
- return NS_OK;
-}
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Startup()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (mStarted) {
- return NS_OK;
- }
-
- RequestSettingValue(kSettingDebugEnabled);
- RequestSettingValue(kSettingDebugGpsIgnored);
-
- // Setup an observer to watch changes to the setting.
- nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
- if (observerService) {
- MOZ_ASSERT(!mObservingSettingsChange);
- nsresult rv = observerService->AddObserver(this, kMozSettingsChangedTopic, false);
- if (NS_FAILED(rv)) {
- NS_WARNING("geo: Gonk GPS AddObserver failed");
- } else {
- mObservingSettingsChange = true;
- }
- }
-
- if (!mInitThread) {
- nsresult rv = NS_NewThread(getter_AddRefs(mInitThread));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- mInitThread->Dispatch(NewRunnableMethod(this, &GonkGPSGeolocationProvider::Init),
- NS_DISPATCH_NORMAL);
-
- mNetworkLocationProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1");
- if (mNetworkLocationProvider) {
- nsresult rv = mNetworkLocationProvider->Startup();
- if (NS_SUCCEEDED(rv)) {
- RefPtr<NetworkLocationUpdate> update = new NetworkLocationUpdate();
- mNetworkLocationProvider->Watch(update);
- }
- }
-
- mStarted = true;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Watch(nsIGeolocationUpdate* aCallback)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mLocationCallback = aCallback;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Shutdown()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!mStarted) {
- return NS_OK;
- }
-
- mStarted = false;
- if (mNetworkLocationProvider) {
- mNetworkLocationProvider->Shutdown();
- mNetworkLocationProvider = nullptr;
- }
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (obs) {
- nsresult rv;
- rv = obs->RemoveObserver(this, kMozSettingsChangedTopic);
- if (NS_FAILED(rv)) {
- NS_WARNING("geo: Gonk GPS mozsettings RemoveObserver failed");
- } else {
- mObservingSettingsChange = false;
- }
- }
-
- mInitThread->Dispatch(NewRunnableMethod(this, &GonkGPSGeolocationProvider::ShutdownGPS),
- NS_DISPATCH_NORMAL);
-
- return NS_OK;
-}
-
-void
-GonkGPSGeolocationProvider::ShutdownGPS()
-{
- MOZ_ASSERT(!mStarted, "Should only be called after Shutdown");
-
- if (mGpsInterface) {
- mGpsInterface->stop();
- mGpsInterface->cleanup();
- }
-}
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::SetHighAccuracy(bool)
-{
- return NS_OK;
-}
-
-namespace {
-int
-ConvertToGpsNetworkType(int aNetworkInterfaceType)
-{
- switch (aNetworkInterfaceType) {
- case nsINetworkInfo::NETWORK_TYPE_WIFI:
- return AGPS_RIL_NETWORK_TYPE_WIFI;
- case nsINetworkInfo::NETWORK_TYPE_MOBILE:
- return AGPS_RIL_NETWORK_TYPE_MOBILE;
- case nsINetworkInfo::NETWORK_TYPE_MOBILE_MMS:
- return AGPS_RIL_NETWORK_TYPE_MOBILE_MMS;
- case nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL:
- return AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL;
- case nsINetworkInfo::NETWORK_TYPE_MOBILE_DUN:
- return AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN;
- default:
- NS_WARNING(nsPrintfCString("Unknown network type mapping %d",
- aNetworkInterfaceType).get());
- return -1;
- }
-}
-} // namespace
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!strcmp(aTopic, kMozSettingsChangedTopic)) {
- // Read changed setting value
- RootedDictionary<SettingChangeNotification> setting(RootingCx());
- if (!WrappedJSToDictionary(aSubject, setting)) {
- return NS_OK;
- }
-
- if (setting.mKey.EqualsASCII(kSettingDebugGpsIgnored)) {
- LOG("received mozsettings-changed: ignoring\n");
- gDebug_isGPSLocationIgnored =
- setting.mValue.isBoolean() ? setting.mValue.toBoolean() : false;
- if (gDebug_isLoggingEnabled) {
- DBG("GPS ignored %d\n", gDebug_isGPSLocationIgnored);
- }
- return NS_OK;
- } else if (setting.mKey.EqualsASCII(kSettingDebugEnabled)) {
- LOG("received mozsettings-changed: logging\n");
- gDebug_isLoggingEnabled =
- setting.mValue.isBoolean() ? setting.mValue.toBoolean() : false;
- return NS_OK;
- }
- }
-
- return NS_OK;
-}
-
-/** nsISettingsServiceCallback **/
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Handle(const nsAString& aName,
- JS::Handle<JS::Value> aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::HandleError(const nsAString& aErrorMessage)
-{
- return NS_OK;
-}
diff --git a/dom/system/gonk/GonkGPSGeolocationProvider.h b/dom/system/gonk/GonkGPSGeolocationProvider.h
deleted file mode 100644
index 514398edf..000000000
--- a/dom/system/gonk/GonkGPSGeolocationProvider.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GonkGPSGeolocationProvider_h
-#define GonkGPSGeolocationProvider_h
-
-#include <hardware/gps.h> // for GpsInterface
-#include "nsCOMPtr.h"
-#include "nsIGeolocationProvider.h"
-#include "nsIObserver.h"
-#include "nsIDOMGeoPosition.h"
-#include "nsISettingsService.h"
-
-class nsIThread;
-
-#define GONK_GPS_GEOLOCATION_PROVIDER_CID \
-{ 0x48525ec5, 0x5a7f, 0x490a, { 0x92, 0x77, 0xba, 0x66, 0xe0, 0xd2, 0x2c, 0x8b } }
-
-#define GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID \
-"@mozilla.org/gonk-gps-geolocation-provider;1"
-
-class GonkGPSGeolocationProvider : public nsIGeolocationProvider
- , public nsIObserver
- , public nsISettingsServiceCallback
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIGEOLOCATIONPROVIDER
- NS_DECL_NSIOBSERVER
- NS_DECL_NSISETTINGSSERVICECALLBACK
-
- static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
-
-private:
-
- /* Client should use GetSingleton() to get the provider instance. */
- GonkGPSGeolocationProvider();
- GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &);
- GonkGPSGeolocationProvider & operator = (const GonkGPSGeolocationProvider &);
- virtual ~GonkGPSGeolocationProvider();
-
- static void LocationCallback(GpsLocation* location);
- static void StatusCallback(GpsStatus* status);
- static void SvStatusCallback(GpsSvStatus* sv_info);
- static void NmeaCallback(GpsUtcTime timestamp, const char* nmea, int length);
- static void SetCapabilitiesCallback(uint32_t capabilities);
- static void AcquireWakelockCallback();
- static void ReleaseWakelockCallback();
- static pthread_t CreateThreadCallback(const char* name, void (*start)(void*), void* arg);
- static void RequestUtcTimeCallback();
-
- static GpsCallbacks mCallbacks;
-
- void Init();
- void StartGPS();
- void ShutdownGPS();
- void InjectLocation(double latitude, double longitude, float accuracy);
- void RequestSettingValue(const char* aKey);
-
- const GpsInterface* GetGPSInterface();
-
- static GonkGPSGeolocationProvider* sSingleton;
-
- bool mStarted;
-
- bool mSupportsScheduling;
- bool mObservingSettingsChange;
- bool mSupportsSingleShot;
- bool mSupportsTimeInjection;
-
- const GpsInterface* mGpsInterface;
- nsCOMPtr<nsIGeolocationUpdate> mLocationCallback;
- nsCOMPtr<nsIThread> mInitThread;
- nsCOMPtr<nsIGeolocationProvider> mNetworkLocationProvider;
- nsCOMPtr<nsIDOMGeoPosition> mLastGPSPosition;
-
- class NetworkLocationUpdate : public nsIGeolocationUpdate
- {
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIGEOLOCATIONUPDATE
-
- NetworkLocationUpdate() {}
-
- private:
- virtual ~NetworkLocationUpdate() {}
- };
-};
-
-#endif /* GonkGPSGeolocationProvider_h */
diff --git a/dom/system/gonk/MozMtpCommon.h b/dom/system/gonk/MozMtpCommon.h
deleted file mode 100644
index 81c0a3a74..000000000
--- a/dom/system/gonk/MozMtpCommon.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozmtpcommon_h__
-#define mozilla_system_mozmtpcommon_h__
-
-#include "mozilla/Types.h"
-#include <android/log.h>
-
-#define USE_DEBUG 0
-
-#if USE_DEBUG
-#define MTP_DBG(msg, ...) \
- __android_log_print(ANDROID_LOG_DEBUG, "MozMtp", \
- "%s: " msg, __FUNCTION__, ##__VA_ARGS__)
-#else
-#define MTP_DBG(msg, ...)
-#endif
-
-#define MTP_LOG(msg, ...) \
- __android_log_print(ANDROID_LOG_INFO, "MozMtp", \
- "%s: " msg, __FUNCTION__, ##__VA_ARGS__)
-
-#define MTP_ERR(msg, ...) \
- __android_log_print(ANDROID_LOG_ERROR, "MozMtp", \
- "%s: " msg, __FUNCTION__, ##__VA_ARGS__)
-
-#define BEGIN_MTP_NAMESPACE \
- namespace mozilla { namespace system { namespace mtp {
-#define END_MTP_NAMESPACE \
- } /* namespace mtp */ } /* namespace system */ } /* namespace mozilla */
-#define USING_MTP_NAMESPACE \
- using namespace mozilla::system::mtp;
-
-namespace android {
- class MOZ_EXPORT MtpServer;
- class MOZ_EXPORT MtpStorage;
- class MOZ_EXPORT MtpStringBuffer;
- class MOZ_EXPORT MtpDatabase;
- class MOZ_EXPORT MtpDataPacket;
- class MOZ_EXPORT MtpProperty;
-}
-
-#include <mtp.h>
-#include <MtpDatabase.h>
-#include <MtpObjectInfo.h>
-#include <MtpProperty.h>
-#include <MtpServer.h>
-#include <MtpStorage.h>
-#include <MtpStringBuffer.h>
-#include <MtpTypes.h>
-
-#endif // mozilla_system_mtpcommon_h__
diff --git a/dom/system/gonk/MozMtpDatabase.cpp b/dom/system/gonk/MozMtpDatabase.cpp
deleted file mode 100644
index 29fe23e8d..000000000
--- a/dom/system/gonk/MozMtpDatabase.cpp
+++ /dev/null
@@ -1,1542 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MozMtpDatabase.h"
-#include "MozMtpServer.h"
-
-#include "base/message_loop.h"
-#include "DeviceStorage.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/AutoRestore.h"
-#include "mozilla/Scoped.h"
-#include "mozilla/Services.h"
-#include "nsIFile.h"
-#include "nsIObserverService.h"
-#include "nsPrintfCString.h"
-#include "nsString.h"
-#include "prio.h"
-
-#include <dirent.h>
-#include <libgen.h>
-#include <utime.h>
-#include <sys/stat.h>
-
-using namespace android;
-using namespace mozilla;
-
-namespace mozilla {
-MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCloseDir, PRDir, PR_CloseDir)
-}
-
-BEGIN_MTP_NAMESPACE
-
-static const char* kMtpWatcherNotify = "mtp-watcher-notify";
-
-#if 0
-// Some debug code for figuring out deadlocks, if you happen to run into
-// that scenario
-
-class DebugMutexAutoLock: public MutexAutoLock
-{
-public:
- DebugMutexAutoLock(mozilla::Mutex& aMutex)
- : MutexAutoLock(aMutex)
- {
- MTP_LOG("Mutex acquired");
- }
-
- ~DebugMutexAutoLock()
- {
- MTP_LOG("Releasing mutex");
- }
-};
-#define MutexAutoLock MTP_LOG("About to enter mutex"); DebugMutexAutoLock
-
-#endif
-
-static const char *
-ObjectPropertyAsStr(MtpObjectProperty aProperty)
-{
- switch (aProperty) {
- case MTP_PROPERTY_STORAGE_ID: return "MTP_PROPERTY_STORAGE_ID";
- case MTP_PROPERTY_OBJECT_FORMAT: return "MTP_PROPERTY_OBJECT_FORMAT";
- case MTP_PROPERTY_PROTECTION_STATUS: return "MTP_PROPERTY_PROTECTION_STATUS";
- case MTP_PROPERTY_OBJECT_SIZE: return "MTP_PROPERTY_OBJECT_SIZE";
- case MTP_PROPERTY_OBJECT_FILE_NAME: return "MTP_PROPERTY_OBJECT_FILE_NAME";
- case MTP_PROPERTY_DATE_CREATED: return "MTP_PROPERTY_DATE_CREATED";
- case MTP_PROPERTY_DATE_MODIFIED: return "MTP_PROPERTY_DATE_MODIFIED";
- case MTP_PROPERTY_PARENT_OBJECT: return "MTP_PROPERTY_PARENT_OBJECT";
- case MTP_PROPERTY_PERSISTENT_UID: return "MTP_PROPERTY_PERSISTENT_UID";
- case MTP_PROPERTY_NAME: return "MTP_PROPERTY_NAME";
- case MTP_PROPERTY_DATE_ADDED: return "MTP_PROPERTY_DATE_ADDED";
- case MTP_PROPERTY_WIDTH: return "MTP_PROPERTY_WIDTH";
- case MTP_PROPERTY_HEIGHT: return "MTP_PROPERTY_HEIGHT";
- case MTP_PROPERTY_IMAGE_BIT_DEPTH: return "MTP_PROPERTY_IMAGE_BIT_DEPTH";
- case MTP_PROPERTY_DISPLAY_NAME: return "MTP_PROPERTY_DISPLAY_NAME";
- }
- return "MTP_PROPERTY_???";
-}
-
-static char*
-FormatDate(time_t aTime, char *aDateStr, size_t aDateStrSize)
-{
- struct tm tm;
- localtime_r(&aTime, &tm);
- MTP_LOG("(%ld) tm_zone = %s off = %ld", aTime, tm.tm_zone, tm.tm_gmtoff);
- strftime(aDateStr, aDateStrSize, "%Y%m%dT%H%M%S", &tm);
- return aDateStr;
-}
-
-MozMtpDatabase::MozMtpDatabase()
- : mMutex("MozMtpDatabase::mMutex"),
- mDb(mMutex),
- mStorage(mMutex),
- mBeginSendObjectCalled(false)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // We use the index into the array as the handle. Since zero isn't a valid
- // index, we stick a dummy entry there.
-
- RefPtr<DbEntry> dummy;
-
- MutexAutoLock lock(mMutex);
- mDb.AppendElement(dummy);
-}
-
-//virtual
-MozMtpDatabase::~MozMtpDatabase()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-}
-
-void
-MozMtpDatabase::AddEntry(DbEntry *entry)
-{
- MutexAutoLock lock(mMutex);
-
- entry->mHandle = GetNextHandle();
- MOZ_ASSERT(mDb.Length() == entry->mHandle);
- mDb.AppendElement(entry);
-
- MTP_DBG("Handle: 0x%08x Parent: 0x%08x Path:'%s'",
- entry->mHandle, entry->mParent, entry->mPath.get());
-}
-
-void
-MozMtpDatabase::AddEntryAndNotify(DbEntry* entry, RefCountedMtpServer* aMtpServer)
-{
- AddEntry(entry);
- aMtpServer->sendObjectAdded(entry->mHandle);
-}
-
-void
-MozMtpDatabase::DumpEntries(const char* aLabel)
-{
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- MTP_LOG("%s: numEntries = %d", aLabel, numEntries);
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry) {
- MTP_LOG("%s: mDb[%d]: mHandle: 0x%08x mParent: 0x%08x StorageID: 0x%08x path: '%s'",
- aLabel, entryIndex, entry->mHandle, entry->mParent, entry->mStorageID, entry->mPath.get());
- } else {
- MTP_LOG("%s: mDb[%2d]: entry is NULL", aLabel, entryIndex);
- }
- }
-}
-
-MtpObjectHandle
-MozMtpDatabase::FindEntryByPath(const nsACString& aPath)
-{
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && entry->mPath.Equals(aPath)) {
- return entryIndex;
- }
- }
- return 0;
-}
-
-already_AddRefed<MozMtpDatabase::DbEntry>
-MozMtpDatabase::GetEntry(MtpObjectHandle aHandle)
-{
- MutexAutoLock lock(mMutex);
-
- RefPtr<DbEntry> entry;
-
- if (aHandle > 0 && aHandle < mDb.Length()) {
- entry = mDb[aHandle];
- }
- return entry.forget();
-}
-
-void
-MozMtpDatabase::RemoveEntry(MtpObjectHandle aHandle)
-{
- MutexAutoLock lock(mMutex);
- if (!IsValidHandle(aHandle)) {
- return;
- }
-
- RefPtr<DbEntry> removedEntry = mDb[aHandle];
- mDb[aHandle] = nullptr;
- MTP_DBG("0x%08x removed", aHandle);
- // if the entry is not a folder, just return.
- if (removedEntry->mObjectFormat != MTP_FORMAT_ASSOCIATION) {
- return;
- }
-
- // Find out and remove the children of aHandle.
- // Since the index for a directory will always be less than the index of any of its children,
- // we can remove the entire subtree in one pass.
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = aHandle+1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && IsValidHandle(entry->mParent) && !mDb[entry->mParent]) {
- mDb[entryIndex] = nullptr;
- MTP_DBG("0x%08x removed", aHandle);
- }
- }
-}
-
-void
-MozMtpDatabase::RemoveEntryAndNotify(MtpObjectHandle aHandle, RefCountedMtpServer* aMtpServer)
-{
- RemoveEntry(aHandle);
- aMtpServer->sendObjectRemoved(aHandle);
-}
-
-void
-MozMtpDatabase::UpdateEntryAndNotify(MtpObjectHandle aHandle, DeviceStorageFile* aFile, RefCountedMtpServer* aMtpServer)
-{
- UpdateEntry(aHandle, aFile);
- aMtpServer->sendObjectAdded(aHandle);
-}
-
-
-void
-MozMtpDatabase::UpdateEntry(MtpObjectHandle aHandle, DeviceStorageFile* aFile)
-{
- MutexAutoLock lock(mMutex);
-
- RefPtr<DbEntry> entry = mDb[aHandle];
-
- int64_t fileSize = 0;
- aFile->mFile->GetFileSize(&fileSize);
- entry->mObjectSize = fileSize;
-
- PRTime dateModifiedMsecs;
- // GetLastModifiedTime returns msecs
- aFile->mFile->GetLastModifiedTime(&dateModifiedMsecs);
- entry->mDateModified = dateModifiedMsecs / PR_MSEC_PER_SEC;
- entry->mDateCreated = entry->mDateModified;
- entry->mDateAdded = entry->mDateModified;
-
- #if USE_DEBUG
- char dateStr[20];
- MTP_DBG("UpdateEntry (0x%08x file %s) modified (%ld) %s",
- entry->mHandle, entry->mPath.get(),
- entry->mDateModified,
- FormatDate(entry->mDateModified, dateStr, sizeof(dateStr)));
- #endif
-}
-
-
-class MtpWatcherNotifyRunnable final : public Runnable
-{
-public:
- MtpWatcherNotifyRunnable(nsACString& aStorageName,
- nsACString& aPath,
- const char* aEventType)
- : mStorageName(aStorageName),
- mPath(aPath),
- mEventType(aEventType)
- {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- NS_ConvertUTF8toUTF16 storageName(mStorageName);
- NS_ConvertUTF8toUTF16 path(mPath);
-
- RefPtr<DeviceStorageFile> dsf(
- new DeviceStorageFile(NS_LITERAL_STRING(DEVICESTORAGE_SDCARD),
- storageName, path));
- NS_ConvertUTF8toUTF16 eventType(mEventType);
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-
- MTP_DBG("Sending mtp-watcher-notify %s %s %s",
- mEventType.get(), mStorageName.get(), mPath.get());
-
- obs->NotifyObservers(dsf, kMtpWatcherNotify, eventType.get());
- return NS_OK;
- }
-
-private:
- nsCString mStorageName;
- nsCString mPath;
- nsCString mEventType;
-};
-
-// MtpWatcherNotify is used to tell DeviceStorage when a file was changed
-// through the MTP server.
-void
-MozMtpDatabase::MtpWatcherNotify(DbEntry* aEntry, const char* aEventType)
-{
- // This function gets called from the MozMtpServer::mServerThread
- MOZ_ASSERT(!NS_IsMainThread());
-
- MTP_DBG("file: %s %s", aEntry->mPath.get(), aEventType);
-
- // Tell interested parties that a file was created, deleted, or modified.
-
- RefPtr<StorageEntry> storageEntry;
- {
- MutexAutoLock lock(mMutex);
-
- // FindStorage and the mStorage[] access both need to have the mutex held.
- StorageArray::index_type storageIndex = FindStorage(aEntry->mStorageID);
- if (storageIndex == StorageArray::NoIndex) {
- return;
- }
- storageEntry = mStorage[storageIndex];
- }
-
- // DeviceStorage wants the storageName and the path relative to the root
- // of the storage area, so we need to strip off the storagePath
-
- nsAutoCString relPath(Substring(aEntry->mPath,
- storageEntry->mStoragePath.Length() + 1));
-
- RefPtr<MtpWatcherNotifyRunnable> r =
- new MtpWatcherNotifyRunnable(storageEntry->mStorageName, relPath, aEventType);
- DebugOnly<nsresult> rv = NS_DispatchToMainThread(r);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-}
-
-// Called to tell the MTP server about new or deleted files,
-void
-MozMtpDatabase::MtpWatcherUpdate(RefCountedMtpServer* aMtpServer,
- DeviceStorageFile* aFile,
- const nsACString& aEventType)
-{
- // Runs on the MtpWatcherUpdate->mIOThread (see MozMtpServer.cpp)
- MOZ_ASSERT(!NS_IsMainThread());
-
- // Figure out which storage the belongs to (if any)
-
- if (!aFile->mFile) {
- // No path - don't bother looking.
- return;
- }
- nsString wideFilePath;
- aFile->mFile->GetPath(wideFilePath);
- NS_ConvertUTF16toUTF8 filePath(wideFilePath);
-
- nsCString evtType(aEventType);
- MTP_LOG("file %s %s", filePath.get(), evtType.get());
-
- MtpObjectHandle entryHandle = FindEntryByPath(filePath);
-
- if (aEventType.EqualsLiteral("modified")) {
- // To update the file information to the newest, we remove the entry for
- // the existing file, then re-add the entry for the file.
-
- if (entryHandle != 0) {
- // Update entry for the file and tell MTP.
- MTP_LOG("About to update handle 0x%08x file %s", entryHandle, filePath.get());
- UpdateEntryAndNotify(entryHandle, aFile, aMtpServer);
- }
- else {
- // Create entry for the file and tell MTP.
- CreateEntryForFileAndNotify(filePath, aFile, aMtpServer);
- }
- return;
- }
-
- if (aEventType.EqualsLiteral("deleted")) {
- if (entryHandle == 0) {
- // The entry has already been removed. We can't tell MTP.
- return;
- }
- MTP_LOG("About to call sendObjectRemoved Handle 0x%08x file %s", entryHandle, filePath.get());
- RemoveEntryAndNotify(entryHandle, aMtpServer);
- return;
- }
-}
-
-nsCString
-MozMtpDatabase::BaseName(const nsCString& path)
-{
- nsCOMPtr<nsIFile> file;
- NS_NewNativeLocalFile(path, false, getter_AddRefs(file));
- if (file) {
- nsCString leafName;
- file->GetNativeLeafName(leafName);
- return leafName;
- }
- return path;
-}
-
-static nsCString
-GetPathWithoutFileName(const nsCString& aFullPath)
-{
- nsCString path;
-
- int32_t offset = aFullPath.RFindChar('/');
- if (offset != kNotFound) {
- // The trailing slash will be as part of 'path'
- path = StringHead(aFullPath, offset + 1);
- }
-
- MTP_LOG("returning '%s'", path.get());
-
- return path;
-}
-
-void
-MozMtpDatabase::CreateEntryForFileAndNotify(const nsACString& aPath,
- DeviceStorageFile* aFile,
- RefCountedMtpServer* aMtpServer)
-{
- // Find the StorageID that this path corresponds to.
-
- nsCString remainder;
- MtpStorageID storageID = FindStorageIDFor(aPath, remainder);
- if (storageID == 0) {
- // The path in question isn't for a storage area we're monitoring.
- nsCString path(aPath);
- return;
- }
-
- bool exists = false;
- aFile->mFile->Exists(&exists);
- if (!exists) {
- // File doesn't exist, no sense telling MTP about it.
- // This could happen if Device Storage created and deleted a file right
- // away. Since the notifications wind up being async, the file might
- // not exist any more.
- return;
- }
-
- // Now walk the remaining directories, finding or creating as required.
-
- MtpObjectHandle parent = MTP_PARENT_ROOT;
- bool doFind = true;
- int32_t offset = aPath.Length() - remainder.Length();
- int32_t slash;
-
- do {
- nsDependentCSubstring component;
- slash = aPath.FindChar('/', offset);
- if (slash == kNotFound) {
- component.Rebind(aPath, 0, aPath.Length());
- } else {
- component.Rebind(aPath, 0 , slash);
- }
- if (doFind) {
- MtpObjectHandle entryHandle = FindEntryByPath(component);
- if (entryHandle != 0) {
- // We found an entry.
- parent = entryHandle;
- offset = slash + 1 ;
- continue;
- }
- }
-
- // We've got a directory component that doesn't exist. This means that all
- // further subdirectories won't exist either, so we can skip searching
- // for them.
- doFind = false;
-
- // This directory and the file don't exist, create them
-
- RefPtr<DbEntry> entry = new DbEntry;
-
- entry->mStorageID = storageID;
- entry->mObjectName = Substring(aPath, offset, slash - offset);
- entry->mParent = parent;
- entry->mDisplayName = entry->mObjectName;
- entry->mPath = component;
-
- if (slash == kNotFound) {
- // No slash - this is the file component
- entry->mObjectFormat = MTP_FORMAT_DEFINED;
-
- int64_t fileSize = 0;
- aFile->mFile->GetFileSize(&fileSize);
- entry->mObjectSize = fileSize;
-
- // Note: Even though PRTime records usec, GetLastModifiedTime returns
- // msecs.
- PRTime dateModifiedMsecs;
- aFile->mFile->GetLastModifiedTime(&dateModifiedMsecs);
- entry->mDateModified = dateModifiedMsecs / PR_MSEC_PER_SEC;
- } else {
- // Found a slash, this makes this a directory component
- entry->mObjectFormat = MTP_FORMAT_ASSOCIATION;
- entry->mObjectSize = 0;
- time(&entry->mDateModified);
- }
- entry->mDateCreated = entry->mDateModified;
- entry->mDateAdded = entry->mDateModified;
-
- AddEntryAndNotify(entry, aMtpServer);
- MTP_LOG("About to call sendObjectAdded Handle 0x%08x file %s", entry->mHandle, entry->mPath.get());
-
- parent = entry->mHandle;
- offset = slash + 1;
- } while (slash != kNotFound);
-
- return;
-}
-
-void
-MozMtpDatabase::AddDirectory(MtpStorageID aStorageID,
- const char* aPath,
- MtpObjectHandle aParent)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- ScopedCloseDir dir;
-
- if (!(dir = PR_OpenDir(aPath))) {
- MTP_ERR("Unable to open directory '%s'", aPath);
- return;
- }
-
- PRDirEntry* dirEntry;
- while ((dirEntry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
- nsPrintfCString filename("%s/%s", aPath, dirEntry->name);
- PRFileInfo64 fileInfo;
- if (PR_GetFileInfo64(filename.get(), &fileInfo) != PR_SUCCESS) {
- MTP_ERR("Unable to retrieve file information for '%s'", filename.get());
- continue;
- }
-
- RefPtr<DbEntry> entry = new DbEntry;
-
- entry->mStorageID = aStorageID;
- entry->mParent = aParent;
- entry->mObjectName = dirEntry->name;
- entry->mDisplayName = dirEntry->name;
- entry->mPath = filename;
-
- // PR_GetFileInfo64 returns timestamps in usecs
- entry->mDateModified = fileInfo.modifyTime / PR_USEC_PER_SEC;
- entry->mDateCreated = fileInfo.creationTime / PR_USEC_PER_SEC;
- time(&entry->mDateAdded);
-
- if (fileInfo.type == PR_FILE_FILE) {
- entry->mObjectFormat = MTP_FORMAT_DEFINED;
- //TODO: Check how 64-bit filesize are dealt with
- entry->mObjectSize = fileInfo.size;
- AddEntry(entry);
- } else if (fileInfo.type == PR_FILE_DIRECTORY) {
- entry->mObjectFormat = MTP_FORMAT_ASSOCIATION;
- entry->mObjectSize = 0;
- AddEntry(entry);
- AddDirectory(aStorageID, filename.get(), entry->mHandle);
- }
- }
-}
-
-MozMtpDatabase::StorageArray::index_type
-MozMtpDatabase::FindStorage(MtpStorageID aStorageID)
-{
- // Currently, this routine is called from MozMtpDatabase::RemoveStorage
- // and MozMtpDatabase::MtpWatcherNotify, which both hold mMutex.
-
- StorageArray::size_type numStorages = mStorage.Length();
- StorageArray::index_type storageIndex;
-
- for (storageIndex = 0; storageIndex < numStorages; storageIndex++) {
- RefPtr<StorageEntry> storage = mStorage[storageIndex];
- if (storage->mStorageID == aStorageID) {
- return storageIndex;
- }
- }
- return StorageArray::NoIndex;
-}
-
-// Find the storage ID for the storage area that contains aPath.
-MtpStorageID
-MozMtpDatabase::FindStorageIDFor(const nsACString& aPath, nsCSubstring& aRemainder)
-{
- MutexAutoLock lock(mMutex);
-
- aRemainder.Truncate();
-
- StorageArray::size_type numStorages = mStorage.Length();
- StorageArray::index_type storageIndex;
-
- for (storageIndex = 0; storageIndex < numStorages; storageIndex++) {
- RefPtr<StorageEntry> storage = mStorage[storageIndex];
- if (StringHead(aPath, storage->mStoragePath.Length()).Equals(storage->mStoragePath)) {
- if (aPath.Length() == storage->mStoragePath.Length()) {
- return storage->mStorageID;
- }
- if (aPath[storage->mStoragePath.Length()] == '/') {
- aRemainder = Substring(aPath, storage->mStoragePath.Length() + 1);
- return storage->mStorageID;
- }
- }
- }
- return 0;
-}
-
-void
-MozMtpDatabase::AddStorage(MtpStorageID aStorageID,
- const char* aPath,
- const char* aName)
-{
- // This is called on the IOThread from MozMtpStorage::StorageAvailable
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- MTP_DBG("StorageID: 0x%08x aPath: '%s' aName: '%s'",
- aStorageID, aPath, aName);
-
- PRFileInfo fileInfo;
- if (PR_GetFileInfo(aPath, &fileInfo) != PR_SUCCESS) {
- MTP_ERR("'%s' doesn't exist", aPath);
- return;
- }
- if (fileInfo.type != PR_FILE_DIRECTORY) {
- MTP_ERR("'%s' isn't a directory", aPath);
- return;
- }
-
- RefPtr<StorageEntry> storageEntry = new StorageEntry;
-
- storageEntry->mStorageID = aStorageID;
- storageEntry->mStoragePath = aPath;
- storageEntry->mStorageName = aName;
- {
- MutexAutoLock lock(mMutex);
- mStorage.AppendElement(storageEntry);
- }
-
- AddDirectory(aStorageID, aPath, MTP_PARENT_ROOT);
- {
- MutexAutoLock lock(mMutex);
- MTP_LOG("added %d items from tree '%s'", mDb.Length(), aPath);
- }
-}
-
-void
-MozMtpDatabase::RemoveStorage(MtpStorageID aStorageID)
-{
- MutexAutoLock lock(mMutex);
-
- // This is called on the IOThread from MozMtpStorage::StorageAvailable
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && entry->mStorageID == aStorageID) {
- mDb[entryIndex] = nullptr;
- }
- }
- StorageArray::index_type storageIndex = FindStorage(aStorageID);
- if (storageIndex != StorageArray::NoIndex) {
- mStorage.RemoveElementAt(storageIndex);
- }
-}
-
-// called from SendObjectInfo to reserve a database entry for the incoming file
-//virtual
-MtpObjectHandle
-MozMtpDatabase::beginSendObject(const char* aPath,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent,
- MtpStorageID aStorageID,
- uint64_t aSize,
- time_t aModified)
-{
- // If MtpServer::doSendObjectInfo receives a request with a parent of
- // MTP_PARENT_ROOT, then it fills in aPath with the fully qualified path
- // and then passes in a parent of zero.
-
- if (aParent == 0) {
- // Undo what doSendObjectInfo did
- aParent = MTP_PARENT_ROOT;
- }
-
- RefPtr<DbEntry> entry = new DbEntry;
-
- entry->mStorageID = aStorageID;
- entry->mParent = aParent;
- entry->mPath = aPath;
- entry->mObjectName = BaseName(entry->mPath);
- entry->mDisplayName = entry->mObjectName;
- entry->mObjectFormat = aFormat;
- entry->mObjectSize = aSize;
-
- if (aModified != 0) {
- // Currently, due to the way that parseDateTime is coded in
- // frameworks/av/media/mtp/MtpUtils.cpp, aModified winds up being the number
- // of seconds from the epoch in local time, rather than UTC time. So we
- // need to convert it back to being relative to UTC since that's what linux
- // expects time_t to contain.
- //
- // In more concrete testable terms, if the host parses 2015-08-02 02:22:00
- // as a local time in the Pacific timezone, aModified will come to us as
- // 1438482120.
- //
- // What we want is what mktime would pass us with the same date. Using python
- // (because its simple) with the current timezone set to be America/Vancouver:
- //
- // >>> import time
- // >>> time.mktime((2015, 8, 2, 2, 22, 0, 0, 0, -1))
- // 1438507320.0
- // >>> time.localtime(1438507320)
- // time.struct_time(tm_year=2015, tm_mon=8, tm_mday=2, tm_hour=2, tm_min=22, tm_sec=0, tm_wday=6, tm_yday=214, tm_isdst=1)
- //
- // Currently, when a file has a modification time of 2015-08-22 02:22:00 PDT
- // then aModified will come in as 1438482120 which corresponds to
- // 2015-08-22 02:22:00 UTC
-
- struct tm tm;
- if (gmtime_r(&aModified, &tm) != NULL) {
- // GMT always comes back with tm_isdst = 0, so we set it to -1 in order
- // to have mktime figure out dst based on the date.
- tm.tm_isdst = -1;
- aModified = mktime(&tm);
- if (aModified == (time_t)-1) {
- aModified = 0;
- }
- } else {
- aModified = 0;
- }
- }
- if (aModified == 0) {
- // The ubuntu host doesn't pass in the modified/created times in the
- // SENDOBJECT packet, so aModified winds up being zero. About the best
- // we can do with that is to use the current time.
- time(&aModified);
- }
-
- // And just an FYI for anybody else looking at timestamps. Under OSX you
- // need to use the Android File Transfer program to copy files into the
- // phone. That utility passes in both date modified and date created
- // timestamps, but they're both equal to the time that the file was copied
- // and not the times that are associated with the files.
-
- // Now we have aModified in a traditional time_t format, which is the number
- // of seconds from the UTC epoch.
-
- entry->mDateModified = aModified;
- entry->mDateCreated = entry->mDateModified;
- entry->mDateAdded = entry->mDateModified;
-
- AddEntry(entry);
-
- #if USE_DEBUG
- char dateStr[20];
- MTP_LOG("Handle: 0x%08x Parent: 0x%08x Path: '%s' aModified %ld %s",
- entry->mHandle, aParent, aPath, aModified,
- FormatDate(entry->mDateModified, dateStr, sizeof(dateStr)));
- #endif
-
- mBeginSendObjectCalled = true;
- return entry->mHandle;
-}
-
-// called to report success or failure of the SendObject file transfer
-// success should signal a notification of the new object's creation,
-// failure should remove the database entry created in beginSendObject
-
-//virtual
-void
-MozMtpDatabase::endSendObject(const char* aPath,
- MtpObjectHandle aHandle,
- MtpObjectFormat aFormat,
- bool aSucceeded)
-{
- MTP_LOG("Handle: 0x%08x Path: '%s'", aHandle, aPath);
-
- if (aSucceeded) {
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (entry) {
- // The android MTP server only copies the data in, it doesn't set the
- // modified timestamp, so we do that here.
-
- struct utimbuf new_times;
- struct stat sb;
-
- char dateStr[20];
- MTP_LOG("Path: '%s' setting modified time to (%ld) %s",
- entry->mPath.get(), entry->mDateModified,
- FormatDate(entry->mDateModified, dateStr, sizeof(dateStr)));
-
- stat(entry->mPath.get(), &sb);
- new_times.actime = sb.st_atime; // Preserve atime
- new_times.modtime = entry->mDateModified;
- utime(entry->mPath.get(), &new_times);
-
- MtpWatcherNotify(entry, "modified");
- }
- } else {
- RemoveEntry(aHandle);
- }
- mBeginSendObjectCalled = false;
-}
-
-//virtual
-MtpObjectHandleList*
-MozMtpDatabase::getObjectList(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent)
-{
- MTP_LOG("StorageID: 0x%08x Format: 0x%04x Parent: 0x%08x",
- aStorageID, aFormat, aParent);
-
- // aStorageID == 0xFFFFFFFF for all storage
- // aFormat == 0 for all formats
- // aParent == 0xFFFFFFFF for objects with no parents
- // aParent == 0 for all objects
-
- //TODO: Optimize
-
- UniquePtr<MtpObjectHandleList> list(new MtpObjectHandleList());
-
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry &&
- (aStorageID == 0xFFFFFFFF || entry->mStorageID == aStorageID) &&
- (aFormat == 0 || entry->mObjectFormat == aFormat) &&
- (aParent == 0 || entry->mParent == aParent)) {
- list->push(entry->mHandle);
- }
- }
- MTP_LOG(" returning %d items", list->size());
- return list.release();
-}
-
-//virtual
-int
-MozMtpDatabase::getNumObjects(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent)
-{
- MTP_LOG("");
-
- // aStorageID == 0xFFFFFFFF for all storage
- // aFormat == 0 for all formats
- // aParent == 0xFFFFFFFF for objects with no parents
- // aParent == 0 for all objects
-
- int count = 0;
-
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry &&
- (aStorageID == 0xFFFFFFFF || entry->mStorageID == aStorageID) &&
- (aFormat == 0 || entry->mObjectFormat == aFormat) &&
- (aParent == 0 || entry->mParent == aParent)) {
- count++;
- }
- }
-
- MTP_LOG(" returning %d items", count);
- return count;
-}
-
-//virtual
-MtpObjectFormatList*
-MozMtpDatabase::getSupportedPlaybackFormats()
-{
- static const uint16_t init_data[] = {MTP_FORMAT_UNDEFINED, MTP_FORMAT_ASSOCIATION,
- MTP_FORMAT_TEXT, MTP_FORMAT_HTML, MTP_FORMAT_WAV,
- MTP_FORMAT_MP3, MTP_FORMAT_MPEG, MTP_FORMAT_EXIF_JPEG,
- MTP_FORMAT_TIFF_EP, MTP_FORMAT_BMP, MTP_FORMAT_GIF,
- MTP_FORMAT_PNG, MTP_FORMAT_TIFF, MTP_FORMAT_WMA,
- MTP_FORMAT_OGG, MTP_FORMAT_AAC, MTP_FORMAT_MP4_CONTAINER,
- MTP_FORMAT_MP2, MTP_FORMAT_3GP_CONTAINER, MTP_FORMAT_FLAC};
-
- MtpObjectFormatList *list = new MtpObjectFormatList();
- list->appendArray(init_data, MOZ_ARRAY_LENGTH(init_data));
-
- MTP_LOG("returning Supported Playback Formats");
- return list;
-}
-
-//virtual
-MtpObjectFormatList*
-MozMtpDatabase::getSupportedCaptureFormats()
-{
- static const uint16_t init_data[] = {MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG};
-
- MtpObjectFormatList *list = new MtpObjectFormatList();
- list->appendArray(init_data, MOZ_ARRAY_LENGTH(init_data));
- MTP_LOG("returning MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG");
- return list;
-}
-
-static const MtpObjectProperty sSupportedObjectProperties[] =
-{
- MTP_PROPERTY_STORAGE_ID,
- MTP_PROPERTY_OBJECT_FORMAT,
- MTP_PROPERTY_PROTECTION_STATUS, // UINT16 - always 0
- MTP_PROPERTY_OBJECT_SIZE,
- MTP_PROPERTY_OBJECT_FILE_NAME, // just the filename - no directory
- MTP_PROPERTY_NAME,
- MTP_PROPERTY_DATE_CREATED,
- MTP_PROPERTY_DATE_MODIFIED,
- MTP_PROPERTY_PARENT_OBJECT,
- MTP_PROPERTY_PERSISTENT_UID,
- MTP_PROPERTY_DATE_ADDED,
-};
-
-//virtual
-MtpObjectPropertyList*
-MozMtpDatabase::getSupportedObjectProperties(MtpObjectFormat aFormat)
-{
- MTP_LOG("");
- MtpObjectPropertyList *list = new MtpObjectPropertyList();
- list->appendArray(sSupportedObjectProperties,
- MOZ_ARRAY_LENGTH(sSupportedObjectProperties));
- return list;
-}
-
-//virtual
-MtpDevicePropertyList*
-MozMtpDatabase::getSupportedDeviceProperties()
-{
- MTP_LOG("");
- static const uint16_t init_data[] = { MTP_DEVICE_PROPERTY_UNDEFINED };
-
- MtpDevicePropertyList *list = new MtpDevicePropertyList();
- list->appendArray(init_data, MOZ_ARRAY_LENGTH(init_data));
- return list;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket)
-{
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Invalid Handle: 0x%08x", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MTP_LOG("Handle: 0x%08x '%s' Property: %s 0x%08x",
- aHandle, entry->mDisplayName.get(), ObjectPropertyAsStr(aProperty), aProperty);
-
- switch (aProperty)
- {
- case MTP_PROPERTY_STORAGE_ID: aPacket.putUInt32(entry->mStorageID); break;
- case MTP_PROPERTY_PARENT_OBJECT: aPacket.putUInt32(entry->mParent); break;
- case MTP_PROPERTY_OBJECT_FORMAT: aPacket.putUInt16(entry->mObjectFormat); break;
- case MTP_PROPERTY_OBJECT_SIZE: aPacket.putUInt64(entry->mObjectSize); break;
- case MTP_PROPERTY_DISPLAY_NAME: aPacket.putString(entry->mDisplayName.get()); break;
- case MTP_PROPERTY_PERSISTENT_UID:
- // the same as aPacket.putUInt128
- aPacket.putUInt64(entry->mHandle);
- aPacket.putUInt64(entry->mStorageID);
- break;
- case MTP_PROPERTY_NAME: aPacket.putString(entry->mDisplayName.get()); break;
-
- default:
- MTP_LOG("Invalid Property: 0x%08x", aProperty);
- return MTP_RESPONSE_INVALID_OBJECT_PROP_CODE;
- }
-
- return MTP_RESPONSE_OK;
-}
-
-static int
-GetTypeOfObjectProp(MtpObjectProperty aProperty)
-{
- struct PropertyTableEntry {
- MtpObjectProperty property;
- int type;
- };
-
- static const PropertyTableEntry kObjectPropertyTable[] = {
- {MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
- {MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
- {MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
- {MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
- {MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
- {MTP_PROPERTY_DATE_CREATED, MTP_TYPE_STR },
- {MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
- {MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
- {MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
- {MTP_PROPERTY_NAME, MTP_TYPE_STR },
- {MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
- {MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
- };
-
- int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
- const PropertyTableEntry* entryProp = kObjectPropertyTable;
- int type = 0;
-
- for (int i = 0; i < count; ++i, ++entryProp) {
- if (entryProp->property == aProperty) {
- type = entryProp->type;
- break;
- }
- }
-
- return type;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::setObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket)
-{
- MTP_LOG("Handle: 0x%08x Property: 0x%08x", aHandle, aProperty);
-
- // Only support file name change
- if (aProperty != MTP_PROPERTY_OBJECT_FILE_NAME) {
- MTP_ERR("property 0x%x not supported", aProperty);
- return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
- }
-
- if (GetTypeOfObjectProp(aProperty) != MTP_TYPE_STR) {
- MTP_ERR("property type 0x%x not supported", GetTypeOfObjectProp(aProperty));
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Invalid Handle: 0x%08x", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MtpStringBuffer buf;
- aPacket.getString(buf);
-
- nsDependentCString newFileName(buf);
- nsCString newFileFullPath(GetPathWithoutFileName(entry->mPath) + newFileName);
-
- if (PR_Rename(entry->mPath.get(), newFileFullPath.get()) != PR_SUCCESS) {
- MTP_ERR("Failed to rename '%s' to '%s'",
- entry->mPath.get(), newFileFullPath.get());
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- MTP_LOG("renamed '%s' to '%s'", entry->mPath.get(), newFileFullPath.get());
-
- entry->mPath = newFileFullPath;
- entry->mObjectName = BaseName(entry->mPath);
- entry->mDisplayName = entry->mObjectName;
-
- return MTP_RESPONSE_OK;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket)
-{
- MTP_LOG("(GENERAL ERROR)");
- return MTP_RESPONSE_GENERAL_ERROR;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::setDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket)
-{
- MTP_LOG("(NOT SUPPORTED)");
- return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::resetDeviceProperty(MtpDeviceProperty aProperty)
-{
- MTP_LOG("(NOT SUPPORTED)");
- return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
-}
-
-void
-MozMtpDatabase::QueryEntries(MozMtpDatabase::MatchType aMatchType,
- uint32_t aMatchField1,
- uint32_t aMatchField2,
- UnprotectedDbArray &result)
-{
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIdx;
- RefPtr<DbEntry> entry;
-
- result.Clear();
-
- switch (aMatchType) {
-
- case MatchAll:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- if (mDb[entryIdx]) {
- result.AppendElement(mDb[entryIdx]);
- }
- }
- break;
-
- case MatchHandle:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mHandle == aMatchField1) {
- result.AppendElement(entry);
- // Handles are unique - return the one that we found.
- return;
- }
- }
- break;
-
- case MatchParent:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mParent == aMatchField1) {
- result.AppendElement(entry);
- }
- }
- break;
-
- case MatchFormat:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mObjectFormat == aMatchField1) {
- result.AppendElement(entry);
- }
- }
- break;
-
- case MatchHandleFormat:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mHandle == aMatchField1) {
- if (entry->mObjectFormat == aMatchField2) {
- result.AppendElement(entry);
- }
- // Only 1 entry can match my aHandle. So we can return early.
- return;
- }
- }
- break;
-
- case MatchParentFormat:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mParent == aMatchField1 && entry->mObjectFormat == aMatchField2) {
- result.AppendElement(entry);
- }
- }
- break;
-
- default:
- MOZ_ASSERT(!"Invalid MatchType");
- }
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getObjectPropertyList(MtpObjectHandle aHandle,
- uint32_t aFormat,
- uint32_t aProperty,
- int aGroupCode,
- int aDepth,
- MtpDataPacket& aPacket)
-{
- MTP_LOG("Handle: 0x%08x Format: 0x%08x aProperty: 0x%08x aGroupCode: %d aDepth %d",
- aHandle, aFormat, aProperty, aGroupCode, aDepth);
-
- if (aDepth > 1) {
- return MTP_RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED;
- }
- if (aGroupCode != 0) {
- return MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED;
- }
-
- MatchType matchType = MatchAll;
- uint32_t matchField1 = 0;
- uint32_t matchField2 = 0;
-
- // aHandle == 0 implies all objects at the root level
- // further specificed by aFormat and/or aDepth
-
- if (aFormat == 0) {
- if (aHandle == 0xffffffff) {
- // select all objects
- matchType = MatchAll;
- } else {
- if (aDepth == 1) {
- // select objects whose Parent matches aHandle
- matchType = MatchParent;
- matchField1 = aHandle;
- } else {
- // select object whose handle matches aHandle
- matchType = MatchHandle;
- matchField1 = aHandle;
- }
- }
- } else {
- if (aHandle == 0xffffffff) {
- // select all objects whose format matches aFormat
- matchType = MatchFormat;
- matchField1 = aFormat;
- } else {
- if (aDepth == 1) {
- // select objects whose Parent is aHandle and format matches aFormat
- matchType = MatchParentFormat;
- matchField1 = aHandle;
- matchField2 = aFormat;
- } else {
- // select objects whose handle is aHandle and format matches aFormat
- matchType = MatchHandleFormat;
- matchField1 = aHandle;
- matchField2 = aFormat;
- }
- }
- }
-
- UnprotectedDbArray result;
- QueryEntries(matchType, matchField1, matchField2, result);
-
- const MtpObjectProperty *objectPropertyList;
- size_t numObjectProperties = 0;
- MtpObjectProperty objectProperty;
-
- if (aProperty == 0xffffffff) {
- // return all supported properties
- numObjectProperties = MOZ_ARRAY_LENGTH(sSupportedObjectProperties);
- objectPropertyList = sSupportedObjectProperties;
- } else {
- // return property indicated by aProperty
- numObjectProperties = 1;
- objectProperty = aProperty;
- objectPropertyList = &objectProperty;
- }
-
- UnprotectedDbArray::size_type numEntries = result.Length();
- UnprotectedDbArray::index_type entryIdx;
-
- char dateStr[20];
-
- aPacket.putUInt32(numObjectProperties * numEntries);
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- RefPtr<DbEntry> entry = result[entryIdx];
-
- for (size_t propertyIdx = 0; propertyIdx < numObjectProperties; propertyIdx++) {
- aPacket.putUInt32(entry->mHandle);
- MtpObjectProperty prop = objectPropertyList[propertyIdx];
- aPacket.putUInt16(prop);
- switch (prop) {
-
- case MTP_PROPERTY_STORAGE_ID:
- aPacket.putUInt16(MTP_TYPE_UINT32);
- aPacket.putUInt32(entry->mStorageID);
- break;
-
- case MTP_PROPERTY_PARENT_OBJECT:
- aPacket.putUInt16(MTP_TYPE_UINT32);
- aPacket.putUInt32(entry->mParent);
- break;
-
- case MTP_PROPERTY_PERSISTENT_UID:
- aPacket.putUInt16(MTP_TYPE_UINT128);
- // the same as aPacket.putUInt128
- aPacket.putUInt64(entry->mHandle);
- aPacket.putUInt64(entry->mStorageID);
- break;
-
- case MTP_PROPERTY_OBJECT_FORMAT:
- aPacket.putUInt16(MTP_TYPE_UINT16);
- aPacket.putUInt16(entry->mObjectFormat);
- break;
-
- case MTP_PROPERTY_OBJECT_SIZE:
- aPacket.putUInt16(MTP_TYPE_UINT64);
- aPacket.putUInt64(entry->mObjectSize);
- break;
-
- case MTP_PROPERTY_OBJECT_FILE_NAME:
- case MTP_PROPERTY_NAME:
- aPacket.putUInt16(MTP_TYPE_STR);
- aPacket.putString(entry->mObjectName.get());
- break;
-
- case MTP_PROPERTY_PROTECTION_STATUS:
- aPacket.putUInt16(MTP_TYPE_UINT16);
- aPacket.putUInt16(0); // 0 = No Protection
- break;
-
- case MTP_PROPERTY_DATE_CREATED: {
- aPacket.putUInt16(MTP_TYPE_STR);
- aPacket.putString(FormatDate(entry->mDateCreated, dateStr, sizeof(dateStr)));
- MTP_LOG("mDateCreated: (%ld) %s", entry->mDateCreated, dateStr);
- break;
- }
-
- case MTP_PROPERTY_DATE_MODIFIED: {
- aPacket.putUInt16(MTP_TYPE_STR);
- aPacket.putString(FormatDate(entry->mDateModified, dateStr, sizeof(dateStr)));
- MTP_LOG("mDateModified: (%ld) %s", entry->mDateModified, dateStr);
- break;
- }
-
- case MTP_PROPERTY_DATE_ADDED: {
- aPacket.putUInt16(MTP_TYPE_STR);
- aPacket.putString(FormatDate(entry->mDateAdded, dateStr, sizeof(dateStr)));
- MTP_LOG("mDateAdded: (%ld) %s", entry->mDateAdded, dateStr);
- break;
- }
-
- default:
- MTP_ERR("Unrecognized property code: %u", prop);
- return MTP_RESPONSE_GENERAL_ERROR;
- }
- }
- }
- return MTP_RESPONSE_OK;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getObjectInfo(MtpObjectHandle aHandle,
- MtpObjectInfo& aInfo)
-{
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Handle 0x%08x is invalid", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MTP_LOG("Handle: 0x%08x Display:'%s' Object:'%s'", aHandle, entry->mDisplayName.get(), entry->mObjectName.get());
-
- aInfo.mHandle = aHandle;
- aInfo.mStorageID = entry->mStorageID;
- aInfo.mFormat = entry->mObjectFormat;
- aInfo.mProtectionStatus = 0x0;
-
- if (entry->mObjectSize > 0xFFFFFFFFuLL) {
- aInfo.mCompressedSize = 0xFFFFFFFFuLL;
- } else {
- aInfo.mCompressedSize = entry->mObjectSize;
- }
-
- aInfo.mThumbFormat = MTP_FORMAT_UNDEFINED;
- aInfo.mThumbCompressedSize = 0;
- aInfo.mThumbPixWidth = 0;
- aInfo.mThumbPixHeight = 0;
- aInfo.mImagePixWidth = 0;
- aInfo.mImagePixHeight = 0;
- aInfo.mImagePixDepth = 0;
- aInfo.mParent = entry->mParent;
- aInfo.mAssociationType = 0;
- aInfo.mAssociationDesc = 0;
- aInfo.mSequenceNumber = 0;
- aInfo.mName = ::strdup(entry->mObjectName.get());
- aInfo.mDateCreated = entry->mDateCreated;
- aInfo.mDateModified = entry->mDateModified;
-
- MTP_LOG("aInfo.mDateCreated = %ld entry->mDateCreated = %ld",
- aInfo.mDateCreated, entry->mDateCreated);
- MTP_LOG("aInfo.mDateModified = %ld entry->mDateModified = %ld",
- aInfo.mDateModified, entry->mDateModified);
-
- aInfo.mKeywords = ::strdup("fxos,touch");
-
- return MTP_RESPONSE_OK;
-}
-
-//virtual
-void*
-MozMtpDatabase::getThumbnail(MtpObjectHandle aHandle, size_t& aOutThumbSize)
-{
- MTP_LOG("Handle: 0x%08x (returning nullptr)", aHandle);
-
- aOutThumbSize = 0;
-
- return nullptr;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getObjectFilePath(MtpObjectHandle aHandle,
- MtpString& aOutFilePath,
- int64_t& aOutFileLength,
- MtpObjectFormat& aOutFormat)
-{
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Handle 0x%08x is invalid", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MTP_LOG("Handle: 0x%08x FilePath: '%s'", aHandle, entry->mPath.get());
-
- aOutFilePath = entry->mPath.get();
- aOutFileLength = entry->mObjectSize;
- aOutFormat = entry->mObjectFormat;
-
- return MTP_RESPONSE_OK;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::deleteFile(MtpObjectHandle aHandle)
-{
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Invalid Handle: 0x%08x", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MTP_LOG("Handle: 0x%08x '%s'", aHandle, entry->mPath.get());
-
- // File deletion will happen in lower level implementation.
- // The only thing we need to do is removing the entry from the db.
- RemoveEntry(aHandle);
-
- // Tell Device Storage that the file is gone.
- MtpWatcherNotify(entry, "deleted");
-
- return MTP_RESPONSE_OK;
-}
-
-#if 0
-//virtual
-MtpResponseCode
-MozMtpDatabase::moveFile(MtpObjectHandle aHandle, MtpObjectHandle aNewParent)
-{
- MTP_LOG("Handle: 0x%08x NewParent: 0x%08x", aHandle, aNewParent);
-
- // change parent
-
- return MTP_RESPONSE_OK
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::copyFile(MtpObjectHandle aHandle, MtpObjectHandle aNewParent)
-{
- MTP_LOG("Handle: 0x%08x NewParent: 0x%08x", aHandle, aNewParent);
-
- // duplicate DbEntry
- // change parent
-
- return MTP_RESPONSE_OK
-}
-#endif
-
-//virtual
-MtpObjectHandleList*
-MozMtpDatabase::getObjectReferences(MtpObjectHandle aHandle)
-{
- MTP_LOG("Handle: 0x%08x (returning nullptr)", aHandle);
- return nullptr;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::setObjectReferences(MtpObjectHandle aHandle,
- MtpObjectHandleList* aReferences)
-{
- MTP_LOG("Handle: 0x%08x (NOT SUPPORTED)", aHandle);
- return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
-}
-
-//virtual
-MtpProperty*
-MozMtpDatabase::getObjectPropertyDesc(MtpObjectProperty aProperty,
- MtpObjectFormat aFormat)
-{
- MTP_LOG("Property: %s 0x%08x", ObjectPropertyAsStr(aProperty), aProperty);
-
- MtpProperty* result = nullptr;
- switch (aProperty)
- {
- case MTP_PROPERTY_PROTECTION_STATUS:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT16);
- break;
- case MTP_PROPERTY_OBJECT_FORMAT:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT16, false, aFormat);
- break;
- case MTP_PROPERTY_STORAGE_ID:
- case MTP_PROPERTY_PARENT_OBJECT:
- case MTP_PROPERTY_WIDTH:
- case MTP_PROPERTY_HEIGHT:
- case MTP_PROPERTY_IMAGE_BIT_DEPTH:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT32);
- break;
- case MTP_PROPERTY_OBJECT_SIZE:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT64);
- break;
- case MTP_PROPERTY_DISPLAY_NAME:
- case MTP_PROPERTY_NAME:
- result = new MtpProperty(aProperty, MTP_TYPE_STR);
- break;
- case MTP_PROPERTY_OBJECT_FILE_NAME:
- result = new MtpProperty(aProperty, MTP_TYPE_STR, true);
- break;
- case MTP_PROPERTY_DATE_CREATED:
- case MTP_PROPERTY_DATE_MODIFIED:
- case MTP_PROPERTY_DATE_ADDED:
- result = new MtpProperty(aProperty, MTP_TYPE_STR);
- result->setFormDateTime();
- break;
- case MTP_PROPERTY_PERSISTENT_UID:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT128);
- break;
- default:
- break;
- }
-
- return result;
-}
-
-//virtual
-MtpProperty*
-MozMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty aProperty)
-{
- MTP_LOG("(returning MTP_DEVICE_PROPERTY_UNDEFINED)");
- return new MtpProperty(MTP_DEVICE_PROPERTY_UNDEFINED, MTP_TYPE_UNDEFINED);
-}
-
-//virtual
-void
-MozMtpDatabase::sessionStarted()
-{
- MTP_LOG("");
-}
-
-//virtual
-void
-MozMtpDatabase::sessionEnded()
-{
- MTP_LOG("");
-}
-
-END_MTP_NAMESPACE
diff --git a/dom/system/gonk/MozMtpDatabase.h b/dom/system/gonk/MozMtpDatabase.h
deleted file mode 100644
index 8b308762e..000000000
--- a/dom/system/gonk/MozMtpDatabase.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozmtpdatabase_h__
-#define mozilla_system_mozmtpdatabase_h__
-
-#include "MozMtpCommon.h"
-
-#include "mozilla/Mutex.h"
-#include "mozilla/RefPtr.h"
-#include "nsCOMPtr.h"
-#include "nsString.h"
-#include "nsIThread.h"
-#include "nsTArray.h"
-
-class DeviceStorageFile;
-
-BEGIN_MTP_NAMESPACE // mozilla::system::mtp
-
-class RefCountedMtpServer;
-
-using namespace android;
-
-class MozMtpDatabase final : public MtpDatabase
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpDatabase)
-
- MozMtpDatabase();
-
- // called from SendObjectInfo to reserve a database entry for the incoming file
- virtual MtpObjectHandle beginSendObject(const char* aPath,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent,
- MtpStorageID aStorageID,
- uint64_t aSize,
- time_t aModified);
-
- // called to report success or failure of the SendObject file transfer
- // success should signal a notification of the new object's creation,
- // failure should remove the database entry created in beginSendObject
- virtual void endSendObject(const char* aPath,
- MtpObjectHandle aHandle,
- MtpObjectFormat aFormat,
- bool aSucceeded);
-
- virtual MtpObjectHandleList* getObjectList(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent);
-
- virtual int getNumObjects(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent);
-
- virtual MtpObjectFormatList* getSupportedPlaybackFormats();
-
- virtual MtpObjectFormatList* getSupportedCaptureFormats();
-
- virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat aFormat);
-
- virtual MtpDevicePropertyList* getSupportedDeviceProperties();
-
- virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty aProperty);
-
- virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle aHandle,
- uint32_t aFormat,
- uint32_t aProperty,
- int aGroupCode,
- int aDepth,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode getObjectInfo(MtpObjectHandle aHandle,
- MtpObjectInfo& aInfo);
-
- virtual void* getThumbnail(MtpObjectHandle aHandle, size_t& aOutThumbSize);
-
- virtual MtpResponseCode getObjectFilePath(MtpObjectHandle aHandle,
- MtpString& aOutFilePath,
- int64_t& aOutFileLength,
- MtpObjectFormat& aOutFormat);
-
- virtual MtpResponseCode deleteFile(MtpObjectHandle aHandle);
-
- virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle aHandle);
-
- virtual MtpResponseCode setObjectReferences(MtpObjectHandle aHandle,
- MtpObjectHandleList* aReferences);
-
- virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty aProperty,
- MtpObjectFormat aFormat);
-
- virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty aProperty);
-
- virtual void sessionStarted();
-
- virtual void sessionEnded();
-
- void AddStorage(MtpStorageID aStorageID, const char* aPath, const char *aName);
- void RemoveStorage(MtpStorageID aStorageID);
-
- void MtpWatcherUpdate(RefCountedMtpServer* aMtpServer,
- DeviceStorageFile* aFile,
- const nsACString& aEventType);
-
-protected:
- virtual ~MozMtpDatabase();
-
-private:
-
- struct DbEntry final
- {
- DbEntry()
- : mHandle(0),
- mStorageID(0),
- mObjectFormat(MTP_FORMAT_DEFINED),
- mParent(0),
- mObjectSize(0),
- mDateCreated(0),
- mDateModified(0),
- mDateAdded(0) {}
-
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DbEntry)
-
- MtpObjectHandle mHandle; // uint32_t
- MtpStorageID mStorageID; // uint32_t
- nsCString mObjectName;
- MtpObjectFormat mObjectFormat; // uint16_t
- MtpObjectHandle mParent; // uint32_t
- uint64_t mObjectSize;
- nsCString mDisplayName;
- nsCString mPath;
- time_t mDateCreated;
- time_t mDateModified;
- time_t mDateAdded;
-
- protected:
- ~DbEntry() {}
- };
-
- template<class T>
- class ProtectedTArray : private nsTArray<T>
- {
- public:
- typedef T elem_type;
- typedef typename nsTArray<T>::size_type size_type;
- typedef typename nsTArray<T>::index_type index_type;
- typedef nsTArray<T> base_type;
-
- static const index_type NoIndex = base_type::NoIndex;
-
- ProtectedTArray(mozilla::Mutex& aMutex)
- : mMutex(aMutex)
- {}
-
- size_type Length() const
- {
- // GRR - This assert prints to stderr and won't show up in logcat.
- mMutex.AssertCurrentThreadOwns();
- return base_type::Length();
- }
-
- template <class Item>
- elem_type* AppendElement(const Item& aItem)
- {
- mMutex.AssertCurrentThreadOwns();
- return base_type::AppendElement(aItem);
- }
-
- void Clear()
- {
- mMutex.AssertCurrentThreadOwns();
- base_type::Clear();
- }
-
- void RemoveElementAt(index_type aIndex)
- {
- mMutex.AssertCurrentThreadOwns();
- base_type::RemoveElementAt(aIndex);
- }
-
- elem_type& operator[](index_type aIndex)
- {
- mMutex.AssertCurrentThreadOwns();
- return base_type::ElementAt(aIndex);
- }
-
- const elem_type& operator[](index_type aIndex) const
- {
- mMutex.AssertCurrentThreadOwns();
- return base_type::ElementAt(aIndex);
- }
-
- private:
- mozilla::Mutex& mMutex;
- };
- typedef nsTArray<RefPtr<DbEntry> > UnprotectedDbArray;
- typedef ProtectedTArray<RefPtr<DbEntry> > ProtectedDbArray;
-
- struct StorageEntry final
- {
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StorageEntry)
-
- MtpStorageID mStorageID;
- nsCString mStoragePath;
- nsCString mStorageName;
-
- protected:
- ~StorageEntry() {}
- };
- typedef ProtectedTArray<RefPtr<StorageEntry> > StorageArray;
-
- enum MatchType
- {
- MatchAll,
- MatchHandle,
- MatchParent,
- MatchFormat,
- MatchHandleFormat,
- MatchParentFormat,
- };
-
- bool IsValidHandle(MtpObjectHandle aHandle)
- {
- return aHandle > 0 && aHandle < mDb.Length();
- }
-
- void AddEntry(DbEntry* aEntry);
- void AddEntryAndNotify(DbEntry* aEntr, RefCountedMtpServer* aMtpServer);
- void DumpEntries(const char* aLabel);
- MtpObjectHandle FindEntryByPath(const nsACString& aPath);
- already_AddRefed<DbEntry> GetEntry(MtpObjectHandle aHandle);
- void RemoveEntry(MtpObjectHandle aHandle);
- void RemoveEntryAndNotify(MtpObjectHandle aHandle, RefCountedMtpServer* aMtpServer);
- void UpdateEntry(MtpObjectHandle aHandle, DeviceStorageFile* aFile);
- void UpdateEntryAndNotify(MtpObjectHandle aHandle, DeviceStorageFile* aFile,
- RefCountedMtpServer* aMtpServer);
- void QueryEntries(MatchType aMatchType, uint32_t aMatchField1,
- uint32_t aMatchField2, UnprotectedDbArray& aResult);
-
- nsCString BaseName(const nsCString& aPath);
-
-
- MtpObjectHandle GetNextHandle()
- {
- return mDb.Length();
- }
-
- void AddDirectory(MtpStorageID aStorageID, const char *aPath, MtpObjectHandle aParent);
-
- void CreateEntryForFileAndNotify(const nsACString& aPath,
- DeviceStorageFile* aFile,
- RefCountedMtpServer* aMtpServer);
-
- StorageArray::index_type FindStorage(MtpStorageID aStorageID);
- MtpStorageID FindStorageIDFor(const nsACString& aPath, nsCSubstring& aRemainder);
- void MtpWatcherNotify(DbEntry* aEntry, const char* aEventType);
-
- // We need a mutex to protext mDb and mStorage. The MTP server runs on a
- // dedicated thread, and it updates/accesses mDb. When files are updated
- // through DeviceStorage, we need to update/access mDb and mStorage as well
- // (from a non-MTP server thread).
- mozilla::Mutex mMutex;
- ProtectedDbArray mDb;
- StorageArray mStorage;
-
- bool mBeginSendObjectCalled;
-};
-
-END_MTP_NAMESPACE
-
-#endif // mozilla_system_mozmtpdatabase_h__
diff --git a/dom/system/gonk/MozMtpServer.cpp b/dom/system/gonk/MozMtpServer.cpp
deleted file mode 100644
index c26b6368b..000000000
--- a/dom/system/gonk/MozMtpServer.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MozMtpServer.h"
-#include "MozMtpDatabase.h"
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-#include <private/android_filesystem_config.h>
-
-#include "base/message_loop.h"
-#include "DeviceStorage.h"
-#include "mozilla/LazyIdleThread.h"
-#include "mozilla/Scoped.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsISupportsImpl.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-
-#include "Volume.h"
-
-#define DEFAULT_THREAD_TIMEOUT_MS 30000
-
-using namespace android;
-using namespace mozilla;
-BEGIN_MTP_NAMESPACE
-
-static const char* kMtpWatcherUpdate = "mtp-watcher-update";
-
-class MtpWatcherUpdateRunnable final : public Runnable
-{
-public:
- MtpWatcherUpdateRunnable(MozMtpDatabase* aMozMtpDatabase,
- RefCountedMtpServer* aMtpServer,
- DeviceStorageFile* aFile,
- const nsACString& aEventType)
- : mMozMtpDatabase(aMozMtpDatabase),
- mMtpServer(aMtpServer),
- mFile(aFile),
- mEventType(aEventType)
- {}
-
- NS_IMETHOD Run() override
- {
- // Runs on the MtpWatcherUpdate->mIOThread
- MOZ_ASSERT(!NS_IsMainThread());
-
- mMozMtpDatabase->MtpWatcherUpdate(mMtpServer, mFile, mEventType);
- return NS_OK;
- }
-
-private:
- RefPtr<MozMtpDatabase> mMozMtpDatabase;
- RefPtr<RefCountedMtpServer> mMtpServer;
- RefPtr<DeviceStorageFile> mFile;
- nsCString mEventType;
-};
-
-// The MtpWatcherUpdate class listens for mtp-watcher-update events
-// and tells the MtpServer about changes made in device storage.
-class MtpWatcherUpdate final : public nsIObserver
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
-
- MtpWatcherUpdate(MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer)
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- mIOThread = new LazyIdleThread(
- DEFAULT_THREAD_TIMEOUT_MS,
- NS_LITERAL_CSTRING("MtpWatcherUpdate"));
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- obs->AddObserver(this, kMtpWatcherUpdate, false);
- }
-
- NS_IMETHOD
- Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- if (strcmp(aTopic, kMtpWatcherUpdate)) {
- // We're only interested in mtp-watcher-update events
- return NS_OK;
- }
-
- NS_ConvertUTF16toUTF8 eventType(aData);
- if (!eventType.EqualsLiteral("modified") && !eventType.EqualsLiteral("deleted")) {
- // Bug 1074604: Needn't handle "created" event, once file operation
- // finished, it would trigger "modified" event.
- return NS_OK;
- }
-
- DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
- file->Dump(kMtpWatcherUpdate);
- MTP_LOG("%s: file %s %s", kMtpWatcherUpdate,
- NS_LossyConvertUTF16toASCII(file->mPath).get(),
- eventType.get());
-
- RefPtr<MozMtpDatabase> mozMtpDatabase = mMozMtpServer->GetMozMtpDatabase();
- RefPtr<RefCountedMtpServer> mtpServer = mMozMtpServer->GetMtpServer();
-
- // We're not supposed to perform I/O on the main thread, so punt the
- // notification (which will write to /dev/mtp_usb) to an I/O Thread.
-
- RefPtr<MtpWatcherUpdateRunnable> r =
- new MtpWatcherUpdateRunnable(mozMtpDatabase, mtpServer, file, eventType);
- mIOThread->Dispatch(r, NS_DISPATCH_NORMAL);
-
- return NS_OK;
- }
-
-protected:
- ~MtpWatcherUpdate()
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- obs->RemoveObserver(this, kMtpWatcherUpdate);
- }
-
-private:
- RefPtr<MozMtpServer> mMozMtpServer;
- nsCOMPtr<nsIThread> mIOThread;
-};
-NS_IMPL_ISUPPORTS(MtpWatcherUpdate, nsIObserver)
-static StaticRefPtr<MtpWatcherUpdate> sMtpWatcherUpdate;
-
-class AllocMtpWatcherUpdateRunnable final : public Runnable
-{
-public:
- AllocMtpWatcherUpdateRunnable(MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer)
- {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- sMtpWatcherUpdate = new MtpWatcherUpdate(mMozMtpServer);
- return NS_OK;
- }
-private:
- RefPtr<MozMtpServer> mMozMtpServer;
-};
-
-class FreeMtpWatcherUpdateRunnable final : public Runnable
-{
-public:
- FreeMtpWatcherUpdateRunnable(MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer)
- {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- sMtpWatcherUpdate = nullptr;
- return NS_OK;
- }
-private:
- RefPtr<MozMtpServer> mMozMtpServer;
-};
-
-class MtpServerRunnable : public Runnable
-{
-public:
- MtpServerRunnable(int aMtpUsbFd, MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer),
- mMtpUsbFd(aMtpUsbFd)
- {
- }
-
- nsresult Run()
- {
- RefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
-
- DebugOnly<nsresult> rv =
- NS_DispatchToMainThread(new AllocMtpWatcherUpdateRunnable(mMozMtpServer));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-
- MTP_LOG("MozMtpServer started");
- server->run();
- MTP_LOG("MozMtpServer finished");
-
- // server->run will have closed the file descriptor.
- mMtpUsbFd.forget();
-
- rv = NS_DispatchToMainThread(new FreeMtpWatcherUpdateRunnable(mMozMtpServer));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-
- return NS_OK;
- }
-
-private:
- RefPtr<MozMtpServer> mMozMtpServer;
- ScopedClose mMtpUsbFd; // We want to hold this open while the server runs
-};
-
-already_AddRefed<RefCountedMtpServer>
-MozMtpServer::GetMtpServer()
-{
- RefPtr<RefCountedMtpServer> server = mMtpServer;
- return server.forget();
-}
-
-already_AddRefed<MozMtpDatabase>
-MozMtpServer::GetMozMtpDatabase()
-{
- RefPtr<MozMtpDatabase> db = mMozMtpDatabase;
- return db.forget();
-}
-
-bool
-MozMtpServer::Init()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- const char *mtpUsbFilename = "/dev/mtp_usb";
- mMtpUsbFd = open(mtpUsbFilename, O_RDWR);
- if (mMtpUsbFd.get() < 0) {
- MTP_ERR("open of '%s' failed((%s))", mtpUsbFilename, strerror(errno));
- return false;
- }
- MTP_LOG("Opened '%s' fd %d", mtpUsbFilename, mMtpUsbFd.get());
-
- mMozMtpDatabase = new MozMtpDatabase();
- mMtpServer = new RefCountedMtpServer(mMtpUsbFd.get(), // fd
- mMozMtpDatabase.get(), // MtpDatabase
- false, // ptp?
- AID_MEDIA_RW, // file group
- 0664, // file permissions
- 0775); // dir permissions
- return true;
-}
-
-void
-MozMtpServer::Run()
-{
- nsresult rv = NS_NewNamedThread("MtpServer", getter_AddRefs(mServerThread));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
- MOZ_ASSERT(mServerThread);
- mServerThread->Dispatch(new MtpServerRunnable(mMtpUsbFd.forget(), this), NS_DISPATCH_NORMAL);
-}
-
-END_MTP_NAMESPACE
diff --git a/dom/system/gonk/MozMtpServer.h b/dom/system/gonk/MozMtpServer.h
deleted file mode 100644
index 4989c25ef..000000000
--- a/dom/system/gonk/MozMtpServer.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozmtpserver_h__
-#define mozilla_system_mozmtpserver_h__
-
-#include "MozMtpCommon.h"
-#include "MozMtpDatabase.h"
-
-#include "mozilla/FileUtils.h"
-
-#include "nsCOMPtr.h"
-#include "nsIThread.h"
-
-BEGIN_MTP_NAMESPACE
-using namespace android;
-
-class RefCountedMtpServer : public MtpServer
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMtpServer)
-
- RefCountedMtpServer(int aFd, MtpDatabase* aDatabase, bool aPtp,
- int aFileGroup, int aFilePerm, int aDirectoryPerm)
- : MtpServer(aFd, aDatabase, aPtp, aFileGroup, aFilePerm, aDirectoryPerm)
- {
- }
-
-protected:
- virtual ~RefCountedMtpServer() {}
-};
-
-class MozMtpServer
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpServer)
-
- bool Init();
- void Run();
-
- already_AddRefed<RefCountedMtpServer> GetMtpServer();
- already_AddRefed<MozMtpDatabase> GetMozMtpDatabase();
-
-protected:
- virtual ~MozMtpServer() {}
-
-private:
- RefPtr<RefCountedMtpServer> mMtpServer;
- RefPtr<MozMtpDatabase> mMozMtpDatabase;
- nsCOMPtr<nsIThread> mServerThread;
- ScopedClose mMtpUsbFd;
-};
-
-END_MTP_NAMESPACE
-
-#endif // mozilla_system_mozmtpserver_h__
-
-
diff --git a/dom/system/gonk/MozMtpStorage.cpp b/dom/system/gonk/MozMtpStorage.cpp
deleted file mode 100644
index 9c358a132..000000000
--- a/dom/system/gonk/MozMtpStorage.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MozMtpStorage.h"
-#include "MozMtpDatabase.h"
-#include "MozMtpServer.h"
-
-#include "base/message_loop.h"
-#include "nsXULAppAPI.h"
-
-BEGIN_MTP_NAMESPACE
-using namespace android;
-
-MozMtpStorage::MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer),
- mVolume(aVolume)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // The MtpStorageID has the physical volume in the top 16 bits, and the
- // logical volumein the lower 16 bits. We treat each volume as a separate
- // phsyical storage;
- mStorageID = mVolume->Id() << 16 | 1;
-
- MTP_LOG("Storage constructed for Volume %s mStorageID 0x%08x",
- aVolume->NameStr(), mStorageID);
-
- Volume::RegisterVolumeObserver(this, "MozMtpStorage");
-
- // Get things in sync
- Notify(mVolume);
-}
-
-MozMtpStorage::~MozMtpStorage()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- MTP_LOG("Storage destructed for Volume %s mStorageID 0x%08x",
- mVolume->NameStr(), mStorageID);
-
- Volume::UnregisterVolumeObserver(this, "MozMtpStorage");
- if (mMtpStorage) {
- StorageUnavailable();
- }
-}
-
-// virtual
-void
-MozMtpStorage::Notify(Volume* const& aVolume)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (aVolume != mVolume) {
- // Not our volume
- return;
- }
- Volume::STATE volState = aVolume->State();
-
- MTP_LOG("Volume %s mStorageID 0x%08x state changed to %s SharingEnabled: %d",
- aVolume->NameStr(), mStorageID, aVolume->StateStr(),
- aVolume->IsSharingEnabled());
-
- // vol->IsSharingEnabled really only applies to UMS volumes. We assume that
- // that as long as MTP is enabled, then all volumes will be shared. The UI
- // currently doesn't give us anything more granular than on/off.
-
- if (mMtpStorage) {
- if (volState != nsIVolume::STATE_MOUNTED) {
- // The volume is no longer accessible. We need to remove this storage
- // from the MTP server
- StorageUnavailable();
- }
- } else {
- if (volState == nsIVolume::STATE_MOUNTED) {
- // The volume is accessible. Tell the MTP server.
- StorageAvailable();
- }
- }
-}
-
-void
-MozMtpStorage::StorageAvailable()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- nsCString mountPoint = mVolume->MountPoint();
-
- MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MozMtpDatabase",
- mVolume->NameStr(), mStorageID, mountPoint.get());
-
- RefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
- db->AddStorage(mStorageID, mountPoint.get(), mVolume->NameStr());
-
- MOZ_ASSERT(!mMtpStorage);
-
- //TODO: Figure out what to do about maxFileSize.
-
- mMtpStorage.reset(new MtpStorage(mStorageID, // id
- mountPoint.get(), // filePath
- mVolume->NameStr(), // description
- 1024uLL * 1024uLL, // reserveSpace
- mVolume->IsHotSwappable(), // removable
- 2uLL * 1024uLL * 1024uLL * 1024uLL)); // maxFileSize
- RefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
-
- MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MtpServer",
- mVolume->NameStr(), mStorageID, mountPoint.get());
- server->addStorage(mMtpStorage.get());
-}
-
-void
-MozMtpStorage::StorageUnavailable()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(mMtpStorage);
-
- MTP_LOG("Removing mStorageID 0x%08x from MtpServer", mStorageID);
-
- RefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
- server->removeStorage(mMtpStorage.get());
-
- MTP_LOG("Removing mStorageID 0x%08x from MozMtpDatabse", mStorageID);
-
- RefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
- db->RemoveStorage(mStorageID);
-
- mMtpStorage = nullptr;
-}
-
-END_MTP_NAMESPACE
-
-
diff --git a/dom/system/gonk/MozMtpStorage.h b/dom/system/gonk/MozMtpStorage.h
deleted file mode 100644
index 18d1e04ac..000000000
--- a/dom/system/gonk/MozMtpStorage.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozmtpstorage_h__
-#define mozilla_system_mozmtpstorage_h__
-
-#include "MozMtpCommon.h"
-
-#include "mozilla/UniquePtr.h"
-
-#include "Volume.h"
-
-BEGIN_MTP_NAMESPACE
-using namespace android;
-
-class MozMtpServer;
-
-class MozMtpStorage : public Volume::EventObserver
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpStorage)
-
- MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer);
-
- typedef nsTArray<RefPtr<MozMtpStorage> > Array;
-
-private:
- virtual ~MozMtpStorage();
- virtual void Notify(Volume* const& aEvent);
-
- void StorageAvailable();
- void StorageUnavailable();
-
- RefPtr<MozMtpServer> mMozMtpServer;
- UniquePtr<MtpStorage> mMtpStorage;
- RefPtr<Volume> mVolume;
- MtpStorageID mStorageID;
-};
-
-END_MTP_NAMESPACE
-
-#endif // mozilla_system_mozmtpstorage_h__
-
-
diff --git a/dom/system/gonk/NetIdManager.cpp b/dom/system/gonk/NetIdManager.cpp
deleted file mode 100644
index 510ec8b22..000000000
--- a/dom/system/gonk/NetIdManager.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NetIdManager.h"
-
-NetIdManager::NetIdManager()
- : mNextNetId(MIN_NET_ID)
-{
-}
-
-int NetIdManager::getNextNetId()
-{
- // Modified from
- // http://androidxref.com/5.0.0_r2/xref/frameworks/base/services/
- // core/java/com/android/server/ConnectivityService.java#764
-
- int netId = mNextNetId;
- if (++mNextNetId > MAX_NET_ID) {
- mNextNetId = MIN_NET_ID;
- }
-
- return netId;
-}
-
-void NetIdManager::acquire(const nsString& aInterfaceName,
- NetIdInfo* aNetIdInfo)
-{
- // Lookup or create one.
- if (!mInterfaceToNetIdHash.Get(aInterfaceName, aNetIdInfo)) {
- aNetIdInfo->mNetId = getNextNetId();
- aNetIdInfo->mRefCnt = 1;
- } else {
- aNetIdInfo->mRefCnt++;
- }
-
- // Update hash and return.
- mInterfaceToNetIdHash.Put(aInterfaceName, *aNetIdInfo);
-
- return;
-}
-
-bool NetIdManager::lookup(const nsString& aInterfaceName,
- NetIdInfo* aNetIdInfo)
-{
- return mInterfaceToNetIdHash.Get(aInterfaceName, aNetIdInfo);
-}
-
-bool NetIdManager::release(const nsString& aInterfaceName,
- NetIdInfo* aNetIdInfo)
-{
- if (!mInterfaceToNetIdHash.Get(aInterfaceName, aNetIdInfo)) {
- return false; // No such key.
- }
-
- aNetIdInfo->mRefCnt--;
-
- // Update the hash if still be referenced.
- if (aNetIdInfo->mRefCnt > 0) {
- mInterfaceToNetIdHash.Put(aInterfaceName, *aNetIdInfo);
- return true;
- }
-
- // No longer be referenced. Remove the entry.
- mInterfaceToNetIdHash.Remove(aInterfaceName);
-
- return true;
-} \ No newline at end of file
diff --git a/dom/system/gonk/NetIdManager.h b/dom/system/gonk/NetIdManager.h
deleted file mode 100644
index e35d0ecd2..000000000
--- a/dom/system/gonk/NetIdManager.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef NetIdManager_h
-#define NetIdManager_h
-
-#include "nsString.h"
-#include "nsDataHashtable.h"
-
-// NetId is a logical network identifier defined by netd.
-// A network is typically a physical one (i.e. PhysicalNetwork.cpp)
-// for netd but it could be a virtual network as well.
-// We currently use physical network only and use one-to-one
-// network-interface mapping.
-
-class NetIdManager {
-public:
- // keep in sync with system/netd/NetworkController.cpp
- enum {
- MIN_NET_ID = 100,
- MAX_NET_ID = 65535,
- };
-
- // We need to count the number of references since different
- // application like data and mms may use the same interface.
- struct NetIdInfo {
- int mNetId;
- int mRefCnt;
- };
-
-public:
- NetIdManager();
-
- bool lookup(const nsString& aInterfaceName, NetIdInfo* aNetIdInfo);
- void acquire(const nsString& aInterfaceName, NetIdInfo* aNetIdInfo);
- bool release(const nsString& aInterfaceName, NetIdInfo* aNetIdInfo);
-
-private:
- int getNextNetId();
- int mNextNetId;
- nsDataHashtable<nsStringHashKey, NetIdInfo> mInterfaceToNetIdHash;
-};
-
-#endif \ No newline at end of file
diff --git a/dom/system/gonk/NetworkInterfaceListService.js b/dom/system/gonk/NetworkInterfaceListService.js
deleted file mode 100644
index 62fe046aa..000000000
--- a/dom/system/gonk/NetworkInterfaceListService.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const NETWORKLISTSERVICE_CONTRACTID =
- "@mozilla.org/network/interface-list-service;1";
-const NETWORKLISTSERVICE_CID =
- Components.ID("{3780be6e-7012-4e53-ade6-15212fb88a0d}");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsISyncMessageSender");
-
-function NetworkInterfaceListService () {
-}
-
-NetworkInterfaceListService.prototype = {
- classID: NETWORKLISTSERVICE_CID,
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterfaceListService]),
-
- getDataInterfaceList: function(aConditions) {
- return new NetworkInterfaceList(
- cpmm.sendSyncMessage(
- 'NetworkInterfaceList:ListInterface',
- {
- excludeSupl: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_SUPL_INTERFACES) != 0,
- excludeMms: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_MMS_INTERFACES) != 0,
- excludeIms: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_IMS_INTERFACES) != 0,
- excludeDun: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_DUN_INTERFACES) != 0,
- excludeFota: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_FOTA_INTERFACES) != 0
- }
- )[0]);
- }
-};
-
-function FakeNetworkInfo(aAttributes) {
- this.state = aAttributes.state;
- this.type = aAttributes.type;
- this.name = aAttributes.name;
- this.ips = aAttributes.ips;
- this.prefixLengths = aAttributes.prefixLengths;
- this.gateways = aAttributes.gateways;
- this.dnses = aAttributes.dnses;
-}
-FakeNetworkInfo.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]),
-
- getAddresses: function (ips, prefixLengths) {
- ips.value = this.ips.slice();
- prefixLengths.value = this.prefixLengths.slice();
-
- return this.ips.length;
- },
-
- getGateways: function (count) {
- if (count) {
- count.value = this.gateways.length;
- }
- return this.gateways.slice();
- },
-
- getDnses: function (count) {
- if (count) {
- count.value = this.dnses.length;
- }
- return this.dnses.slice();
- }
-};
-
-function NetworkInterfaceList (aInterfaceLiterals) {
- this._interfaces = [];
- for (let entry of aInterfaceLiterals) {
- this._interfaces.push(new FakeNetworkInfo(entry));
- }
-}
-
-NetworkInterfaceList.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterfaceList]),
-
- getNumberOfInterface: function() {
- return this._interfaces.length;
- },
-
- getInterfaceInfo: function(index) {
- if (!this._interfaces) {
- return null;
- }
- return this._interfaces[index];
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkInterfaceListService]);
-
diff --git a/dom/system/gonk/NetworkInterfaceListService.manifest b/dom/system/gonk/NetworkInterfaceListService.manifest
deleted file mode 100644
index a827e778f..000000000
--- a/dom/system/gonk/NetworkInterfaceListService.manifest
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2012 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# NetworkInterfaceListService.js
-component {3780be6e-7012-4e53-ade6-15212fb88a0d} NetworkInterfaceListService.js
-contract @mozilla.org/network/interface-list-service;1 {3780be6e-7012-4e53-ade6-15212fb88a0d}
diff --git a/dom/system/gonk/NetworkManager.js b/dom/system/gonk/NetworkManager.js
deleted file mode 100644
index 9d7a5683e..000000000
--- a/dom/system/gonk/NetworkManager.js
+++ /dev/null
@@ -1,1219 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-const NETWORKMANAGER_CONTRACTID = "@mozilla.org/network/manager;1";
-const NETWORKMANAGER_CID =
- Components.ID("{1ba9346b-53b5-4660-9dc6-58f0b258d0a6}");
-
-const DEFAULT_PREFERRED_NETWORK_TYPE = Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET;
-
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
- return Cc["@mozilla.org/parentprocessmessagemanager;1"]
- .getService(Ci.nsIMessageBroadcaster);
-});
-
-XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
- "@mozilla.org/network/dns-service;1",
- "nsIDNSService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gTetheringService",
- "@mozilla.org/tethering/service;1",
- "nsITetheringService");
-
-const TOPIC_INTERFACE_REGISTERED = "network-interface-registered";
-const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
-const TOPIC_ACTIVE_CHANGED = "network-active-changed";
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const PREF_MANAGE_OFFLINE_STATUS = "network.gonk.manage-offline-status";
-const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
-
-const IPV4_ADDRESS_ANY = "0.0.0.0";
-const IPV6_ADDRESS_ANY = "::0";
-
-const IPV4_MAX_PREFIX_LENGTH = 32;
-const IPV6_MAX_PREFIX_LENGTH = 128;
-
-// Connection Type for Network Information API
-const CONNECTION_TYPE_CELLULAR = 0;
-const CONNECTION_TYPE_BLUETOOTH = 1;
-const CONNECTION_TYPE_ETHERNET = 2;
-const CONNECTION_TYPE_WIFI = 3;
-const CONNECTION_TYPE_OTHER = 4;
-const CONNECTION_TYPE_NONE = 5;
-
-const MANUAL_PROXY_CONFIGURATION = 1;
-
-var debug;
-function updateDebug() {
- let debugPref = false; // set default value here.
- try {
- debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
- } catch (e) {}
-
- if (debugPref) {
- debug = function(s) {
- dump("-*- NetworkManager: " + s + "\n");
- };
- } else {
- debug = function(s) {};
- }
-}
-updateDebug();
-
-function defineLazyRegExp(obj, name, pattern) {
- obj.__defineGetter__(name, function() {
- delete obj[name];
- return obj[name] = new RegExp(pattern);
- });
-}
-
-function ExtraNetworkInfo(aNetwork) {
- let ips = {};
- let prefixLengths = {};
- aNetwork.info.getAddresses(ips, prefixLengths);
-
- this.state = aNetwork.info.state;
- this.type = aNetwork.info.type;
- this.name = aNetwork.info.name;
- this.ips = ips.value;
- this.prefixLengths = prefixLengths.value;
- this.gateways = aNetwork.info.getGateways();
- this.dnses = aNetwork.info.getDnses();
- this.httpProxyHost = aNetwork.httpProxyHost;
- this.httpProxyPort = aNetwork.httpProxyPort;
- this.mtu = aNetwork.mtu;
-}
-ExtraNetworkInfo.prototype = {
- getAddresses: function(aIps, aPrefixLengths) {
- aIps.value = this.ips.slice();
- aPrefixLengths.value = this.prefixLengths.slice();
-
- return this.ips.length;
- },
-
- getGateways: function(aCount) {
- if (aCount) {
- aCount.value = this.gateways.length;
- }
-
- return this.gateways.slice();
- },
-
- getDnses: function(aCount) {
- if (aCount) {
- aCount.value = this.dnses.length;
- }
-
- return this.dnses.slice();
- }
-};
-
-function NetworkInterfaceLinks()
-{
- this.resetLinks();
-}
-NetworkInterfaceLinks.prototype = {
- linkRoutes: null,
- gateways: null,
- interfaceName: null,
- extraRoutes: null,
-
- setLinks: function(linkRoutes, gateways, interfaceName) {
- this.linkRoutes = linkRoutes;
- this.gateways = gateways;
- this.interfaceName = interfaceName;
- },
-
- resetLinks: function() {
- this.linkRoutes = [];
- this.gateways = [];
- this.interfaceName = "";
- this.extraRoutes = [];
- },
-
- compareGateways: function(gateways) {
- if (this.gateways.length != gateways.length) {
- return false;
- }
-
- for (let i = 0; i < this.gateways.length; i++) {
- if (this.gateways[i] != gateways[i]) {
- return false;
- }
- }
-
- return true;
- }
-};
-
-/**
- * This component watches for network interfaces changing state and then
- * adjusts routes etc. accordingly.
- */
-function NetworkManager() {
- this.networkInterfaces = {};
- this.networkInterfaceLinks = {};
-
- try {
- this._manageOfflineStatus =
- Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
- } catch(ex) {
- // Ignore.
- }
- Services.prefs.addObserver(PREF_MANAGE_OFFLINE_STATUS, this, false);
- Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
-
- this.setAndConfigureActive();
-
- ppmm.addMessageListener('NetworkInterfaceList:ListInterface', this);
-
- // Used in resolveHostname().
- defineLazyRegExp(this, "REGEXP_IPV4", "^\\d{1,3}(?:\\.\\d{1,3}){3}$");
- defineLazyRegExp(this, "REGEXP_IPV6", "^[\\da-fA-F]{4}(?::[\\da-fA-F]{4}){7}$");
-}
-NetworkManager.prototype = {
- classID: NETWORKMANAGER_CID,
- classInfo: XPCOMUtils.generateCI({classID: NETWORKMANAGER_CID,
- contractID: NETWORKMANAGER_CONTRACTID,
- classDescription: "Network Manager",
- interfaces: [Ci.nsINetworkManager]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkManager,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- // nsIObserver
-
- observe: function(subject, topic, data) {
- switch (topic) {
- case TOPIC_PREF_CHANGED:
- if (data === PREF_NETWORK_DEBUG_ENABLED) {
- updateDebug();
- } else if (data === PREF_MANAGE_OFFLINE_STATUS) {
- this._manageOfflineStatus =
- Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
- debug(PREF_MANAGE_OFFLINE_STATUS + " has changed to " + this._manageOfflineStatus);
- }
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- Services.prefs.removeObserver(PREF_MANAGE_OFFLINE_STATUS, this);
- Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
- break;
- }
- },
-
- receiveMessage: function(aMsg) {
- switch (aMsg.name) {
- case "NetworkInterfaceList:ListInterface": {
- let excludeMms = aMsg.json.excludeMms;
- let excludeSupl = aMsg.json.excludeSupl;
- let excludeIms = aMsg.json.excludeIms;
- let excludeDun = aMsg.json.excludeDun;
- let excludeFota = aMsg.json.excludeFota;
- let interfaces = [];
-
- for (let key in this.networkInterfaces) {
- let network = this.networkInterfaces[key];
- let i = network.info;
- if ((i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS && excludeMms) ||
- (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL && excludeSupl) ||
- (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS && excludeIms) ||
- (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN && excludeDun) ||
- (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA && excludeFota)) {
- continue;
- }
-
- let ips = {};
- let prefixLengths = {};
- i.getAddresses(ips, prefixLengths);
-
- interfaces.push({
- state: i.state,
- type: i.type,
- name: i.name,
- ips: ips.value,
- prefixLengths: prefixLengths.value,
- gateways: i.getGateways(),
- dnses: i.getDnses()
- });
- }
- return interfaces;
- }
- }
- },
-
- getNetworkId: function(aNetworkInfo) {
- let id = "device";
- try {
- if (aNetworkInfo instanceof Ci.nsIRilNetworkInfo) {
- let rilInfo = aNetworkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
- id = "ril" + rilInfo.serviceId;
- }
- } catch (e) {}
-
- return id + "-" + aNetworkInfo.type;
- },
-
- // nsINetworkManager
-
- registerNetworkInterface: function(network) {
- if (!(network instanceof Ci.nsINetworkInterface)) {
- throw Components.Exception("Argument must be nsINetworkInterface.",
- Cr.NS_ERROR_INVALID_ARG);
- }
- let networkId = this.getNetworkId(network.info);
- if (networkId in this.networkInterfaces) {
- throw Components.Exception("Network with that type already registered!",
- Cr.NS_ERROR_INVALID_ARG);
- }
- this.networkInterfaces[networkId] = network;
- this.networkInterfaceLinks[networkId] = new NetworkInterfaceLinks();
-
- Services.obs.notifyObservers(network.info, TOPIC_INTERFACE_REGISTERED, null);
- debug("Network '" + networkId + "' registered.");
- },
-
- _addSubnetRoutes: function(network) {
- let ips = {};
- let prefixLengths = {};
- let length = network.getAddresses(ips, prefixLengths);
- let promises = [];
-
- for (let i = 0; i < length; i++) {
- debug('Adding subnet routes: ' + ips.value[i] + '/' + prefixLengths.value[i]);
- promises.push(
- gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_ADD,
- network.name, ips.value[i], prefixLengths.value[i])
- .catch(aError => {
- debug("_addSubnetRoutes error: " + aError);
- }));
- }
-
- return Promise.all(promises);
- },
-
- updateNetworkInterface: function(network) {
- if (!(network instanceof Ci.nsINetworkInterface)) {
- throw Components.Exception("Argument must be nsINetworkInterface.",
- Cr.NS_ERROR_INVALID_ARG);
- }
- let networkId = this.getNetworkId(network.info);
- if (!(networkId in this.networkInterfaces)) {
- throw Components.Exception("No network with that type registered.",
- Cr.NS_ERROR_INVALID_ARG);
- }
- debug("Network " + network.info.type + "/" + network.info.name +
- " changed state to " + network.info.state);
-
- // Keep a copy of network in case it is modified while we are updating.
- let extNetworkInfo = new ExtraNetworkInfo(network);
-
- // Note that since Lollipop we need to allocate and initialize
- // something through netd, so we add createNetwork/destroyNetwork
- // to deal with that explicitly.
-
- switch (extNetworkInfo.state) {
- case Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED:
-
- this._createNetwork(extNetworkInfo.name)
- // Remove pre-created default route and let setAndConfigureActive()
- // to set default route only on preferred network
- .then(() => this._removeDefaultRoute(extNetworkInfo))
- // Set DNS server as early as possible to prevent from
- // premature domain name lookup.
- .then(() => this._setDNS(extNetworkInfo))
- .then(() => {
- // Add host route for data calls
- if (!this.isNetworkTypeMobile(extNetworkInfo.type)) {
- return;
- }
-
- let currentInterfaceLinks = this.networkInterfaceLinks[networkId];
- let newLinkRoutes = extNetworkInfo.getDnses().concat(
- extNetworkInfo.httpProxyHost);
- // If gateways have changed, remove all old routes first.
- return this._handleGateways(networkId, extNetworkInfo.getGateways())
- .then(() => this._updateRoutes(currentInterfaceLinks.linkRoutes,
- newLinkRoutes,
- extNetworkInfo.getGateways(),
- extNetworkInfo.name))
- .then(() => currentInterfaceLinks.setLinks(newLinkRoutes,
- extNetworkInfo.getGateways(),
- extNetworkInfo.name));
- })
- .then(() => {
- if (extNetworkInfo.type !=
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
- return;
- }
- // Dun type is a special case where we add the default route to a
- // secondary table.
- return this.setSecondaryDefaultRoute(extNetworkInfo);
- })
- .then(() => this._addSubnetRoutes(extNetworkInfo))
- .then(() => {
- if (extNetworkInfo.mtu <= 0) {
- return;
- }
-
- return this._setMtu(extNetworkInfo);
- })
- .then(() => this.setAndConfigureActive())
- .then(() => {
- // Update data connection when Wifi connected/disconnected
- if (extNetworkInfo.type ==
- Ci.nsINetworkInfo.NETWORK_TYPE_WIFI && this.mRil) {
- for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
- this.mRil.getRadioInterface(i).updateRILNetworkInterface();
- }
- }
-
- // Probing the public network accessibility after routing table is ready
- CaptivePortalDetectionHelper
- .notify(CaptivePortalDetectionHelper.EVENT_CONNECT,
- this.activeNetworkInfo);
- })
- .then(() => {
- // Notify outer modules like MmsService to start the transaction after
- // the configuration of the network interface is done.
- Services.obs.notifyObservers(network.info,
- TOPIC_CONNECTION_STATE_CHANGED,
- this.convertConnectionType(network.info));
- })
- .catch(aError => {
- debug("updateNetworkInterface error: " + aError);
- });
- break;
- case Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED:
- Promise.resolve()
- .then(() => {
- if (!this.isNetworkTypeMobile(extNetworkInfo.type)) {
- return;
- }
- // Remove host route for data calls
- return this._cleanupAllHostRoutes(networkId);
- })
- .then(() => {
- if (extNetworkInfo.type !=
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
- return;
- }
- // Remove secondary default route for dun.
- return this.removeSecondaryDefaultRoute(extNetworkInfo);
- })
- .then(() => {
- if (extNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI ||
- extNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_ETHERNET) {
- // Remove routing table in /proc/net/route
- return this._resetRoutingTable(extNetworkInfo.name);
- }
- if (extNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) {
- return this._removeDefaultRoute(extNetworkInfo)
- }
- })
- .then(() => {
- // Clear http proxy on active network.
- if (this.activeNetworkInfo &&
- extNetworkInfo.type == this.activeNetworkInfo.type) {
- this.clearNetworkProxy();
- }
-
- // Abort ongoing captive portal detection on the wifi interface
- CaptivePortalDetectionHelper
- .notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, extNetworkInfo);
- })
- .then(() => this.setAndConfigureActive())
- .then(() => {
- // Update data connection when Wifi connected/disconnected
- if (extNetworkInfo.type ==
- Ci.nsINetworkInfo.NETWORK_TYPE_WIFI && this.mRil) {
- for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
- this.mRil.getRadioInterface(i).updateRILNetworkInterface();
- }
- }
- })
- .then(() => this._destroyNetwork(extNetworkInfo.name))
- .then(() => {
- // Notify outer modules like MmsService to start the transaction after
- // the configuration of the network interface is done.
- Services.obs.notifyObservers(network.info,
- TOPIC_CONNECTION_STATE_CHANGED,
- this.convertConnectionType(network.info));
- })
- .catch(aError => {
- debug("updateNetworkInterface error: " + aError);
- });
- break;
- }
- },
-
- unregisterNetworkInterface: function(network) {
- if (!(network instanceof Ci.nsINetworkInterface)) {
- throw Components.Exception("Argument must be nsINetworkInterface.",
- Cr.NS_ERROR_INVALID_ARG);
- }
- let networkId = this.getNetworkId(network.info);
- if (!(networkId in this.networkInterfaces)) {
- throw Components.Exception("No network with that type registered.",
- Cr.NS_ERROR_INVALID_ARG);
- }
-
- // This is for in case a network gets unregistered without being
- // DISCONNECTED.
- if (this.isNetworkTypeMobile(network.info.type)) {
- this._cleanupAllHostRoutes(networkId);
- }
-
- delete this.networkInterfaces[networkId];
-
- Services.obs.notifyObservers(network.info, TOPIC_INTERFACE_UNREGISTERED, null);
- debug("Network '" + networkId + "' unregistered.");
- },
-
- _manageOfflineStatus: true,
-
- networkInterfaces: null,
-
- networkInterfaceLinks: null,
-
- _networkTypePriorityList: [Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET,
- Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
- Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE],
- get networkTypePriorityList() {
- return this._networkTypePriorityList;
- },
- set networkTypePriorityList(val) {
- if (val.length != this._networkTypePriorityList.length) {
- throw "Priority list length should equal to " +
- this._networkTypePriorityList.length;
- }
-
- // Check if types in new priority list are valid and also make sure there
- // are no duplicate types.
- let list = [Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET,
- Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
- Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE];
- while (list.length) {
- let type = list.shift();
- if (val.indexOf(type) == -1) {
- throw "There is missing network type";
- }
- }
-
- this._networkTypePriorityList = val;
- },
-
- getPriority: function(type) {
- if (this._networkTypePriorityList.indexOf(type) == -1) {
- // 0 indicates the lowest priority.
- return 0;
- }
-
- return this._networkTypePriorityList.length -
- this._networkTypePriorityList.indexOf(type);
- },
-
- get allNetworkInfo() {
- let allNetworkInfo = {};
-
- for (let networkId in this.networkInterfaces) {
- if (this.networkInterfaces.hasOwnProperty(networkId)) {
- allNetworkInfo[networkId] = this.networkInterfaces[networkId].info;
- }
- }
-
- return allNetworkInfo;
- },
-
- _preferredNetworkType: DEFAULT_PREFERRED_NETWORK_TYPE,
- get preferredNetworkType() {
- return this._preferredNetworkType;
- },
- set preferredNetworkType(val) {
- if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
- Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
- Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET].indexOf(val) == -1) {
- throw "Invalid network type";
- }
- this._preferredNetworkType = val;
- },
-
- _activeNetwork: null,
-
- get activeNetworkInfo() {
- return this._activeNetwork && this._activeNetwork.info;
- },
-
- _overriddenActive: null,
-
- overrideActive: function(network) {
- if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
- Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
- Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET].indexOf(val) == -1) {
- throw "Invalid network type";
- }
-
- this._overriddenActive = network;
- this.setAndConfigureActive();
- },
-
- _updateRoutes: function(oldLinks, newLinks, gateways, interfaceName) {
- // Returns items that are in base but not in target.
- function getDifference(base, target) {
- return base.filter(function(i) { return target.indexOf(i) < 0; });
- }
-
- let addedLinks = getDifference(newLinks, oldLinks);
- let removedLinks = getDifference(oldLinks, newLinks);
-
- if (addedLinks.length === 0 && removedLinks.length === 0) {
- return Promise.resolve();
- }
-
- return this._setHostRoutes(false, removedLinks, interfaceName, gateways)
- .then(this._setHostRoutes(true, addedLinks, interfaceName, gateways));
- },
-
- _setHostRoutes: function(doAdd, ipAddresses, networkName, gateways) {
- let getMaxPrefixLength = (aIp) => {
- return aIp.match(this.REGEXP_IPV4) ? IPV4_MAX_PREFIX_LENGTH : IPV6_MAX_PREFIX_LENGTH;
- }
-
- let promises = [];
-
- ipAddresses.forEach((aIpAddress) => {
- let gateway = this.selectGateway(gateways, aIpAddress);
- if (gateway) {
- promises.push((doAdd)
- ? gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_ADD,
- networkName, aIpAddress,
- getMaxPrefixLength(aIpAddress), gateway)
- : gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_REMOVE,
- networkName, aIpAddress,
- getMaxPrefixLength(aIpAddress), gateway));
- }
- });
-
- return Promise.all(promises);
- },
-
- isValidatedNetwork: function(aNetworkInfo) {
- let isValid = false;
- try {
- isValid = (this.getNetworkId(aNetworkInfo) in this.networkInterfaces);
- } catch (e) {
- debug("Invalid network interface: " + e);
- }
-
- return isValid;
- },
-
- addHostRoute: function(aNetworkInfo, aHost) {
- if (!this.isValidatedNetwork(aNetworkInfo)) {
- return Promise.reject("Invalid network info.");
- }
-
- return this.resolveHostname(aNetworkInfo, aHost)
- .then((ipAddresses) => {
- let promises = [];
- let networkId = this.getNetworkId(aNetworkInfo);
-
- ipAddresses.forEach((aIpAddress) => {
- let promise =
- this._setHostRoutes(true, [aIpAddress], aNetworkInfo.name, aNetworkInfo.getGateways())
- .then(() => this.networkInterfaceLinks[networkId].extraRoutes.push(aIpAddress));
-
- promises.push(promise);
- });
-
- return Promise.all(promises);
- });
- },
-
- removeHostRoute: function(aNetworkInfo, aHost) {
- if (!this.isValidatedNetwork(aNetworkInfo)) {
- return Promise.reject("Invalid network info.");
- }
-
- return this.resolveHostname(aNetworkInfo, aHost)
- .then((ipAddresses) => {
- let promises = [];
- let networkId = this.getNetworkId(aNetworkInfo);
-
- ipAddresses.forEach((aIpAddress) => {
- let found = this.networkInterfaceLinks[networkId].extraRoutes.indexOf(aIpAddress);
- if (found < 0) {
- return; // continue
- }
-
- let promise =
- this._setHostRoutes(false, [aIpAddress], aNetworkInfo.name, aNetworkInfo.getGateways())
- .then(() => {
- this.networkInterfaceLinks[networkId].extraRoutes.splice(found, 1);
- }, () => {
- // We should remove it even if the operation failed.
- this.networkInterfaceLinks[networkId].extraRoutes.splice(found, 1);
- });
- promises.push(promise);
- });
-
- return Promise.all(promises);
- });
- },
-
- isNetworkTypeSecondaryMobile: function(type) {
- return (type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS ||
- type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL ||
- type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS ||
- type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN ||
- type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA);
- },
-
- isNetworkTypeMobile: function(type) {
- return (type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE ||
- this.isNetworkTypeSecondaryMobile(type));
- },
-
- _handleGateways: function(networkId, gateways) {
- let currentNetworkLinks = this.networkInterfaceLinks[networkId];
- if (currentNetworkLinks.gateways.length == 0 ||
- currentNetworkLinks.compareGateways(gateways)) {
- return Promise.resolve();
- }
-
- let currentExtraRoutes = currentNetworkLinks.extraRoutes;
- return this._cleanupAllHostRoutes(networkId)
- .then(() => {
- // If gateways have changed, re-add extra host routes with new gateways.
- if (currentExtraRoutes.length > 0) {
- this._setHostRoutes(true,
- currentExtraRoutes,
- currentNetworkLinks.interfaceName,
- gateways)
- .then(() => {
- currentNetworkLinks.extraRoutes = currentExtraRoutes;
- });
- }
- });
- },
-
- _cleanupAllHostRoutes: function(networkId) {
- let currentNetworkLinks = this.networkInterfaceLinks[networkId];
- let hostRoutes = currentNetworkLinks.linkRoutes.concat(
- currentNetworkLinks.extraRoutes);
-
- if (hostRoutes.length === 0) {
- return Promise.resolve();
- }
-
- return this._setHostRoutes(false,
- hostRoutes,
- currentNetworkLinks.interfaceName,
- currentNetworkLinks.gateways)
- .catch((aError) => {
- debug("Error (" + aError + ") on _cleanupAllHostRoutes, keep proceeding.");
- })
- .then(() => currentNetworkLinks.resetLinks());
- },
-
- selectGateway: function(gateways, host) {
- for (let i = 0; i < gateways.length; i++) {
- let gateway = gateways[i];
- if (gateway.match(this.REGEXP_IPV4) && host.match(this.REGEXP_IPV4) ||
- gateway.indexOf(":") != -1 && host.indexOf(":") != -1) {
- return gateway;
- }
- }
- return null;
- },
-
- _setSecondaryRoute: function(aDoAdd, aInterfaceName, aRoute) {
- return new Promise((aResolve, aReject) => {
- if (aDoAdd) {
- gNetworkService.addSecondaryRoute(aInterfaceName, aRoute,
- (aSuccess) => {
- if (!aSuccess) {
- aReject("addSecondaryRoute failed");
- return;
- }
- aResolve();
- });
- } else {
- gNetworkService.removeSecondaryRoute(aInterfaceName, aRoute,
- (aSuccess) => {
- if (!aSuccess) {
- debug("removeSecondaryRoute failed")
- }
- // Always resolve.
- aResolve();
- });
- }
- });
- },
-
- setSecondaryDefaultRoute: function(network) {
- let gateways = network.getGateways();
- let promises = [];
-
- for (let i = 0; i < gateways.length; i++) {
- let isIPv6 = (gateways[i].indexOf(":") != -1) ? true : false;
- // First, we need to add a host route to the gateway in the secondary
- // routing table to make the gateway reachable. Host route takes the max
- // prefix and gateway address 'any'.
- let hostRoute = {
- ip: gateways[i],
- prefix: isIPv6 ? IPV6_MAX_PREFIX_LENGTH : IPV4_MAX_PREFIX_LENGTH,
- gateway: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY
- };
- // Now we can add the default route through gateway. Default route takes the
- // min prefix and destination ip 'any'.
- let defaultRoute = {
- ip: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY,
- prefix: 0,
- gateway: gateways[i]
- };
-
- let promise = this._setSecondaryRoute(true, network.name, hostRoute)
- .then(() => this._setSecondaryRoute(true, network.name, defaultRoute));
-
- promises.push(promise);
- }
-
- return Promise.all(promises);
- },
-
- removeSecondaryDefaultRoute: function(network) {
- let gateways = network.getGateways();
- let promises = [];
-
- for (let i = 0; i < gateways.length; i++) {
- let isIPv6 = (gateways[i].indexOf(":") != -1) ? true : false;
- // Remove both default route and host route.
- let defaultRoute = {
- ip: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY,
- prefix: 0,
- gateway: gateways[i]
- };
- let hostRoute = {
- ip: gateways[i],
- prefix: isIPv6 ? IPV6_MAX_PREFIX_LENGTH : IPV4_MAX_PREFIX_LENGTH,
- gateway: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY
- };
-
- let promise = this._setSecondaryRoute(false, network.name, defaultRoute)
- .then(() => this._setSecondaryRoute(false, network.name, hostRoute));
-
- promises.push(promise);
- }
-
- return Promise.all(promises);
- },
-
- /**
- * Determine the active interface and configure it.
- */
- setAndConfigureActive: function() {
- debug("Evaluating whether active network needs to be changed.");
- let oldActive = this._activeNetwork;
-
- if (this._overriddenActive) {
- debug("We have an override for the active network: " +
- this._overriddenActive.info.name);
- // The override was just set, so reconfigure the network.
- if (this._activeNetwork != this._overriddenActive) {
- this._activeNetwork = this._overriddenActive;
- this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
- Services.obs.notifyObservers(this.activeNetworkInfo,
- TOPIC_ACTIVE_CHANGED, null);
- }
- return;
- }
-
- // The active network is already our preferred type.
- if (this.activeNetworkInfo &&
- this.activeNetworkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED &&
- this.activeNetworkInfo.type == this._preferredNetworkType) {
- debug("Active network is already our preferred type.");
- return this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
- }
-
- // Find a suitable network interface to activate.
- this._activeNetwork = null;
- let anyConnected = false;
-
- for (let key in this.networkInterfaces) {
- let network = this.networkInterfaces[key];
- if (network.info.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- continue;
- }
- anyConnected = true;
-
- // Set active only for default connections.
- if (network.info.type != Ci.nsINetworkInfo.NETWORK_TYPE_WIFI &&
- network.info.type != Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE &&
- network.info.type != Ci.nsINetworkInfo.NETWORK_TYPE_ETHERNET) {
- continue;
- }
-
- if (network.info.type == this.preferredNetworkType) {
- this._activeNetwork = network;
- debug("Found our preferred type of network: " + network.info.name);
- break;
- }
-
- // Initialize the active network with the first connected network.
- if (!this._activeNetwork) {
- this._activeNetwork = network;
- continue;
- }
-
- // Compare the prioriy between two network types. If found incoming
- // network with higher priority, replace the active network.
- if (this.getPriority(this._activeNetwork.type) < this.getPriority(network.type)) {
- this._activeNetwork = network;
- }
- }
-
- return Promise.resolve()
- .then(() => {
- if (!this._activeNetwork) {
- return Promise.resolve();
- }
-
- return this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
- })
- .then(() => {
- if (this._activeNetwork != oldActive) {
- Services.obs.notifyObservers(this.activeNetworkInfo,
- TOPIC_ACTIVE_CHANGED, null);
- }
-
- if (this._manageOfflineStatus) {
- Services.io.offline = !anyConnected &&
- (gTetheringService.state ===
- Ci.nsITetheringService.TETHERING_STATE_INACTIVE);
- }
- });
- },
-
- resolveHostname: function(aNetworkInfo, aHostname) {
- // Sanity check for null, undefined and empty string... etc.
- if (!aHostname) {
- return Promise.reject(new Error("hostname is empty: " + aHostname));
- }
-
- if (aHostname.match(this.REGEXP_IPV4) ||
- aHostname.match(this.REGEXP_IPV6)) {
- return Promise.resolve([aHostname]);
- }
-
- // Wrap gDNSService.asyncResolveExtended to a promise, which
- // resolves with an array of ip addresses or rejects with
- // the reason otherwise.
- let hostResolveWrapper = aNetId => {
- return new Promise((aResolve, aReject) => {
- // Callback for gDNSService.asyncResolveExtended.
- let onLookupComplete = (aRequest, aRecord, aStatus) => {
- if (!Components.isSuccessCode(aStatus)) {
- aReject(new Error("Failed to resolve '" + aHostname +
- "', with status: " + aStatus));
- return;
- }
-
- let retval = [];
- while (aRecord.hasMore()) {
- retval.push(aRecord.getNextAddrAsString());
- }
-
- if (!retval.length) {
- aReject(new Error("No valid address after DNS lookup!"));
- return;
- }
-
- debug("hostname is resolved: " + aHostname);
- debug("Addresses: " + JSON.stringify(retval));
-
- aResolve(retval);
- };
-
- debug('Calling gDNSService.asyncResolveExtended: ' + aNetId + ', ' + aHostname);
- gDNSService.asyncResolveExtended(aHostname,
- 0,
- aNetId,
- onLookupComplete,
- Services.tm.mainThread);
- });
- };
-
- // TODO: |getNetId| will be implemented as a sync call in nsINetworkManager
- // once Bug 1141903 is landed.
- return gNetworkService.getNetId(aNetworkInfo.name)
- .then(aNetId => hostResolveWrapper(aNetId));
- },
-
- convertConnectionType: function(aNetworkInfo) {
- // If there is internal interface change (e.g., MOBILE_MMS, MOBILE_SUPL),
- // the function will return null so that it won't trigger type change event
- // in NetworkInformation API.
- if (aNetworkInfo.type != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI &&
- aNetworkInfo.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE &&
- aNetworkInfo.type != Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET) {
- return null;
- }
-
- if (aNetworkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED) {
- return CONNECTION_TYPE_NONE;
- }
-
- switch (aNetworkInfo.type) {
- case Ci.nsINetworkInfo.NETWORK_TYPE_WIFI:
- return CONNECTION_TYPE_WIFI;
- case Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE:
- return CONNECTION_TYPE_CELLULAR;
- case Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET:
- return CONNECTION_TYPE_ETHERNET;
- }
- },
-
- _setDNS: function(aNetworkInfo) {
- return new Promise((aResolve, aReject) => {
- let dnses = aNetworkInfo.getDnses();
- let gateways = aNetworkInfo.getGateways();
- gNetworkService.setDNS(aNetworkInfo.name, dnses.length, dnses,
- gateways.length, gateways, (aError) => {
- if (aError) {
- aReject("setDNS failed");
- return;
- }
- aResolve();
- });
- });
- },
-
- _setMtu: function(aNetworkInfo) {
- return new Promise((aResolve, aReject) => {
- gNetworkService.setMtu(aNetworkInfo.name, aNetworkInfo.mtu, (aSuccess) => {
- if (!aSuccess) {
- debug("setMtu failed");
- }
- // Always resolve.
- aResolve();
- });
- });
- },
-
- _createNetwork: function(aInterfaceName) {
- return new Promise((aResolve, aReject) => {
- gNetworkService.createNetwork(aInterfaceName, (aSuccess) => {
- if (!aSuccess) {
- aReject("createNetwork failed");
- return;
- }
- aResolve();
- });
- });
- },
-
- _destroyNetwork: function(aInterfaceName) {
- return new Promise((aResolve, aReject) => {
- gNetworkService.destroyNetwork(aInterfaceName, (aSuccess) => {
- if (!aSuccess) {
- debug("destroyNetwork failed")
- }
- // Always resolve.
- aResolve();
- });
- });
- },
-
- _resetRoutingTable: function(aInterfaceName) {
- return new Promise((aResolve, aReject) => {
- gNetworkService.resetRoutingTable(aInterfaceName, (aSuccess) => {
- if (!aSuccess) {
- debug("resetRoutingTable failed");
- }
- // Always resolve.
- aResolve();
- });
- });
- },
-
- _removeDefaultRoute: function(aNetworkInfo) {
- return new Promise((aResolve, aReject) => {
- let gateways = aNetworkInfo.getGateways();
- gNetworkService.removeDefaultRoute(aNetworkInfo.name, gateways.length,
- gateways, (aSuccess) => {
- if (!aSuccess) {
- debug("removeDefaultRoute failed");
- }
- // Always resolve.
- aResolve();
- });
- });
- },
-
- _setDefaultRouteAndProxy: function(aNetwork, aOldNetwork) {
- if (aOldNetwork) {
- return this._removeDefaultRoute(aOldNetwork.info)
- .then(() => this._setDefaultRouteAndProxy(aNetwork, null));
- }
-
- return new Promise((aResolve, aReject) => {
- let networkInfo = aNetwork.info;
- let gateways = networkInfo.getGateways();
-
- gNetworkService.setDefaultRoute(networkInfo.name, gateways.length, gateways,
- (aSuccess) => {
- if (!aSuccess) {
- gNetworkService.destroyNetwork(networkInfo.name, function() {
- aReject("setDefaultRoute failed");
- });
- return;
- }
- this.setNetworkProxy(aNetwork);
- aResolve();
- });
- });
- },
-
- setNetworkProxy: function(aNetwork) {
- try {
- if (!aNetwork.httpProxyHost || aNetwork.httpProxyHost === "") {
- // Sets direct connection to internet.
- this.clearNetworkProxy();
-
- debug("No proxy support for " + aNetwork.info.name + " network interface.");
- return;
- }
-
- debug("Going to set proxy settings for " + aNetwork.info.name + " network interface.");
- // Sets manual proxy configuration.
- Services.prefs.setIntPref("network.proxy.type", MANUAL_PROXY_CONFIGURATION);
-
- // Do not use this proxy server for all protocols.
- Services.prefs.setBoolPref("network.proxy.share_proxy_settings", false);
- Services.prefs.setCharPref("network.proxy.http", aNetwork.httpProxyHost);
- Services.prefs.setCharPref("network.proxy.ssl", aNetwork.httpProxyHost);
- let port = aNetwork.httpProxyPort === 0 ? 8080 : aNetwork.httpProxyPort;
- Services.prefs.setIntPref("network.proxy.http_port", port);
- Services.prefs.setIntPref("network.proxy.ssl_port", port);
- } catch(ex) {
- debug("Exception " + ex + ". Unable to set proxy setting for " +
- aNetwork.info.name + " network interface.");
- }
- },
-
- clearNetworkProxy: function() {
- debug("Going to clear all network proxy.");
-
- Services.prefs.clearUserPref("network.proxy.type");
- Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
- Services.prefs.clearUserPref("network.proxy.http");
- Services.prefs.clearUserPref("network.proxy.http_port");
- Services.prefs.clearUserPref("network.proxy.ssl");
- Services.prefs.clearUserPref("network.proxy.ssl_port");
- },
-};
-
-var CaptivePortalDetectionHelper = (function() {
-
- const EVENT_CONNECT = "Connect";
- const EVENT_DISCONNECT = "Disconnect";
- let _ongoingInterface = null;
- let _available = ("nsICaptivePortalDetector" in Ci);
- let getService = function() {
- return Cc['@mozilla.org/toolkit/captive-detector;1']
- .getService(Ci.nsICaptivePortalDetector);
- };
-
- let _performDetection = function(interfaceName, callback) {
- let capService = getService();
- let capCallback = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
- prepare: function() {
- capService.finishPreparation(interfaceName);
- },
- complete: function(success) {
- _ongoingInterface = null;
- callback(success);
- }
- };
-
- // Abort any unfinished captive portal detection.
- if (_ongoingInterface != null) {
- capService.abort(_ongoingInterface);
- _ongoingInterface = null;
- }
- try {
- capService.checkCaptivePortal(interfaceName, capCallback);
- _ongoingInterface = interfaceName;
- } catch (e) {
- debug('Fail to detect captive portal due to: ' + e.message);
- }
- };
-
- let _abort = function(interfaceName) {
- if (_ongoingInterface !== interfaceName) {
- return;
- }
-
- let capService = getService();
- capService.abort(_ongoingInterface);
- _ongoingInterface = null;
- };
-
- return {
- EVENT_CONNECT: EVENT_CONNECT,
- EVENT_DISCONNECT: EVENT_DISCONNECT,
- notify: function(eventType, network) {
- switch (eventType) {
- case EVENT_CONNECT:
- // perform captive portal detection on wifi interface
- if (_available && network &&
- network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
- _performDetection(network.name, function() {
- // TODO: bug 837600
- // We can disconnect wifi in here if user abort the login procedure.
- });
- }
-
- break;
- case EVENT_DISCONNECT:
- if (_available &&
- network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
- _abort(network.name);
- }
- break;
- }
- }
- };
-}());
-
-XPCOMUtils.defineLazyGetter(NetworkManager.prototype, "mRil", function() {
- try {
- return Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
- } catch (e) {}
-
- return null;
-});
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
diff --git a/dom/system/gonk/NetworkManager.manifest b/dom/system/gonk/NetworkManager.manifest
deleted file mode 100644
index 995fa6559..000000000
--- a/dom/system/gonk/NetworkManager.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-# NetworkManager.js
-component {1ba9346b-53b5-4660-9dc6-58f0b258d0a6} NetworkManager.js
-contract @mozilla.org/network/manager;1 {1ba9346b-53b5-4660-9dc6-58f0b258d0a6}
diff --git a/dom/system/gonk/NetworkService.js b/dom/system/gonk/NetworkService.js
deleted file mode 100644
index 7147f40c7..000000000
--- a/dom/system/gonk/NetworkService.js
+++ /dev/null
@@ -1,862 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
-const NETWORKSERVICE_CID = Components.ID("{48c13741-aec9-4a86-8962-432011708261}");
-
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkWorker",
- "@mozilla.org/network/worker;1",
- "nsINetworkWorker");
-
-// 1xx - Requested action is proceeding
-const NETD_COMMAND_PROCEEDING = 100;
-// 2xx - Requested action has been successfully completed
-const NETD_COMMAND_OKAY = 200;
-// 4xx - The command is accepted but the requested action didn't
-// take place.
-const NETD_COMMAND_FAIL = 400;
-// 5xx - The command syntax or parameters error
-const NETD_COMMAND_ERROR = 500;
-// 6xx - Unsolicited broadcasts
-const NETD_COMMAND_UNSOLICITED = 600;
-
-const WIFI_CTRL_INTERFACE = "wl0.1";
-
-var debug;
-function updateDebug() {
- let debugPref = false; // set default value here.
- try {
- debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
- } catch (e) {}
-
- if (debugPref) {
- debug = function(s) {
- dump("-*- NetworkService: " + s + "\n");
- };
- } else {
- debug = function(s) {};
- }
-}
-updateDebug();
-
-function netdResponseType(aCode) {
- return Math.floor(aCode / 100) * 100;
-}
-
-function isError(aCode) {
- let type = netdResponseType(aCode);
- return (type !== NETD_COMMAND_PROCEEDING && type !== NETD_COMMAND_OKAY);
-}
-
-function Task(aId, aParams, aSetupFunction) {
- this.id = aId;
- this.params = aParams;
- this.setupFunction = aSetupFunction;
-}
-
-function NetworkWorkerRequestQueue(aNetworkService) {
- this.networkService = aNetworkService;
- this.tasks = [];
-}
-NetworkWorkerRequestQueue.prototype = {
- runQueue: function() {
- if (this.tasks.length === 0) {
- return;
- }
-
- let task = this.tasks[0];
- debug("run task id: " + task.id);
-
- if (typeof task.setupFunction === 'function') {
- // If setupFunction returns false, skip sending to Network Worker but call
- // handleWorkerMessage() directly with task id, as if the response was
- // returned from Network Worker.
- if (!task.setupFunction()) {
- this.networkService.handleWorkerMessage({id: task.id});
- return;
- }
- }
-
- gNetworkWorker.postMessage(task.params);
- },
-
- enqueue: function(aId, aParams, aSetupFunction) {
- debug("enqueue id: " + aId);
- this.tasks.push(new Task(aId, aParams, aSetupFunction));
-
- if (this.tasks.length === 1) {
- this.runQueue();
- }
- },
-
- dequeue: function(aId) {
- debug("dequeue id: " + aId);
-
- if (!this.tasks.length || this.tasks[0].id != aId) {
- debug("Id " + aId + " is not on top of the queue");
- return;
- }
-
- this.tasks.shift();
- if (this.tasks.length > 0) {
- // Run queue on the next tick.
- Services.tm.currentThread.dispatch(() => {
- this.runQueue();
- }, Ci.nsIThread.DISPATCH_NORMAL);
- }
- }
-};
-
-
-/**
- * This component watches for network interfaces changing state and then
- * adjusts routes etc. accordingly.
- */
-function NetworkService() {
- debug("Starting NetworkService.");
-
- let self = this;
-
- if (gNetworkWorker) {
- let networkListener = {
- onEvent: function(aEvent) {
- self.handleWorkerMessage(aEvent);
- }
- };
- gNetworkWorker.start(networkListener);
- }
- // Callbacks to invoke when a reply arrives from the net_worker.
- this.controlCallbacks = Object.create(null);
-
- this.addedRoutes = new Map();
- this.netWorkerRequestQueue = new NetworkWorkerRequestQueue(this);
- this.shutdown = false;
-
- Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
-}
-
-NetworkService.prototype = {
- classID: NETWORKSERVICE_CID,
- classInfo: XPCOMUtils.generateCI({classID: NETWORKSERVICE_CID,
- contractID: NETWORKSERVICE_CONTRACTID,
- classDescription: "Network Service",
- interfaces: [Ci.nsINetworkService]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkService,
- Ci.nsIObserver]),
-
- addedRoutes: null,
-
- shutdown: false,
-
- // nsIObserver
-
- observe: function(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_PREF_CHANGED:
- if (aData === PREF_NETWORK_DEBUG_ENABLED) {
- updateDebug();
- }
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- debug("NetworkService shutdown");
- this.shutdown = true;
- if (gNetworkWorker) {
- gNetworkWorker.shutdown();
- gNetworkWorker = null;
- }
-
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
- break;
- }
- },
-
- // Helpers
-
- idgen: 0,
- controlMessage: function(aParams, aCallback, aSetupFunction) {
- if (this.shutdown) {
- return;
- }
-
- let id = this.idgen++;
- aParams.id = id;
- if (aCallback) {
- this.controlCallbacks[id] = aCallback;
- }
-
- // For now, we use aSetupFunction to determine if this command needs to be
- // queued or not.
- if (aSetupFunction) {
- this.netWorkerRequestQueue.enqueue(id, aParams, aSetupFunction);
- return;
- }
-
- if (gNetworkWorker) {
- gNetworkWorker.postMessage(aParams);
- }
- },
-
- handleWorkerMessage: function(aResponse) {
- debug("NetworkManager received message from worker: " + JSON.stringify(aResponse));
- let id = aResponse.id;
- if (aResponse.broadcast === true) {
- Services.obs.notifyObservers(null, aResponse.topic, aResponse.reason);
- return;
- }
- let callback = this.controlCallbacks[id];
- if (callback) {
- callback.call(this, aResponse);
- delete this.controlCallbacks[id];
- }
-
- this.netWorkerRequestQueue.dequeue(id);
- },
-
- // nsINetworkService
-
- getNetworkInterfaceStats: function(aInterfaceName, aCallback) {
- debug("getNetworkInterfaceStats for " + aInterfaceName);
-
- let file = new FileUtils.File("/proc/net/dev");
- if (!file) {
- aCallback.networkStatsAvailable(false, 0, 0, Date.now());
- return;
- }
-
- NetUtil.asyncFetch({
- uri: NetUtil.newURI(file),
- loadUsingSystemPrincipal: true
- }, function(inputStream, status) {
- let rxBytes = 0,
- txBytes = 0,
- now = Date.now();
-
- if (Components.isSuccessCode(status)) {
- // Find record for corresponding interface.
- let statExpr = /(\S+): +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+/;
- let data =
- NetUtil.readInputStreamToString(inputStream, inputStream.available())
- .split("\n");
- for (let i = 2; i < data.length; i++) {
- let parseResult = statExpr.exec(data[i]);
- if (parseResult && parseResult[1] === aInterfaceName) {
- rxBytes = parseInt(parseResult[2], 10);
- txBytes = parseInt(parseResult[3], 10);
- break;
- }
- }
- }
-
- // netd always return success even interface doesn't exist.
- aCallback.networkStatsAvailable(true, rxBytes, txBytes, now);
- });
- },
-
- setNetworkTetheringAlarm(aEnable, aInterface) {
- // Method called when enabling disabling tethering, it checks if there is
- // some alarm active and move from interfaceAlarm to globalAlarm because
- // interfaceAlarm doens't work in tethering scenario due to forwarding.
- debug("setNetworkTetheringAlarm for tethering" + aEnable);
-
- let filename = aEnable ? "/proc/net/xt_quota/" + aInterface + "Alert" :
- "/proc/net/xt_quota/globalAlert";
-
- let file = new FileUtils.File(filename);
- if (!file) {
- return;
- }
-
- NetUtil.asyncFetch({
- uri: NetUtil.newURI(file),
- loadUsingSystemPrincipal: true
- }, (inputStream, status) => {
- if (Components.isSuccessCode(status)) {
- let data = NetUtil.readInputStreamToString(inputStream, inputStream.available())
- .split("\n");
- if (data) {
- let threshold = parseInt(data[0], 10);
-
- this._setNetworkTetheringAlarm(aEnable, aInterface, threshold);
- }
- }
- });
- },
-
- _setNetworkTetheringAlarm(aEnable, aInterface, aThreshold, aCallback) {
- debug("_setNetworkTetheringAlarm for tethering" + aEnable);
-
- let cmd = aEnable ? "setTetheringAlarm" : "removeTetheringAlarm";
-
- let params = {
- cmd: cmd,
- ifname: aInterface,
- threshold: aThreshold,
- };
-
- this.controlMessage(params, function(aData) {
- let code = aData.resultCode;
- let reason = aData.resultReason;
- let enableString = aEnable ? "Enable" : "Disable";
- debug(enableString + " tethering Alarm result: Code " + code + " reason " + reason);
- if (aCallback) {
- aCallback.networkUsageAlarmResult(null);
- }
- });
- },
-
- setNetworkInterfaceAlarm: function(aInterfaceName, aThreshold, aCallback) {
- if (!aInterfaceName) {
- aCallback.networkUsageAlarmResult(-1);
- return;
- }
-
- let self = this;
- this._disableNetworkInterfaceAlarm(aInterfaceName, function(aResult) {
- if (aThreshold < 0) {
- if (!isError(aResult.resultCode)) {
- aCallback.networkUsageAlarmResult(null);
- return;
- }
- aCallback.networkUsageAlarmResult(aResult.reason);
- return
- }
-
- // Check if tethering is enabled
- let params = {
- cmd: "getTetheringStatus"
- };
-
- self.controlMessage(params, function(aResult) {
- if (isError(aResult.resultCode)) {
- aCallback.networkUsageAlarmResult(aResult.reason);
- return;
- }
-
- if (aResult.resultReason.indexOf('started') == -1) {
- // Tethering disabled, set interfaceAlarm
- self._setNetworkInterfaceAlarm(aInterfaceName, aThreshold, aCallback);
- return;
- }
-
- // Tethering enabled, set globalAlarm
- self._setNetworkTetheringAlarm(true, aInterfaceName, aThreshold, aCallback);
- });
- });
- },
-
- _setNetworkInterfaceAlarm: function(aInterfaceName, aThreshold, aCallback) {
- debug("setNetworkInterfaceAlarm for " + aInterfaceName + " at " + aThreshold + "bytes");
-
- let params = {
- cmd: "setNetworkInterfaceAlarm",
- ifname: aInterfaceName,
- threshold: aThreshold
- };
-
- params.report = true;
-
- this.controlMessage(params, function(aResult) {
- if (!isError(aResult.resultCode)) {
- aCallback.networkUsageAlarmResult(null);
- return;
- }
-
- this._enableNetworkInterfaceAlarm(aInterfaceName, aThreshold, aCallback);
- });
- },
-
- _enableNetworkInterfaceAlarm: function(aInterfaceName, aThreshold, aCallback) {
- debug("enableNetworkInterfaceAlarm for " + aInterfaceName + " at " + aThreshold + "bytes");
-
- let params = {
- cmd: "enableNetworkInterfaceAlarm",
- ifname: aInterfaceName,
- threshold: aThreshold
- };
-
- params.report = true;
-
- this.controlMessage(params, function(aResult) {
- if (!isError(aResult.resultCode)) {
- aCallback.networkUsageAlarmResult(null);
- return;
- }
- aCallback.networkUsageAlarmResult(aResult.reason);
- });
- },
-
- _disableNetworkInterfaceAlarm: function(aInterfaceName, aCallback) {
- debug("disableNetworkInterfaceAlarm for " + aInterfaceName);
-
- let params = {
- cmd: "disableNetworkInterfaceAlarm",
- ifname: aInterfaceName,
- };
-
- params.report = true;
-
- this.controlMessage(params, function(aResult) {
- aCallback(aResult);
- });
- },
-
- setWifiOperationMode: function(aInterfaceName, aMode, aCallback) {
- debug("setWifiOperationMode on " + aInterfaceName + " to " + aMode);
-
- let params = {
- cmd: "setWifiOperationMode",
- ifname: aInterfaceName,
- mode: aMode
- };
-
- params.report = true;
-
- this.controlMessage(params, function(aResult) {
- if (isError(aResult.resultCode)) {
- aCallback.wifiOperationModeResult("netd command error");
- } else {
- aCallback.wifiOperationModeResult(null);
- }
- });
- },
-
- resetRoutingTable: function(aInterfaceName, aCallback) {
- let options = {
- cmd: "removeNetworkRoute",
- ifname: aInterfaceName
- };
-
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- setDNS: function(aInterfaceName, aDnsesCount, aDnses, aGatewaysCount,
- aGateways, aCallback) {
- debug("Going to set DNS to " + aInterfaceName);
- let options = {
- cmd: "setDNS",
- ifname: aInterfaceName,
- domain: "mozilla." + aInterfaceName + ".domain",
- dnses: aDnses,
- gateways: aGateways
- };
- this.controlMessage(options, function(aResult) {
- aCallback.setDnsResult(aResult.success ? null : aResult.reason);
- });
- },
-
- setDefaultRoute: function(aInterfaceName, aCount, aGateways, aCallback) {
- debug("Going to change default route to " + aInterfaceName);
- let options = {
- cmd: "setDefaultRoute",
- ifname: aInterfaceName,
- gateways: aGateways
- };
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- removeDefaultRoute: function(aInterfaceName, aCount, aGateways, aCallback) {
- debug("Remove default route for " + aInterfaceName);
- let options = {
- cmd: "removeDefaultRoute",
- ifname: aInterfaceName,
- gateways: aGateways
- };
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- _routeToString: function(aInterfaceName, aHost, aPrefixLength, aGateway) {
- return aHost + "-" + aPrefixLength + "-" + aGateway + "-" + aInterfaceName;
- },
-
- modifyRoute: function(aAction, aInterfaceName, aHost, aPrefixLength, aGateway) {
- let command;
-
- switch (aAction) {
- case Ci.nsINetworkService.MODIFY_ROUTE_ADD:
- command = 'addHostRoute';
- break;
- case Ci.nsINetworkService.MODIFY_ROUTE_REMOVE:
- command = 'removeHostRoute';
- break;
- default:
- debug('Unknown action: ' + aAction);
- return Promise.reject();
- }
-
- let route = this._routeToString(aInterfaceName, aHost, aPrefixLength, aGateway);
- let setupFunc = () => {
- let count = this.addedRoutes.get(route);
- debug(command + ": " + route + " -> " + count);
-
- // Return false if there is no need to send the command to network worker.
- if ((aAction == Ci.nsINetworkService.MODIFY_ROUTE_ADD && count) ||
- (aAction == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE &&
- (!count || count > 1))) {
- return false;
- }
-
- return true;
- };
-
- debug(command + " " + aHost + " on " + aInterfaceName);
- let options = {
- cmd: command,
- ifname: aInterfaceName,
- gateway: aGateway,
- prefixLength: aPrefixLength,
- ip: aHost
- };
-
- return new Promise((aResolve, aReject) => {
- this.controlMessage(options, (aData) => {
- let count = this.addedRoutes.get(route);
-
- // Remove route from addedRoutes on success or failure.
- if (aAction == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE) {
- if (count > 1) {
- this.addedRoutes.set(route, count - 1);
- } else {
- this.addedRoutes.delete(route);
- }
- }
-
- if (aData.error) {
- aReject(aData.reason);
- return;
- }
-
- if (aAction == Ci.nsINetworkService.MODIFY_ROUTE_ADD) {
- this.addedRoutes.set(route, count ? count + 1 : 1);
- }
-
- aResolve();
- }, setupFunc);
- });
- },
-
- addSecondaryRoute: function(aInterfaceName, aRoute, aCallback) {
- debug("Going to add route to secondary table on " + aInterfaceName);
- let options = {
- cmd: "addSecondaryRoute",
- ifname: aInterfaceName,
- ip: aRoute.ip,
- prefix: aRoute.prefix,
- gateway: aRoute.gateway
- };
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- removeSecondaryRoute: function(aInterfaceName, aRoute, aCallback) {
- debug("Going to remove route from secondary table on " + aInterfaceName);
- let options = {
- cmd: "removeSecondaryRoute",
- ifname: aInterfaceName,
- ip: aRoute.ip,
- prefix: aRoute.prefix,
- gateway: aRoute.gateway
- };
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- // Enable/Disable DHCP server.
- setDhcpServer: function(aEnabled, aConfig, aCallback) {
- if (null === aConfig) {
- aConfig = {};
- }
-
- aConfig.cmd = "setDhcpServer";
- aConfig.enabled = aEnabled;
-
- this.controlMessage(aConfig, function(aResponse) {
- if (!aResponse.success) {
- aCallback.dhcpServerResult('Set DHCP server error');
- return;
- }
- aCallback.dhcpServerResult(null);
- });
- },
-
- // Enable/disable WiFi tethering by sending commands to netd.
- setWifiTethering: function(aEnable, aConfig, aCallback) {
- // config should've already contained:
- // .ifname
- // .internalIfname
- // .externalIfname
- aConfig.wifictrlinterfacename = WIFI_CTRL_INTERFACE;
- aConfig.cmd = "setWifiTethering";
-
- // The callback function in controlMessage may not be fired immediately.
- this.controlMessage(aConfig, (aData) => {
- let code = aData.resultCode;
- let reason = aData.resultReason;
- let enable = aData.enable;
- let enableString = aEnable ? "Enable" : "Disable";
-
- debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
-
- this.setNetworkTetheringAlarm(aEnable, aConfig.externalIfname);
-
- if (isError(code)) {
- aCallback.wifiTetheringEnabledChange("netd command error");
- } else {
- aCallback.wifiTetheringEnabledChange(null);
- }
- });
- },
-
- // Enable/disable USB tethering by sending commands to netd.
- setUSBTethering: function(aEnable, aConfig, aCallback) {
- aConfig.cmd = "setUSBTethering";
- // The callback function in controlMessage may not be fired immediately.
- this.controlMessage(aConfig, (aData) => {
- let code = aData.resultCode;
- let reason = aData.resultReason;
- let enable = aData.enable;
- let enableString = aEnable ? "Enable" : "Disable";
-
- debug(enableString + " USB tethering result: Code " + code + " reason " + reason);
-
- this.setNetworkTetheringAlarm(aEnable, aConfig.externalIfname);
-
- if (isError(code)) {
- aCallback.usbTetheringEnabledChange("netd command error");
- } else {
- aCallback.usbTetheringEnabledChange(null);
- }
- });
- },
-
- // Switch usb function by modifying property of persist.sys.usb.config.
- enableUsbRndis: function(aEnable, aCallback) {
- debug("enableUsbRndis: " + aEnable);
-
- let params = {
- cmd: "enableUsbRndis",
- enable: aEnable
- };
- // Ask net work to report the result when this value is set to true.
- if (aCallback) {
- params.report = true;
- } else {
- params.report = false;
- }
-
- // The callback function in controlMessage may not be fired immediately.
- //this._usbTetheringAction = TETHERING_STATE_ONGOING;
- this.controlMessage(params, function(aData) {
- aCallback.enableUsbRndisResult(aData.result, aData.enable);
- });
- },
-
- updateUpStream: function(aPrevious, aCurrent, aCallback) {
- let params = {
- cmd: "updateUpStream",
- preInternalIfname: aPrevious.internalIfname,
- preExternalIfname: aPrevious.externalIfname,
- curInternalIfname: aCurrent.internalIfname,
- curExternalIfname: aCurrent.externalIfname
- };
-
- this.controlMessage(params, function(aData) {
- let code = aData.resultCode;
- let reason = aData.resultReason;
- debug("updateUpStream result: Code " + code + " reason " + reason);
- aCallback.updateUpStreamResult(!isError(code), aData.curExternalIfname);
- });
- },
-
- getInterfaces: function(callback) {
- let params = {
- cmd: "getInterfaces",
- isAsync: true
- };
-
- this.controlMessage(params, function(data) {
- debug("getInterfaces result: " + JSON.stringify(data));
- let success = !isError(data.resultCode);
- callback.getInterfacesResult(success, data.interfaceList);
- });
- },
-
- getInterfaceConfig: function(ifname, callback) {
- let params = {
- cmd: "getInterfaceConfig",
- ifname: ifname,
- isAsync: true
- };
-
- this.controlMessage(params, function(data) {
- debug("getInterfaceConfig result: " + JSON.stringify(data));
- let success = !isError(data.resultCode);
- let result = { ip: data.ipAddr,
- prefix: data.prefixLength,
- link: data.flag,
- mac: data.macAddr };
- callback.getInterfaceConfigResult(success, result);
- });
- },
-
- setInterfaceConfig: function(config, callback) {
- config.cmd = "setInterfaceConfig";
- config.isAsync = true;
-
- this.controlMessage(config, function(data) {
- debug("setInterfaceConfig result: " + JSON.stringify(data));
- let success = !isError(data.resultCode);
- callback.setInterfaceConfigResult(success);
- });
- },
-
- configureInterface: function(aConfig, aCallback) {
- let params = {
- cmd: "configureInterface",
- ifname: aConfig.ifname,
- ipaddr: aConfig.ipaddr,
- mask: aConfig.mask,
- gateway_long: aConfig.gateway,
- dns1_long: aConfig.dns1,
- dns2_long: aConfig.dns2,
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- dhcpRequest: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "dhcpRequest",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.dhcpRequestResult(!aResult.error, aResult.error ? null : aResult);
- });
- },
-
- stopDhcp: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "stopDhcp",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- enableInterface: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "enableInterface",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- disableInterface: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "disableInterface",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- resetConnections: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "resetConnections",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- createNetwork: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "createNetwork",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- destroyNetwork: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "destroyNetwork",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- getNetId: function(aInterfaceName) {
- let params = {
- cmd: "getNetId",
- ifname: aInterfaceName
- };
-
- return new Promise((aResolve, aReject) => {
- this.controlMessage(params, result => {
- if (result.error) {
- aReject(result.reason);
- return;
- }
- aResolve(result.netId);
- });
- });
- },
-
- setMtu: function (aInterfaceName, aMtu, aCallback) {
- debug("Set MTU on " + aInterfaceName + ": " + aMtu);
-
- let params = {
- cmd: "setMtu",
- ifname: aInterfaceName,
- mtu: aMtu
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkService]);
diff --git a/dom/system/gonk/NetworkService.manifest b/dom/system/gonk/NetworkService.manifest
deleted file mode 100644
index caf8f2554..000000000
--- a/dom/system/gonk/NetworkService.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-# NetworkService.js
-component {48c13741-aec9-4a86-8962-432011708261} NetworkService.js
-contract @mozilla.org/network/service;1 {48c13741-aec9-4a86-8962-432011708261}
diff --git a/dom/system/gonk/NetworkUtils.cpp b/dom/system/gonk/NetworkUtils.cpp
deleted file mode 100644
index d661368b8..000000000
--- a/dom/system/gonk/NetworkUtils.cpp
+++ /dev/null
@@ -1,2973 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "NetworkUtils.h"
-
-#include "mozilla/Sprintf.h"
-#include "SystemProperty.h"
-
-#include <android/log.h>
-#include <limits>
-#include "mozilla/dom/network/NetUtils.h"
-#include "mozilla/fallible.h"
-#include "base/task.h"
-
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h> // struct addrinfo
-#include <sys/socket.h> // getaddrinfo(), freeaddrinfo()
-#include <netdb.h>
-#include <arpa/inet.h> // inet_ntop()
-
-#define _DEBUG 0
-
-#define WARN(args...) __android_log_print(ANDROID_LOG_WARN, "NetworkUtils", ## args)
-#define ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "NetworkUtils", ## args)
-
-#if _DEBUG
-#define NU_DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "NetworkUtils" , ## args)
-#else
-#define NU_DBG(args...)
-#endif
-
-using namespace mozilla::dom;
-using namespace mozilla::ipc;
-using mozilla::system::Property;
-
-static const char* PERSIST_SYS_USB_CONFIG_PROPERTY = "persist.sys.usb.config";
-static const char* SYS_USB_CONFIG_PROPERTY = "sys.usb.config";
-static const char* SYS_USB_STATE_PROPERTY = "sys.usb.state";
-
-static const char* USB_FUNCTION_RNDIS = "rndis";
-static const char* USB_FUNCTION_ADB = "adb";
-
-// Use this command to continue the function chain.
-static const char* DUMMY_COMMAND = "tether status";
-
-// IPV6 Tethering is not supported in AOSP, use the property to
-// identify vendor specific support in IPV6. We can remove this flag
-// once upstream Android support IPV6 in tethering.
-static const char* IPV6_TETHERING = "ro.tethering.ipv6";
-
-// Retry 20 times (2 seconds) for usb state transition.
-static const uint32_t USB_FUNCTION_RETRY_TIMES = 20;
-// Check "sys.usb.state" every 100ms.
-static const uint32_t USB_FUNCTION_RETRY_INTERVAL = 100;
-
-// 1xx - Requested action is proceeding
-static const uint32_t NETD_COMMAND_PROCEEDING = 100;
-// 2xx - Requested action has been successfully completed
-static const uint32_t NETD_COMMAND_OKAY = 200;
-// 4xx - The command is accepted but the requested action didn't
-// take place.
-static const uint32_t NETD_COMMAND_FAIL = 400;
-// 5xx - The command syntax or parameters error
-static const uint32_t NETD_COMMAND_ERROR = 500;
-// 6xx - Unsolicited broadcasts
-static const uint32_t NETD_COMMAND_UNSOLICITED = 600;
-
-// Broadcast messages
-static const uint32_t NETD_COMMAND_INTERFACE_CHANGE = 600;
-static const uint32_t NETD_COMMAND_BANDWIDTH_CONTROLLER = 601;
-
-static const char* INTERFACE_DELIMIT = ",";
-static const char* USB_CONFIG_DELIMIT = ",";
-static const char* NETD_MESSAGE_DELIMIT = " ";
-
-static const uint32_t BUF_SIZE = 1024;
-
-static const int32_t SUCCESS = 0;
-
-static uint32_t SDK_VERSION;
-static uint32_t SUPPORT_IPV6_TETHERING;
-
-struct IFProperties {
- char gateway[Property::VALUE_MAX_LENGTH];
- char dns1[Property::VALUE_MAX_LENGTH];
- char dns2[Property::VALUE_MAX_LENGTH];
-};
-
-struct CurrentCommand {
- CommandChain* chain;
- CommandCallback callback;
- char command[MAX_COMMAND_SIZE];
-};
-
-typedef Tuple3<NetdCommand*, CommandChain*, CommandCallback> QueueData;
-
-#define GET_CURRENT_NETD_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a)
-#define GET_CURRENT_CHAIN (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].b)
-#define GET_CURRENT_CALLBACK (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].c)
-#define GET_CURRENT_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a->mData)
-
-// A macro for native function call return value check.
-// For native function call, non-zero return value means failure.
-#define RETURN_IF_FAILED(rv) do { \
- if (SUCCESS != rv) { \
- return rv; \
- } \
-} while (0);
-
-#define WARN_IF_FAILED(rv) do { \
- if (SUCCESS != rv) { \
- WARN("Error (%d) occurred in %s (%s:%d)", rv, __PRETTY_FUNCTION__, __FILE__, __LINE__); \
- } \
-} while (0);
-
-static NetworkUtils* gNetworkUtils;
-static nsTArray<QueueData> gCommandQueue;
-static CurrentCommand gCurrentCommand;
-static bool gPending = false;
-static nsTArray<nsCString> gReason;
-static NetworkParams *gWifiTetheringParms = 0;
-
-static nsTArray<CommandChain*> gCommandChainQueue;
-
-const CommandFunc NetworkUtils::sWifiEnableChain[] = {
- NetworkUtils::clearWifiTetherParms,
- NetworkUtils::wifiFirmwareReload,
- NetworkUtils::startAccessPointDriver,
- NetworkUtils::setAccessPoint,
- NetworkUtils::startSoftAP,
- NetworkUtils::setConfig,
- NetworkUtils::tetherInterface,
- NetworkUtils::addInterfaceToLocalNetwork,
- NetworkUtils::addRouteToLocalNetwork,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::tetheringStatus,
- NetworkUtils::startTethering,
- NetworkUtils::setDnsForwarders,
- NetworkUtils::enableNat,
- NetworkUtils::wifiTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sWifiDisableChain[] = {
- NetworkUtils::clearWifiTetherParms,
- NetworkUtils::stopSoftAP,
- NetworkUtils::stopAccessPointDriver,
- NetworkUtils::wifiFirmwareReload,
- NetworkUtils::untetherInterface,
- NetworkUtils::removeInterfaceFromLocalNetwork,
- NetworkUtils::preTetherInterfaceList,
- NetworkUtils::postTetherInterfaceList,
- NetworkUtils::disableNat,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::stopTethering,
- NetworkUtils::wifiTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sWifiFailChain[] = {
- NetworkUtils::clearWifiTetherParms,
- NetworkUtils::stopSoftAP,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::stopTethering
-};
-
-const CommandFunc NetworkUtils::sWifiRetryChain[] = {
- NetworkUtils::clearWifiTetherParms,
- NetworkUtils::stopSoftAP,
- NetworkUtils::stopTethering,
-
- // sWifiEnableChain:
- NetworkUtils::wifiFirmwareReload,
- NetworkUtils::startAccessPointDriver,
- NetworkUtils::setAccessPoint,
- NetworkUtils::startSoftAP,
- NetworkUtils::setConfig,
- NetworkUtils::tetherInterface,
- NetworkUtils::addInterfaceToLocalNetwork,
- NetworkUtils::addRouteToLocalNetwork,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::tetheringStatus,
- NetworkUtils::startTethering,
- NetworkUtils::setDnsForwarders,
- NetworkUtils::enableNat,
- NetworkUtils::wifiTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sWifiOperationModeChain[] = {
- NetworkUtils::wifiFirmwareReload,
- NetworkUtils::wifiOperationModeSuccess
-};
-
-const CommandFunc NetworkUtils::sUSBEnableChain[] = {
- NetworkUtils::setConfig,
- NetworkUtils::enableNat,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::tetherInterface,
- NetworkUtils::addInterfaceToLocalNetwork,
- NetworkUtils::addRouteToLocalNetwork,
- NetworkUtils::tetheringStatus,
- NetworkUtils::startTethering,
- NetworkUtils::setDnsForwarders,
- NetworkUtils::addUpstreamInterface,
- NetworkUtils::usbTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sUSBDisableChain[] = {
- NetworkUtils::untetherInterface,
- NetworkUtils::removeInterfaceFromLocalNetwork,
- NetworkUtils::preTetherInterfaceList,
- NetworkUtils::postTetherInterfaceList,
- NetworkUtils::removeUpstreamInterface,
- NetworkUtils::disableNat,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::stopTethering,
- NetworkUtils::usbTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sUSBFailChain[] = {
- NetworkUtils::stopSoftAP,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::stopTethering
-};
-
-const CommandFunc NetworkUtils::sUpdateUpStreamChain[] = {
- NetworkUtils::cleanUpStream,
- NetworkUtils::removeUpstreamInterface,
- NetworkUtils::createUpStream,
- NetworkUtils::addUpstreamInterface,
- NetworkUtils::updateUpStreamSuccess
-};
-
-const CommandFunc NetworkUtils::sStartDhcpServerChain[] = {
- NetworkUtils::setConfig,
- NetworkUtils::startTethering,
- NetworkUtils::setDhcpServerSuccess
-};
-
-const CommandFunc NetworkUtils::sStopDhcpServerChain[] = {
- NetworkUtils::stopTethering,
- NetworkUtils::setDhcpServerSuccess
-};
-
-const CommandFunc NetworkUtils::sNetworkInterfaceEnableAlarmChain[] = {
- NetworkUtils::enableAlarm,
- NetworkUtils::setQuota,
- NetworkUtils::setAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sNetworkInterfaceDisableAlarmChain[] = {
- NetworkUtils::removeQuota,
- NetworkUtils::disableAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sNetworkInterfaceSetAlarmChain[] = {
- NetworkUtils::setAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sGetInterfacesChain[] = {
- NetworkUtils::getInterfaceList,
- NetworkUtils::getInterfacesSuccess
-};
-
-const CommandFunc NetworkUtils::sGetInterfaceConfigChain[] = {
- NetworkUtils::getConfig,
- NetworkUtils::getInterfaceConfigSuccess
-};
-
-const CommandFunc NetworkUtils::sSetInterfaceConfigChain[] = {
- NetworkUtils::setConfig,
- NetworkUtils::setInterfaceConfigSuccess
-};
-
-const CommandFunc NetworkUtils::sTetheringInterfaceSetAlarmChain[] = {
- NetworkUtils::setGlobalAlarm,
- NetworkUtils::removeAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sTetheringInterfaceRemoveAlarmChain[] = {
- NetworkUtils::removeGlobalAlarm,
- NetworkUtils::setAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sTetheringGetStatusChain[] = {
- NetworkUtils::tetheringStatus,
- NetworkUtils::defaultAsyncSuccessHandler
-};
-
-/**
- * Helper function to get the mask from given prefix length.
- */
-static uint32_t makeMask(const uint32_t prefixLength)
-{
- uint32_t mask = 0;
- for (uint32_t i = 0; i < prefixLength; ++i) {
- mask |= (0x80000000 >> i);
- }
- return ntohl(mask);
-}
-
-/**
- * Helper function to get the network part of an ip from prefix.
- * param ip must be in network byte order.
- */
-static char* getNetworkAddr(const uint32_t ip, const uint32_t prefix)
-{
- uint32_t mask = 0, subnet = 0;
-
- mask = ~mask << (32 - prefix);
- mask = htonl(mask);
- subnet = ip & mask;
-
- struct in_addr addr;
- addr.s_addr = subnet;
-
- return inet_ntoa(addr);
-}
-
-/**
- * Helper function to split string by seperator, store split result as an nsTArray.
- */
-static void split(char* str, const char* sep, nsTArray<nsCString>& result)
-{
- char *s = strtok(str, sep);
- while (s != nullptr) {
- result.AppendElement(s);
- s = strtok(nullptr, sep);
- }
-}
-
-static void split(char* str, const char* sep, nsTArray<nsString>& result)
-{
- char *s = strtok(str, sep);
- while (s != nullptr) {
- result.AppendElement(NS_ConvertUTF8toUTF16(s));
- s = strtok(nullptr, sep);
- }
-}
-
-/**
- * Helper function that implement join function.
- */
-static void join(nsTArray<nsCString>& array,
- const char* sep,
- const uint32_t maxlen,
- char* result)
-{
-#define CHECK_LENGTH(len, add, max) len += add; \
- if (len > max - 1) \
- return; \
-
- uint32_t len = 0;
- uint32_t seplen = strlen(sep);
-
- if (array.Length() > 0) {
- CHECK_LENGTH(len, strlen(array[0].get()), maxlen)
- strcpy(result, array[0].get());
-
- for (uint32_t i = 1; i < array.Length(); i++) {
- CHECK_LENGTH(len, seplen, maxlen)
- strcat(result, sep);
-
- CHECK_LENGTH(len, strlen(array[i].get()), maxlen)
- strcat(result, array[i].get());
- }
- }
-
-#undef CHECK_LEN
-}
-
-static void convertUTF8toUTF16(nsTArray<nsCString>& narrow,
- nsTArray<nsString>& wide,
- uint32_t length)
-{
- for (uint32_t i = 0; i < length; i++) {
- wide.AppendElement(NS_ConvertUTF8toUTF16(narrow[i].get()));
- }
-}
-
-/**
- * Helper function to get network interface properties from the system property table.
- */
-static void getIFProperties(const char* ifname, IFProperties& prop)
-{
- char key[Property::KEY_MAX_LENGTH];
- snprintf(key, Property::KEY_MAX_LENGTH - 1, "net.%s.gw", ifname);
- Property::Get(key, prop.gateway, "");
- snprintf(key, Property::KEY_MAX_LENGTH - 1, "net.%s.dns1", ifname);
- Property::Get(key, prop.dns1, "");
- snprintf(key, Property::KEY_MAX_LENGTH - 1, "net.%s.dns2", ifname);
- Property::Get(key, prop.dns2, "");
-}
-
-static int getIpType(const char *aIp) {
- struct addrinfo hint, *ip_info = NULL;
-
- memset(&hint, 0, sizeof(hint));
- hint.ai_family = AF_UNSPEC;
- hint.ai_flags = AI_NUMERICHOST;
-
- if (getaddrinfo(aIp, NULL, &hint, &ip_info)) {
- return AF_UNSPEC;
- }
-
- int type = ip_info->ai_family;
- freeaddrinfo(ip_info);
-
- return type;
-}
-
-static void postMessage(NetworkResultOptions& aResult)
-{
- MOZ_ASSERT(gNetworkUtils);
- MOZ_ASSERT(gNetworkUtils->getMessageCallback());
-
- if (*(gNetworkUtils->getMessageCallback()))
- (*(gNetworkUtils->getMessageCallback()))(aResult);
-}
-
-static void postMessage(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- MOZ_ASSERT(gNetworkUtils);
- MOZ_ASSERT(gNetworkUtils->getMessageCallback());
-
- aResult.mId = aOptions.mId;
-
- if (*(gNetworkUtils->getMessageCallback()))
- (*(gNetworkUtils->getMessageCallback()))(aResult);
-}
-
-void NetworkUtils::runNextQueuedCommandChain()
-{
- if (gCommandChainQueue.IsEmpty()) {
- NU_DBG("No command chain left in the queue. Done!");
- return;
- }
- NU_DBG("Process the queued command chain.");
- CommandChain* nextChain = gCommandChainQueue[0];
- NetworkResultOptions newResult;
- next(nextChain, false, newResult);
-}
-
-void NetworkUtils::next(CommandChain* aChain, bool aError, NetworkResultOptions& aResult)
-{
- if (aError) {
- ErrorCallback onError = aChain->getErrorCallback();
- if(onError) {
- aResult.mError = true;
- (*onError)(aChain->getParams(), aResult);
- }
- delete aChain;
- gCommandChainQueue.RemoveElementAt(0);
- runNextQueuedCommandChain();
- return;
- }
- CommandFunc f = aChain->getNextCommand();
- if (!f) {
- delete aChain;
- gCommandChainQueue.RemoveElementAt(0);
- runNextQueuedCommandChain();
- return;
- }
-
- (*f)(aChain, next, aResult);
-}
-
-CommandResult::CommandResult(int32_t aResultCode)
- : mIsPending(false)
-{
- // This is usually not a netd command. We treat the return code
- // typical linux convention, which uses 0 to indicate success.
- mResult.mError = (aResultCode == SUCCESS ? false : true);
- mResult.mResultCode = aResultCode;
- if (aResultCode != SUCCESS) {
- // The returned value is sometimes negative, make sure we pass a positive
- // error number to strerror.
- enum { STRERROR_R_BUF_SIZE = 1024, };
- char strerrorBuf[STRERROR_R_BUF_SIZE];
- strerror_r(abs(aResultCode), strerrorBuf, STRERROR_R_BUF_SIZE);
- mResult.mReason = NS_ConvertUTF8toUTF16(strerrorBuf);
- }
-}
-
-CommandResult::CommandResult(const mozilla::dom::NetworkResultOptions& aResult)
- : mResult(aResult)
- , mIsPending(false)
-{
-}
-
-CommandResult::CommandResult(const Pending&)
- : mIsPending(true)
-{
-}
-
-bool CommandResult::isPending() const
-{
- return mIsPending;
-}
-
-/**
- * Send command to netd.
- */
-void NetworkUtils::nextNetdCommand()
-{
- if (gCommandQueue.IsEmpty() || gPending) {
- return;
- }
-
- gCurrentCommand.chain = GET_CURRENT_CHAIN;
- gCurrentCommand.callback = GET_CURRENT_CALLBACK;
- snprintf(gCurrentCommand.command, MAX_COMMAND_SIZE - 1, "%s", GET_CURRENT_COMMAND);
-
- NU_DBG("Sending \'%s\' command to netd.", gCurrentCommand.command);
- SendNetdCommand(GET_CURRENT_NETD_COMMAND);
-
- gCommandQueue.RemoveElementAt(0);
- gPending = true;
-}
-
-/**
- * Composite NetdCommand sent to netd
- *
- * @param aCommand Command sent to netd to execute.
- * @param aChain Store command chain data, ex. command parameter.
- * @param aCallback Callback function to be executed when the result of
- * this command is returned from netd.
- */
-void NetworkUtils::doCommand(const char* aCommand, CommandChain* aChain, CommandCallback aCallback)
-{
- NU_DBG("Preparing to send \'%s\' command...", aCommand);
-
- NetdCommand* netdCommand = new NetdCommand();
-
- // Android JB version adds sequence number to netd command.
- if (SDK_VERSION >= 16) {
- snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "0 %s", aCommand);
- } else {
- snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "%s", aCommand);
- }
- netdCommand->mSize = strlen((char*)netdCommand->mData) + 1;
-
- gCommandQueue.AppendElement(QueueData(netdCommand, aChain, aCallback));
-
- nextNetdCommand();
-}
-
-/*
- * Netd command function
- */
-#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aChain->getParams().prop).get()
-#define GET_FIELD(prop) aChain->getParams().prop
-
-void NetworkUtils::wifiFirmwareReload(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap fwreload %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::startAccessPointDriver(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version >= 16.
- if (SDK_VERSION >= 16) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap start %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::stopAccessPointDriver(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version >= 16.
- if (SDK_VERSION >= 16) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap stop %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-/**
- * Command format for sdk version < 16
- * Arguments:
- * argv[2] - wlan interface
- * argv[3] - SSID
- * argv[4] - Security
- * argv[5] - Key
- * argv[6] - Channel
- * argv[7] - Preamble
- * argv[8] - Max SCB
- *
- * Command format for sdk version >= 16
- * Arguments:
- * argv[2] - wlan interface
- * argv[3] - SSID
- * argv[4] - Security
- * argv[5] - Key
- *
- * Command format for sdk version >= 18
- * Arguments:
- * argv[2] - wlan interface
- * argv[3] - SSID
- * argv[4] - Broadcast/Hidden
- * argv[5] - Channel
- * argv[6] - Security
- * argv[7] - Key
- */
-void NetworkUtils::setAccessPoint(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- nsCString ssid(GET_CHAR(mSsid));
- nsCString key(GET_CHAR(mKey));
-
- escapeQuote(ssid);
- escapeQuote(key);
-
- if (SDK_VERSION >= 19) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" broadcast 6 %s \"%s\"",
- GET_CHAR(mIfname),
- ssid.get(),
- GET_CHAR(mSecurity),
- key.get());
- } else if (SDK_VERSION >= 16) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" %s \"%s\"",
- GET_CHAR(mIfname),
- ssid.get(),
- GET_CHAR(mSecurity),
- key.get());
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s %s \"%s\" %s \"%s\" 6 0 8",
- GET_CHAR(mIfname),
- GET_CHAR(mWifictrlinterfacename),
- ssid.get(),
- GET_CHAR(mSecurity),
- key.get());
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::cleanUpStream(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0", GET_CHAR(mPreInternalIfname), GET_CHAR(mPreExternalIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::createUpStream(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0", GET_CHAR(mCurInternalIfname), GET_CHAR(mCurExternalIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::startSoftAP(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "softap startap";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::stopSoftAP(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "softap stopap";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::clearWifiTetherParms(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- delete gWifiTetheringParms;
- gWifiTetheringParms = 0;
- next(aChain, false, aResult);
-}
-
-void NetworkUtils::enableAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "bandwidth enable";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::disableAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "bandwidth disable";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setQuota(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setiquota %s % " PRId64, GET_CHAR(mIfname), INT64_MAX);
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeQuota(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeiquota %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setinterfacealert %s %lld",
- GET_CHAR(mIfname), GET_FIELD(mThreshold));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeinterfacealert %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setGlobalAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setglobalalert %lld", GET_FIELD(mThreshold));
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeGlobalAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeglobalalert");
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::tetherInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface add %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addInterfaceToLocalNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version < 20.
- if (SDK_VERSION < 20) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network interface add local %s",
- GET_CHAR(mInternalIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addRouteToLocalNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version < 20.
- if (SDK_VERSION < 20) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- uint32_t prefix = atoi(GET_CHAR(mPrefix));
- uint32_t ip = inet_addr(GET_CHAR(mIp));
- char* networkAddr = getNetworkAddr(ip, prefix);
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "network route add local %s %s/%s",
- GET_CHAR(mInternalIfname), networkAddr, GET_CHAR(mPrefix));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::preTetherInterfaceList(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- if (SDK_VERSION >= 16) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list");
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list 0");
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::postTetherInterfaceList(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Send the dummy command to continue the function chain.
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
-
- char buf[BUF_SIZE];
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
-
- size_t length = reason.Length() + 1 < BUF_SIZE ? reason.Length() + 1 : BUF_SIZE;
- memcpy(buf, reason.get(), length);
- split(buf, INTERFACE_DELIMIT, GET_FIELD(mInterfaceList));
-
- doCommand(command, aChain, aCallback);
-}
-
-bool isCommandChainIPv6(CommandChain* aChain, const char *externalInterface) {
- // Check by gateway address
- if (getIpType(GET_CHAR(mGateway)) == AF_INET6) {
- return true;
- }
-
- uint32_t length = GET_FIELD(mGateways).Length();
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoGateway(GET_FIELD(mGateways)[i]);
- if(getIpType(autoGateway.get()) == AF_INET6) {
- return true;
- }
- }
-
- // Check by external inteface address
- FILE *file = fopen("/proc/net/if_inet6", "r");
- if (!file) {
- return false;
- }
-
- bool isIPv6 = false;
- char interface[32];
- while(fscanf(file, "%*s %*s %*s %*s %*s %32s", interface)) {
- if (strcmp(interface, externalInterface) == 0) {
- isIPv6 = true;
- break;
- }
- }
-
- fclose(file);
- return isIPv6;
-}
-
-void NetworkUtils::addUpstreamInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- nsCString interface(GET_CHAR(mExternalIfname));
- if (!interface.get()[0]) {
- interface = GET_CHAR(mCurExternalIfname);
- }
-
- if (SUPPORT_IPV6_TETHERING == 0 || !isCommandChainIPv6(aChain, interface.get())) {
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface add_upstream %s",
- interface.get());
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeUpstreamInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- nsCString interface(GET_CHAR(mExternalIfname));
- if (!interface.get()[0]) {
- interface = GET_CHAR(mPreExternalIfname);
- }
-
- if (SUPPORT_IPV6_TETHERING == 0 || !isCommandChainIPv6(aChain, interface.get())) {
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface remove_upstream %s",
- interface.get());
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setIpForwardingEnabled(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- if (GET_FIELD(mEnable)) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd enable");
- } else {
- // Don't disable ip forwarding because others interface still need it.
- // Send the dummy command to continue the function chain.
- if (GET_FIELD(mInterfaceList).Length() > 1) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd disable");
- }
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::tetheringStatus(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "tether status";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::stopTethering(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- // Don't stop tethering because others interface still need it.
- // Send the dummy to continue the function chain.
- if (GET_FIELD(mInterfaceList).Length() > 1) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether stop");
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::startTethering(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- // We don't need to start tethering again.
- // Send the dummy command to continue the function chain.
- if (aResult.mResultReason.Find("started") != kNotFound) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
- } else {
- // If usbStartIp/usbEndIp is not valid, don't append them since
- // the trailing white spaces will be parsed to extra empty args
- // See: http://androidxref.com/4.3_r2.1/xref/system/core/libsysutils/src/FrameworkListener.cpp#78
- if (!GET_FIELD(mUsbStartIp).IsEmpty() && !GET_FIELD(mUsbEndIp).IsEmpty()) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s %s %s",
- GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp),
- GET_CHAR(mUsbStartIp), GET_CHAR(mUsbEndIp));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s",
- GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp));
- }
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::untetherInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface remove %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeInterfaceFromLocalNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version < 20.
- if (SDK_VERSION < 20) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network interface remove local %s",
- GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setDnsForwarders(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- if (SDK_VERSION >= 20) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether dns set %d %s %s",
- GET_FIELD(mNetId), GET_CHAR(mDns1), GET_CHAR(mDns2));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether dns set %s %s",
- GET_CHAR(mDns1), GET_CHAR(mDns2));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::enableNat(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- if (!GET_FIELD(mIp).IsEmpty() && !GET_FIELD(mPrefix).IsEmpty()) {
- uint32_t prefix = atoi(GET_CHAR(mPrefix));
- uint32_t ip = inet_addr(GET_CHAR(mIp));
- char* networkAddr = getNetworkAddr(ip, prefix);
-
- // address/prefix will only take effect when secondary routing table exists.
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 1 %s/%s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname), networkAddr,
- GET_CHAR(mPrefix));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::disableNat(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- if (!GET_FIELD(mIp).IsEmpty() && !GET_FIELD(mPrefix).IsEmpty()) {
- uint32_t prefix = atoi(GET_CHAR(mPrefix));
- uint32_t ip = inet_addr(GET_CHAR(mIp));
- char* networkAddr = getNetworkAddr(ip, prefix);
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 1 %s/%s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname), networkAddr,
- GET_CHAR(mPrefix));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setDefaultInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "resolver setdefaultif %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeDefaultRoute(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- if (GET_FIELD(mLoopIndex) >= GET_FIELD(mGateways).Length()) {
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- nsTArray<nsString>& gateways = GET_FIELD(mGateways);
- NS_ConvertUTF16toUTF8 autoGateway(gateways[GET_FIELD(mLoopIndex)]);
-
- int type = getIpType(autoGateway.get());
- snprintf(command, MAX_COMMAND_SIZE - 1, "network route remove %d %s %s/0 %s",
- GET_FIELD(mNetId), GET_CHAR(mIfname),
- type == AF_INET6 ? "::" : "0.0.0.0", autoGateway.get());
-
- struct MyCallback {
- static void callback(CommandCallback::CallbackType aOriginalCallback,
- CommandChain* aChain,
- bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- NU_DBG("removeDefaultRoute's reason: %s", reason.get());
- if (aError && !reason.EqualsASCII("removeRoute() failed (No such process)")) {
- return aOriginalCallback(aChain, aError, aResult);
- }
-
- GET_FIELD(mLoopIndex)++;
- return removeDefaultRoute(aChain, aOriginalCallback, aResult);
- }
- };
-
- CommandCallback wrappedCallback(MyCallback::callback, aCallback);
- doCommand(command, aChain, wrappedCallback);
-}
-
-void NetworkUtils::setInterfaceDns(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- int written;
-
- if (SDK_VERSION >= 20) {
- written = SprintfLiteral(command, "resolver setnetdns %d %s",
- GET_FIELD(mNetId), GET_CHAR(mDomain));
- } else {
- written = SprintfLiteral(command, "resolver setifdns %s %s",
- GET_CHAR(mIfname), GET_CHAR(mDomain));
- }
-
- nsTArray<nsString>& dnses = GET_FIELD(mDnses);
- uint32_t length = dnses.Length();
-
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoDns(dnses[i]);
-
- int ret = snprintf(command + written, sizeof(command) - written, " %s", autoDns.get());
- if (ret <= 1) {
- command[written] = '\0';
- continue;
- }
-
- if (((size_t)ret + written) >= sizeof(command)) {
- command[written] = '\0';
- break;
- }
-
- written += ret;
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::getInterfaceList(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface list");
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::getConfig(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface getcfg %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setConfig(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- if (SDK_VERSION >= 16) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s %s",
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mLink));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s [%s]",
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mLink));
- }
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::clearAddrForInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface clearaddrs %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::createNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network create %d", GET_FIELD(mNetId));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::destroyNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network destroy %d", GET_FIELD(mNetId));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addInterfaceToNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network interface add %d %s",
- GET_FIELD(mNetId), GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addRouteToInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- struct MyCallback {
- static void callback(CommandCallback::CallbackType aOriginalCallback,
- CommandChain* aChain,
- bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- NU_DBG("addRouteToInterface's reason: %s", reason.get());
- if (aError && reason.EqualsASCII("addRoute() failed (File exists)")) {
- NU_DBG("Ignore \"File exists\" error when adding host route.");
- return aOriginalCallback(aChain, false, aResult);
- }
- aOriginalCallback(aChain, aError, aResult);
- }
- };
-
- CommandCallback wrappedCallback(MyCallback::callback, aCallback);
- modifyRouteOnInterface(aChain, wrappedCallback, aResult, true);
-}
-
-void NetworkUtils::removeRouteFromInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- modifyRouteOnInterface(aChain, aCallback, aResult, false);
-}
-
-void NetworkUtils::modifyRouteOnInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult,
- bool aDoAdd)
-{
- char command[MAX_COMMAND_SIZE];
-
- // AOSP adds host route to its interface table but it doesn't work for
- // B2G because we cannot set fwmark per application. So, we add
- // all host routes to legacy_system table except scope link route.
-
- nsCString ipOrSubnetIp = NS_ConvertUTF16toUTF8(GET_FIELD(mIp));
- nsCString gatewayOrEmpty;
- const char* legacyOrEmpty = "legacy 0 "; // Add to legacy by default.
- if (GET_FIELD(mGateway).IsEmpty()) {
- ipOrSubnetIp = getSubnetIp(ipOrSubnetIp, GET_FIELD(mPrefixLength));
- legacyOrEmpty = ""; // Add to interface table for scope link route.
- } else {
- gatewayOrEmpty = nsCString(" ") + NS_ConvertUTF16toUTF8(GET_FIELD(mGateway));
- }
-
- const char* action = aDoAdd ? "add" : "remove";
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "network route %s%s %d %s %s/%d%s",
- legacyOrEmpty, action,
- GET_FIELD(mNetId), GET_CHAR(mIfname), ipOrSubnetIp.get(),
- GET_FIELD(mPrefixLength), gatewayOrEmpty.get());
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addDefaultRouteToNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- if (GET_FIELD(mLoopIndex) >= GET_FIELD(mGateways).Length()) {
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- nsTArray<nsString>& gateways = GET_FIELD(mGateways);
- NS_ConvertUTF16toUTF8 autoGateway(gateways[GET_FIELD(mLoopIndex)]);
-
- int type = getIpType(autoGateway.get());
- snprintf(command, MAX_COMMAND_SIZE - 1, "network route add %d %s %s/0 %s",
- GET_FIELD(mNetId), GET_CHAR(mIfname),
- type == AF_INET6 ? "::" : "0.0.0.0", autoGateway.get());
-
- struct MyCallback {
- static void callback(CommandCallback::CallbackType aOriginalCallback,
- CommandChain* aChain,
- bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- NU_DBG("addDefaultRouteToNetwork's reason: %s", reason.get());
- if (aError && !reason.EqualsASCII("addRoute() failed (File exists)")) {
- return aOriginalCallback(aChain, aError, aResult);
- }
-
- GET_FIELD(mLoopIndex)++;
- return addDefaultRouteToNetwork(aChain, aOriginalCallback, aResult);
- }
- };
-
- CommandCallback wrappedCallback(MyCallback::callback, aCallback);
- doCommand(command, aChain, wrappedCallback);
-}
-
-void NetworkUtils::setDefaultNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network default set %d", GET_FIELD(mNetId));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addRouteToSecondaryTable(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult) {
-
- char command[MAX_COMMAND_SIZE];
-
- if (SDK_VERSION >= 20) {
- snprintf(command, MAX_COMMAND_SIZE - 1,
- "network route add %d %s %s/%s %s",
- GET_FIELD(mNetId),
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mGateway));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1,
- "interface route add %s secondary %s %s %s",
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mGateway));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeRouteFromSecondaryTable(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult) {
- char command[MAX_COMMAND_SIZE];
-
- if (SDK_VERSION >= 20) {
- snprintf(command, MAX_COMMAND_SIZE - 1,
- "network route remove %d %s %s/%s %s",
- GET_FIELD(mNetId),
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mGateway));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1,
- "interface route remove %s secondary %s %s %s",
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mGateway));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setIpv6Enabled(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult,
- bool aEnabled)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface ipv6 %s %s",
- GET_CHAR(mIfname), aEnabled ? "enable" : "disable");
-
- struct MyCallback {
- static void callback(CommandCallback::CallbackType aOriginalCallback,
- CommandChain* aChain,
- bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- aOriginalCallback(aChain, false, aResult);
- }
- };
-
- CommandCallback wrappedCallback(MyCallback::callback, aCallback);
- doCommand(command, aChain, wrappedCallback);
-}
-
-void NetworkUtils::enableIpv6(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- setIpv6Enabled(aChain, aCallback, aResult, true);
-}
-
-void NetworkUtils::disableIpv6(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- setIpv6Enabled(aChain, aCallback, aResult, false);
-}
-
-void NetworkUtils::setMtu(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface setmtu %s %ld",
- GET_CHAR(mIfname), GET_FIELD(mMtu));
-
- doCommand(command, aChain, aCallback);
-}
-
-#undef GET_CHAR
-#undef GET_FIELD
-
-/*
- * Netd command success/fail function
- */
-#define ASSIGN_FIELD(prop) aResult.prop = aChain->getParams().prop;
-#define ASSIGN_FIELD_VALUE(prop, value) aResult.prop = value;
-
-template<size_t N>
-void NetworkUtils::runChain(const NetworkParams& aParams,
- const CommandFunc (&aCmds)[N],
- ErrorCallback aError)
-{
- CommandChain* chain = new CommandChain(aParams, aCmds, N, aError);
- gCommandChainQueue.AppendElement(chain);
-
- if (gCommandChainQueue.Length() > 1) {
- NU_DBG("%d command chains are queued. Wait!", gCommandChainQueue.Length());
- return;
- }
-
- NetworkResultOptions result;
- NetworkUtils::next(gCommandChainQueue[0], false, result);
-}
-
-// Called to clean up the command chain and process the queued command chain if any.
-void NetworkUtils::finalizeSuccess(CommandChain* aChain,
- NetworkResultOptions& aResult)
-{
- next(aChain, false, aResult);
-}
-
-void NetworkUtils::wifiTetheringFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- // Notify the main thread.
- postMessage(aOptions, aResult);
-
- // If one of the stages fails, we try roll back to ensure
- // we don't leave the network systems in limbo.
- ASSIGN_FIELD_VALUE(mEnable, false)
- runChain(aOptions, sWifiFailChain, nullptr);
-}
-
-void NetworkUtils::wifiTetheringSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- ASSIGN_FIELD(mEnable)
-
- if (aChain->getParams().mEnable) {
- MOZ_ASSERT(!gWifiTetheringParms);
- gWifiTetheringParms = new NetworkParams(aChain->getParams());
- }
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::usbTetheringFail(NetworkParams& aOptions,
- NetworkResultOptions& aResult)
-{
- // Notify the main thread.
- postMessage(aOptions, aResult);
- // Try to roll back to ensure
- // we don't leave the network systems in limbo.
- // This parameter is used to disable ipforwarding.
- {
- aOptions.mEnable = false;
- runChain(aOptions, sUSBFailChain, nullptr);
- }
-
- // Disable usb rndis function.
- {
- NetworkParams options;
- options.mEnable = false;
- options.mReport = false;
- gNetworkUtils->enableUsbRndis(options);
- }
-}
-
-void NetworkUtils::usbTetheringSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- ASSIGN_FIELD(mEnable)
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::networkInterfaceAlarmFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::networkInterfaceAlarmSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // TODO : error is not used , and it is conflict with boolean type error.
- // params.error = parseFloat(params.resultReason);
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::updateUpStreamFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::updateUpStreamSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- ASSIGN_FIELD(mCurExternalIfname)
- ASSIGN_FIELD(mCurInternalIfname)
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::setDhcpServerFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- aResult.mSuccess = false;
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::setDhcpServerSuccess(CommandChain* aChain, CommandCallback aCallback, NetworkResultOptions& aResult)
-{
- aResult.mSuccess = true;
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::wifiOperationModeFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::wifiOperationModeSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::setDnsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::defaultAsyncSuccessHandler(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- NU_DBG("defaultAsyncSuccessHandler");
- aResult.mRet = true;
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::defaultAsyncFailureHandler(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- aResult.mRet = false;
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::getInterfacesFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::getInterfacesSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char buf[BUF_SIZE];
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- memcpy(buf, reason.get(), strlen(reason.get()));
-
- nsTArray<nsCString> result;
- split(buf, INTERFACE_DELIMIT, result);
-
- nsTArray<nsString> interfaceList;
- uint32_t length = result.Length();
- convertUTF8toUTF16(result, interfaceList, length);
-
- aResult.mInterfaceList.Construct();
- for (uint32_t i = 0; i < length; i++) {
- aResult.mInterfaceList.Value().AppendElement(interfaceList[i], fallible_t());
- }
-
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::getInterfaceConfigFail(NetworkParams& aOptions,
- NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::getInterfaceConfigSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char buf[BUF_SIZE];
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- memcpy(buf, reason.get(), strlen(reason.get()));
-
- nsTArray<nsCString> result;
- split(buf, NETD_MESSAGE_DELIMIT, result);
-
- ASSIGN_FIELD_VALUE(mMacAddr, NS_ConvertUTF8toUTF16(result[0]))
- ASSIGN_FIELD_VALUE(mIpAddr, NS_ConvertUTF8toUTF16(result[1]))
- ASSIGN_FIELD_VALUE(mPrefixLength, atol(result[2].get()))
-
- if (result[3].Find("up")) {
- ASSIGN_FIELD_VALUE(mFlag, NS_ConvertUTF8toUTF16("up"))
- } else {
- ASSIGN_FIELD_VALUE(mFlag, NS_ConvertUTF8toUTF16("down"))
- }
-
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::setInterfaceConfigFail(NetworkParams& aOptions,
- NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::setInterfaceConfigSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-#undef ASSIGN_FIELD
-#undef ASSIGN_FIELD_VALUE
-
-NetworkUtils::NetworkUtils(MessageCallback aCallback)
- : mMessageCallback(aCallback)
-{
- mNetUtils = new NetUtils();
-
- char value[Property::VALUE_MAX_LENGTH];
- Property::Get("ro.build.version.sdk", value, nullptr);
- SDK_VERSION = atoi(value);
-
- Property::Get(IPV6_TETHERING, value, "0");
- SUPPORT_IPV6_TETHERING = atoi(value);
-
- gNetworkUtils = this;
-}
-
-NetworkUtils::~NetworkUtils()
-{
-}
-
-#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aOptions.prop).get()
-#define GET_FIELD(prop) aOptions.prop
-
-// Hoist this type definition to global to avoid template
-// instantiation error on gcc 4.4 used by ICS emulator.
-typedef CommandResult (NetworkUtils::*CommandHandler)(NetworkParams&);
-struct CommandHandlerEntry
-{
- const char* mCommandName;
- CommandHandler mCommandHandler;
-};
-
-void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
-{
- const static CommandHandlerEntry
- COMMAND_HANDLER_TABLE[] = {
-
- // For command 'testCommand', BUILD_ENTRY(testCommand) will generate
- // {"testCommand", NetworkUtils::testCommand}
- #define BUILD_ENTRY(c) {#c, &NetworkUtils::c}
-
- BUILD_ENTRY(removeNetworkRoute),
- BUILD_ENTRY(setDNS),
- BUILD_ENTRY(setDefaultRoute),
- BUILD_ENTRY(removeDefaultRoute),
- BUILD_ENTRY(addHostRoute),
- BUILD_ENTRY(removeHostRoute),
- BUILD_ENTRY(addSecondaryRoute),
- BUILD_ENTRY(removeSecondaryRoute),
- BUILD_ENTRY(setNetworkInterfaceAlarm),
- BUILD_ENTRY(enableNetworkInterfaceAlarm),
- BUILD_ENTRY(disableNetworkInterfaceAlarm),
- BUILD_ENTRY(setTetheringAlarm),
- BUILD_ENTRY(removeTetheringAlarm),
- BUILD_ENTRY(getTetheringStatus),
- BUILD_ENTRY(setWifiOperationMode),
- BUILD_ENTRY(setDhcpServer),
- BUILD_ENTRY(setWifiTethering),
- BUILD_ENTRY(setUSBTethering),
- BUILD_ENTRY(enableUsbRndis),
- BUILD_ENTRY(updateUpStream),
- BUILD_ENTRY(configureInterface),
- BUILD_ENTRY(dhcpRequest),
- BUILD_ENTRY(stopDhcp),
- BUILD_ENTRY(enableInterface),
- BUILD_ENTRY(disableInterface),
- BUILD_ENTRY(resetConnections),
- BUILD_ENTRY(createNetwork),
- BUILD_ENTRY(destroyNetwork),
- BUILD_ENTRY(getNetId),
- BUILD_ENTRY(getInterfaces),
- BUILD_ENTRY(getInterfaceConfig),
- BUILD_ENTRY(setInterfaceConfig),
- BUILD_ENTRY(setMtu),
-
- #undef BUILD_ENTRY
- };
-
- // Loop until we find the command name which matches aOptions.mCmd.
- CommandHandler handler = nullptr;
- for (size_t i = 0; i < mozilla::ArrayLength(COMMAND_HANDLER_TABLE); i++) {
- if (aOptions.mCmd.EqualsASCII(COMMAND_HANDLER_TABLE[i].mCommandName)) {
- handler = COMMAND_HANDLER_TABLE[i].mCommandHandler;
- break;
- }
- }
-
- if (!handler) {
- // Command not found in COMMAND_HANDLER_TABLE.
- WARN("unknown message: %s", NS_ConvertUTF16toUTF8(aOptions.mCmd).get());
- return;
- }
-
- // The handler would return one of the following 3 values
- // to be wrapped to CommandResult:
- //
- // 1) |int32_t| for mostly synchronous native function calls.
- // 2) |NetworkResultOptions| to populate additional results. (e.g. dhcpRequest)
- // 3) |CommandResult::Pending| to indicate the result is not
- // obtained yet.
- //
- // If the handler returns "Pending", the handler should take the
- // responsibility for posting result to main thread.
- CommandResult commandResult = (this->*handler)(aOptions);
- if (!commandResult.isPending()) {
- postMessage(aOptions, commandResult.mResult);
- }
-}
-
-/**
- * Handle received data from netd.
- */
-void NetworkUtils::onNetdMessage(NetdCommand* aCommand)
-{
- char* data = (char*)aCommand->mData;
-
- // get code & reason.
- char* result = strtok(data, NETD_MESSAGE_DELIMIT);
-
- if (!result) {
- nextNetdCommand();
- return;
- }
- uint32_t code = atoi(result);
-
- if (!isBroadcastMessage(code) && SDK_VERSION >= 16) {
- strtok(nullptr, NETD_MESSAGE_DELIMIT);
- }
-
- char* reason = strtok(nullptr, "\0");
-
- if (isBroadcastMessage(code)) {
- NU_DBG("Receiving broadcast message from netd.");
- NU_DBG(" ==> Code: %d Reason: %s", code, reason);
- sendBroadcastMessage(code, reason);
-
- if (code == NETD_COMMAND_INTERFACE_CHANGE) {
- if (gWifiTetheringParms) {
- char linkdownReason[MAX_COMMAND_SIZE];
- snprintf(linkdownReason, MAX_COMMAND_SIZE - 1,
- "Iface linkstate %s down",
- NS_ConvertUTF16toUTF8(gWifiTetheringParms->mIfname).get());
-
- if (!strcmp(reason, linkdownReason)) {
- NU_DBG("Wifi link down, restarting tethering.");
- runChain(*gWifiTetheringParms, sWifiRetryChain, wifiTetheringFail);
- }
- }
- }
-
- nextNetdCommand();
- return;
- }
-
- // Set pending to false before we handle next command.
- NU_DBG("Receiving \"%s\" command response from netd.", gCurrentCommand.command);
- NU_DBG(" ==> Code: %d Reason: %s", code, reason);
-
- gReason.AppendElement(nsCString(reason));
-
- // 1xx response code regards as command is proceeding, we need to wait for
- // final response code such as 2xx, 4xx and 5xx before sending next command.
- if (isProceeding(code)) {
- return;
- }
-
- if (isComplete(code)) {
- gPending = false;
- }
-
- {
- char buf[BUF_SIZE];
- join(gReason, INTERFACE_DELIMIT, BUF_SIZE, buf);
-
- NetworkResultOptions result;
- result.mResultCode = code;
- result.mResultReason = NS_ConvertUTF8toUTF16(buf);
- (gCurrentCommand.callback)(gCurrentCommand.chain, isError(code), result);
- gReason.Clear();
- }
-
- // Handling pending commands if any.
- if (isComplete(code)) {
- nextNetdCommand();
- }
-}
-
-/**
- * Start/Stop DHCP server.
- */
-CommandResult NetworkUtils::setDhcpServer(NetworkParams& aOptions)
-{
- if (aOptions.mEnabled) {
- aOptions.mWifiStartIp = aOptions.mStartIp;
- aOptions.mWifiEndIp = aOptions.mEndIp;
- aOptions.mIp = aOptions.mServerIp;
- aOptions.mPrefix = aOptions.mMaskLength;
- aOptions.mLink = NS_ConvertUTF8toUTF16("up");
-
- runChain(aOptions, sStartDhcpServerChain, setDhcpServerFail);
- } else {
- runChain(aOptions, sStopDhcpServerChain, setDhcpServerFail);
- }
- return CommandResult::Pending();
-}
-
-/**
- * Set DNS servers for given network interface.
- */
-CommandResult NetworkUtils::setDNS(NetworkParams& aOptions)
-{
- uint32_t length = aOptions.mDnses.Length();
-
- if (length > 0) {
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoDns(aOptions.mDnses[i]);
-
- char dns_prop_key[Property::VALUE_MAX_LENGTH];
- SprintfLiteral(dns_prop_key, "net.dns%d", i+1);
- Property::Set(dns_prop_key, autoDns.get());
- }
- } else {
- // Set dnses from system properties.
- IFProperties interfaceProperties;
- getIFProperties(GET_CHAR(mIfname), interfaceProperties);
-
- Property::Set("net.dns1", interfaceProperties.dns1);
- Property::Set("net.dns2", interfaceProperties.dns2);
- }
-
- // Bump the DNS change property.
- char dnschange[Property::VALUE_MAX_LENGTH];
- Property::Get("net.dnschange", dnschange, "0");
-
- char num[Property::VALUE_MAX_LENGTH];
- snprintf(num, Property::VALUE_MAX_LENGTH - 1, "%d", atoi(dnschange) + 1);
- Property::Set("net.dnschange", num);
-
- // DNS needs to be set through netd since JellyBean (4.3).
- if (SDK_VERSION >= 20) {
- // Lollipop.
- static CommandFunc COMMAND_CHAIN[] = {
- setInterfaceDns,
- addDefaultRouteToNetwork,
- defaultAsyncSuccessHandler
- };
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mIfname, &netIdInfo)) {
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, setDnsFail);
- return CommandResult::Pending();
- }
- if (SDK_VERSION >= 18) {
- // JB, KK.
- static CommandFunc COMMAND_CHAIN[] = {
- #if ANDROID_VERSION == 18
- // Since we don't use per-interface DNS lookup feature on JB,
- // we need to set the default DNS interface whenever setting the
- // DNS name server.
- setDefaultInterface,
- #endif
- setInterfaceDns,
- defaultAsyncSuccessHandler
- };
- runChain(aOptions, COMMAND_CHAIN, setDnsFail);
- return CommandResult::Pending();
- }
-
- return SUCCESS;
-}
-
-CommandResult NetworkUtils::configureInterface(NetworkParams& aOptions)
-{
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- return mNetUtils->do_ifc_configure(
- autoIfname.get(),
- aOptions.mIpaddr,
- aOptions.mMask,
- aOptions.mGateway_long,
- aOptions.mDns1_long,
- aOptions.mDns2_long
- );
-}
-
-CommandResult NetworkUtils::stopDhcp(NetworkParams& aOptions)
-{
- return mNetUtils->do_dhcp_stop(GET_CHAR(mIfname));
-}
-
-CommandResult NetworkUtils::dhcpRequest(NetworkParams& aOptions) {
- mozilla::dom::NetworkResultOptions result;
-
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- char ipaddr[Property::VALUE_MAX_LENGTH];
- char gateway[Property::VALUE_MAX_LENGTH];
- uint32_t prefixLength;
- char dns1[Property::VALUE_MAX_LENGTH];
- char dns2[Property::VALUE_MAX_LENGTH];
- char server[Property::VALUE_MAX_LENGTH];
- uint32_t lease;
- char vendorinfo[Property::VALUE_MAX_LENGTH];
- int32_t ret = mNetUtils->do_dhcp_do_request(autoIfname.get(),
- ipaddr,
- gateway,
- &prefixLength,
- dns1,
- dns2,
- server,
- &lease,
- vendorinfo);
-
- RETURN_IF_FAILED(ret);
-
- result.mIpaddr_str = NS_ConvertUTF8toUTF16(ipaddr);
- result.mGateway_str = NS_ConvertUTF8toUTF16(gateway);
- result.mDns1_str = NS_ConvertUTF8toUTF16(dns1);
- result.mDns2_str = NS_ConvertUTF8toUTF16(dns2);
- result.mServer_str = NS_ConvertUTF8toUTF16(server);
- result.mVendor_str = NS_ConvertUTF8toUTF16(vendorinfo);
- result.mLease = lease;
- result.mPrefixLength = prefixLength;
- result.mMask = makeMask(prefixLength);
-
- uint32_t inet4; // only support IPv4 for now.
-
-#define INET_PTON(var, field) \
- PR_BEGIN_MACRO \
- inet_pton(AF_INET, var, &inet4); \
- result.field = inet4; \
- PR_END_MACRO
-
- INET_PTON(ipaddr, mIpaddr);
- INET_PTON(gateway, mGateway);
-
- if (dns1[0] != '\0') {
- INET_PTON(dns1, mDns1);
- }
-
- if (dns2[0] != '\0') {
- INET_PTON(dns2, mDns2);
- }
-
- INET_PTON(server, mServer);
-
- char inet_str[64];
- if (inet_ntop(AF_INET, &result.mMask, inet_str, sizeof(inet_str))) {
- result.mMask_str = NS_ConvertUTF8toUTF16(inet_str);
- }
-
- return result;
-}
-
-CommandResult NetworkUtils::enableInterface(NetworkParams& aOptions) {
- return mNetUtils->do_ifc_enable(
- NS_ConvertUTF16toUTF8(aOptions.mIfname).get());
-}
-
-CommandResult NetworkUtils::disableInterface(NetworkParams& aOptions) {
- return mNetUtils->do_ifc_disable(
- NS_ConvertUTF16toUTF8(aOptions.mIfname).get());
-}
-
-CommandResult NetworkUtils::resetConnections(NetworkParams& aOptions) {
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- return mNetUtils->do_ifc_reset_connections(
- NS_ConvertUTF16toUTF8(aOptions.mIfname).get(),
- RESET_ALL_ADDRESSES);
-}
-
-/**
- * Set default route and DNS servers for given network interface.
- */
-CommandResult NetworkUtils::setDefaultRoute(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return setDefaultRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- addDefaultRouteToNetwork,
- setDefaultNetwork,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No such interface");
- return -1;
- }
-
- aOptions.mNetId = netIdInfo.mNetId;
- aOptions.mLoopIndex = 0;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * Set default route and DNS servers for given network interface by obsoleted libnetutils.
- */
-CommandResult NetworkUtils::setDefaultRouteLegacy(NetworkParams& aOptions)
-{
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
-
- uint32_t length = aOptions.mGateways.Length();
- if (length > 0) {
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[i]);
-
- int type = getIpType(autoGateway.get());
- if (type != AF_INET && type != AF_INET6) {
- continue;
- }
-
- if (type == AF_INET6) {
- RETURN_IF_FAILED(mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, autoGateway.get()));
- } else { /* type == AF_INET */
- RETURN_IF_FAILED(mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(autoGateway.get())));
- }
- }
- } else {
- // Set default froute from system properties.
- char key[Property::KEY_MAX_LENGTH];
- char gateway[Property::KEY_MAX_LENGTH];
-
- snprintf(key, sizeof key - 1, "net.%s.gw", autoIfname.get());
- Property::Get(key, gateway, "");
-
- int type = getIpType(gateway);
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- if (type == AF_INET6) {
- RETURN_IF_FAILED(mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, gateway));
- } else { /* type == AF_INET */
- RETURN_IF_FAILED(mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(gateway)));
- }
- }
-
- // Set the default DNS interface.
- if (SDK_VERSION >= 18) {
- // For JB, KK only.
- static CommandFunc COMMAND_CHAIN[] = {
- setDefaultInterface,
- defaultAsyncSuccessHandler
- };
- runChain(aOptions, COMMAND_CHAIN, setDnsFail);
- return CommandResult::Pending();
- }
-
- return SUCCESS;
-}
-
-/**
- * Remove default route for given network interface.
- */
-CommandResult NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
-{
- NU_DBG("Calling NetworkUtils::removeDefaultRoute");
-
- if (SDK_VERSION < 20) {
- return removeDefaultRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- removeDefaultRoute,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mIfname));
- return -1;
- }
-
- NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
-
- aOptions.mNetId = netIdInfo.mNetId;
- aOptions.mLoopIndex = 0;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * Remove default route for given network interface by obsoleted libnetutils.
- */
-CommandResult NetworkUtils::removeDefaultRouteLegacy(NetworkParams& aOptions)
-{
- // Legacy libnetutils calls before Lollipop.
- uint32_t length = aOptions.mGateways.Length();
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[i]);
-
- int type = getIpType(autoGateway.get());
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- WARN_IF_FAILED(mNetUtils->do_ifc_remove_route(GET_CHAR(mIfname),
- type == AF_INET ? "0.0.0.0" : "::",
- 0, autoGateway.get()));
- }
-
- return SUCCESS;
-}
-
-/**
- * Add host route for given network interface.
- */
-CommandResult NetworkUtils::addHostRoute(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return addHostRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- addRouteToInterface,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mIfname));
- return -1;
- }
-
- NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
-
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * Add host route for given network interface.
- */
-CommandResult NetworkUtils::addHostRouteLegacy(NetworkParams& aOptions)
-{
- if (aOptions.mGateway.IsEmpty()) {
- ERROR("addHostRouteLegacy does not support empty gateway.");
- return EINVAL;
- }
-
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- NS_ConvertUTF16toUTF8 autoHostname(aOptions.mIp);
- NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateway);
- int type, prefix;
-
- type = getIpType(autoHostname.get());
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- if (type != getIpType(autoGateway.get())) {
- return EINVAL;
- }
-
- prefix = type == AF_INET ? 32 : 128;
- return mNetUtils->do_ifc_add_route(autoIfname.get(), autoHostname.get(),
- prefix, autoGateway.get());
-}
-
-/**
- * Remove host route for given network interface.
- */
-CommandResult NetworkUtils::removeHostRoute(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return removeHostRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- removeRouteFromInterface,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mIfname));
- return -1;
- }
-
- NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
-
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * Remove host route for given network interface.
- */
-CommandResult NetworkUtils::removeHostRouteLegacy(NetworkParams& aOptions)
-{
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- NS_ConvertUTF16toUTF8 autoHostname(aOptions.mIp);
- NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateway);
- int type, prefix;
-
- type = getIpType(autoHostname.get());
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- if (type != getIpType(autoGateway.get())) {
- return EINVAL;
- }
-
- prefix = type == AF_INET ? 32 : 128;
- return mNetUtils->do_ifc_remove_route(autoIfname.get(), autoHostname.get(),
- prefix, autoGateway.get());
-}
-
-CommandResult NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return removeNetworkRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- clearAddrForInterface,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("interface %s is not present in any network", GET_CHAR(mIfname));
- return -1;
- }
-
- NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
-
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-nsCString NetworkUtils::getSubnetIp(const nsCString& aIp, int aPrefixLength)
-{
- int type = getIpType(aIp.get());
-
- if (AF_INET6 == type) {
- struct in6_addr in6;
- if (inet_pton(AF_INET6, aIp.get(), &in6) != 1) {
- return nsCString();
- }
-
- uint32_t p, i, p1, mask;
- p = aPrefixLength;
- i = 0;
- while (i < 4) {
- p1 = p > 32 ? 32 : p;
- p -= p1;
- mask = p1 ? ~0x0 << (32 - p1) : 0;
- in6.s6_addr32[i++] &= htonl(mask);
- }
-
- char subnetStr[INET6_ADDRSTRLEN];
- if (!inet_ntop(AF_INET6, &in6, subnetStr, sizeof subnetStr)) {
- return nsCString();
- }
-
- return nsCString(subnetStr);
- }
-
- if (AF_INET == type) {
- uint32_t ip = inet_addr(aIp.get());
- uint32_t netmask = makeMask(aPrefixLength);
- uint32_t subnet = ip & netmask;
- struct in_addr addr;
- addr.s_addr = subnet;
- return nsCString(inet_ntoa(addr));
- }
-
- return nsCString();
-}
-
-CommandResult NetworkUtils::removeNetworkRouteLegacy(NetworkParams& aOptions)
-{
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- NS_ConvertUTF16toUTF8 autoIp(aOptions.mIp);
-
- int type = getIpType(autoIp.get());
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- uint32_t prefixLength = GET_FIELD(mPrefixLength);
-
- if (type == AF_INET6) {
- // Calculate subnet.
- struct in6_addr in6;
- if (inet_pton(AF_INET6, autoIp.get(), &in6) != 1) {
- return EINVAL;
- }
-
- uint32_t p, i, p1, mask;
- p = prefixLength;
- i = 0;
- while (i < 4) {
- p1 = p > 32 ? 32 : p;
- p -= p1;
- mask = p1 ? ~0x0 << (32 - p1) : 0;
- in6.s6_addr32[i++] &= htonl(mask);
- }
-
- char subnetStr[INET6_ADDRSTRLEN];
- if (!inet_ntop(AF_INET6, &in6, subnetStr, sizeof subnetStr)) {
- return EINVAL;
- }
-
- // Remove default route.
- WARN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), "::", 0, NULL));
-
- // Remove subnet route.
- RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), subnetStr, prefixLength, NULL));
- return SUCCESS;
- }
-
- /* type == AF_INET */
- uint32_t ip = inet_addr(autoIp.get());
- uint32_t netmask = makeMask(prefixLength);
- uint32_t subnet = ip & netmask;
- const char* gateway = "0.0.0.0";
- struct in_addr addr;
- addr.s_addr = subnet;
- const char* dst = inet_ntoa(addr);
-
- RETURN_IF_FAILED(mNetUtils->do_ifc_remove_default_route(autoIfname.get()));
- RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), dst, prefixLength, gateway));
- return SUCCESS;
-}
-
-CommandResult NetworkUtils::addSecondaryRoute(NetworkParams& aOptions)
-{
- static CommandFunc COMMAND_CHAIN[] = {
- addRouteToSecondaryTable,
- defaultAsyncSuccessHandler
- };
-
- if (SDK_VERSION >= 20) {
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mIfname, &netIdInfo)) {
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- }
-
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::removeSecondaryRoute(NetworkParams& aOptions)
-{
- static CommandFunc COMMAND_CHAIN[] = {
- removeRouteFromSecondaryTable,
- defaultAsyncSuccessHandler
- };
-
- if (SDK_VERSION >= 20) {
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mIfname, &netIdInfo)) {
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- }
-
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::setNetworkInterfaceAlarm(NetworkParams& aOptions)
-{
- NU_DBG("setNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
- runChain(aOptions, sNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::enableNetworkInterfaceAlarm(NetworkParams& aOptions)
-{
- NU_DBG("enableNetworkInterfaceAlarm: %s", GET_CHAR(mIfname));
- runChain(aOptions, sNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions)
-{
- NU_DBG("disableNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
- runChain(aOptions, sNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::setTetheringAlarm(NetworkParams& aOptions)
-{
- NU_DBG("setTetheringAlarm");
- runChain(aOptions, sTetheringInterfaceSetAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::removeTetheringAlarm(NetworkParams& aOptions)
-{
- NU_DBG("removeTetheringAlarm");
- runChain(aOptions, sTetheringInterfaceRemoveAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::getTetheringStatus(NetworkParams& aOptions)
-{
- NU_DBG("getTetheringStatus");
- runChain(aOptions, sTetheringGetStatusChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-/**
- * handling main thread's reload Wifi firmware request
- */
-CommandResult NetworkUtils::setWifiOperationMode(NetworkParams& aOptions)
-{
- NU_DBG("setWifiOperationMode: %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
- runChain(aOptions, sWifiOperationModeChain, wifiOperationModeFail);
- return CommandResult::Pending();
-}
-
-/**
- * handling main thread's enable/disable WiFi Tethering request
- */
-CommandResult NetworkUtils::setWifiTethering(NetworkParams& aOptions)
-{
- bool enable = aOptions.mEnable;
- IFProperties interfaceProperties;
- getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
-
- if (strcmp(interfaceProperties.dns1, "")) {
- int type = getIpType(interfaceProperties.dns1);
- if (type != AF_INET6) {
- aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
- }
- }
- if (strcmp(interfaceProperties.dns2, "")) {
- int type = getIpType(interfaceProperties.dns2);
- if (type != AF_INET6) {
- aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
- }
- }
- dumpParams(aOptions, "WIFI");
-
- if (SDK_VERSION >= 20) {
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mExternalIfname, &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mExternalIfname));
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- }
-
- if (enable) {
- NU_DBG("Starting Wifi Tethering on %s <-> %s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- runChain(aOptions, sWifiEnableChain, wifiTetheringFail);
- } else {
- NU_DBG("Stopping Wifi Tethering on %s <-> %s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- runChain(aOptions, sWifiDisableChain, wifiTetheringFail);
- }
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::setUSBTethering(NetworkParams& aOptions)
-{
- bool enable = aOptions.mEnable;
- IFProperties interfaceProperties;
- getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
-
- if (strcmp(interfaceProperties.dns1, "")) {
- int type = getIpType(interfaceProperties.dns1);
- if (type != AF_INET6) {
- aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
- }
- }
- if (strcmp(interfaceProperties.dns2, "")) {
- int type = getIpType(interfaceProperties.dns2);
- if (type != AF_INET6) {
- aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
- }
- }
- dumpParams(aOptions, "USB");
-
- if (SDK_VERSION >= 20) {
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mExternalIfname, &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mExternalIfname));
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- }
-
- if (enable) {
- NU_DBG("Starting USB Tethering on %s <-> %s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- runChain(aOptions, sUSBEnableChain, usbTetheringFail);
- } else {
- NU_DBG("Stopping USB Tethering on %s <-> %s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- runChain(aOptions, sUSBDisableChain, usbTetheringFail);
- }
- return CommandResult::Pending();
-}
-
-void NetworkUtils::escapeQuote(nsCString& aString)
-{
- aString.ReplaceSubstring("\\", "\\\\");
- aString.ReplaceSubstring("\"", "\\\"");
-}
-
-CommandResult NetworkUtils::checkUsbRndisState(NetworkParams& aOptions)
-{
- static uint32_t retry = 0;
-
- char currentState[Property::VALUE_MAX_LENGTH];
- Property::Get(SYS_USB_STATE_PROPERTY, currentState, nullptr);
-
- nsTArray<nsCString> stateFuncs;
- split(currentState, USB_CONFIG_DELIMIT, stateFuncs);
- bool rndisPresent = stateFuncs.Contains(nsCString(USB_FUNCTION_RNDIS));
-
- if (aOptions.mEnable == rndisPresent) {
- NetworkResultOptions result;
- result.mEnable = aOptions.mEnable;
- result.mResult = true;
- retry = 0;
- return result;
- }
- if (retry < USB_FUNCTION_RETRY_TIMES) {
- retry++;
- usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
- return checkUsbRndisState(aOptions);
- }
-
- NetworkResultOptions result;
- result.mResult = false;
- retry = 0;
- return result;
-}
-
-/**
- * Modify usb function's property to turn on USB RNDIS function
- */
-CommandResult NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
-{
- bool report = aOptions.mReport;
-
- // For some reason, rndis doesn't play well with diag,modem,nmea.
- // So when turning rndis on, we set sys.usb.config to either "rndis"
- // or "rndis,adb". When turning rndis off, we go back to
- // persist.sys.usb.config.
- //
- // On the otoro/unagi, persist.sys.usb.config should be one of:
- //
- // diag,modem,nmea,mass_storage
- // diag,modem,nmea,mass_storage,adb
- //
- // When rndis is enabled, sys.usb.config should be one of:
- //
- // rdnis
- // rndis,adb
- //
- // and when rndis is disabled, it should revert to persist.sys.usb.config
-
- char currentConfig[Property::VALUE_MAX_LENGTH];
- Property::Get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
-
- nsTArray<nsCString> configFuncs;
- split(currentConfig, USB_CONFIG_DELIMIT, configFuncs);
-
- char persistConfig[Property::VALUE_MAX_LENGTH];
- Property::Get(PERSIST_SYS_USB_CONFIG_PROPERTY, persistConfig, nullptr);
-
- nsTArray<nsCString> persistFuncs;
- split(persistConfig, USB_CONFIG_DELIMIT, persistFuncs);
-
- if (aOptions.mEnable) {
- configFuncs.Clear();
- configFuncs.AppendElement(nsCString(USB_FUNCTION_RNDIS));
- if (persistFuncs.Contains(nsCString(USB_FUNCTION_ADB))) {
- configFuncs.AppendElement(nsCString(USB_FUNCTION_ADB));
- }
- } else {
- // We're turning rndis off, revert back to the persist setting.
- // adb will already be correct there, so we don't need to do any
- // further adjustments.
- configFuncs = persistFuncs;
- }
-
- char newConfig[Property::VALUE_MAX_LENGTH] = "";
- Property::Get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
- join(configFuncs, USB_CONFIG_DELIMIT, Property::VALUE_MAX_LENGTH, newConfig);
- if (strcmp(currentConfig, newConfig)) {
- Property::Set(SYS_USB_CONFIG_PROPERTY, newConfig);
- }
-
- // Trigger the timer to check usb state and report the result to NetworkManager.
- if (report) {
- usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
- return checkUsbRndisState(aOptions);
- }
- return SUCCESS;
-}
-
-/**
- * handling upstream interface change event.
- */
-CommandResult NetworkUtils::updateUpStream(NetworkParams& aOptions)
-{
- runChain(aOptions, sUpdateUpStreamChain, updateUpStreamFail);
- return CommandResult::Pending();
-}
-
-/**
- * handling upstream interface change event.
- */
-CommandResult NetworkUtils::createNetwork(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return SUCCESS;
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- createNetwork,
- enableIpv6,
- addInterfaceToNetwork,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- mNetIdManager.acquire(GET_FIELD(mIfname), &netIdInfo);
- if (netIdInfo.mRefCnt > 1) {
- // Already created. Just return.
- NU_DBG("Interface %s (%d) has been created.", GET_CHAR(mIfname),
- netIdInfo.mNetId);
- return SUCCESS;
- }
-
- NU_DBG("Request netd to create a network with netid %d", netIdInfo.mNetId);
- // Newly created netid. Ask netd to create network.
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * handling upstream interface change event.
- */
-CommandResult NetworkUtils::destroyNetwork(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return SUCCESS;
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- disableIpv6,
- destroyNetwork,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.release(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No existing netid for %s", GET_CHAR(mIfname));
- return -1;
- }
-
- if (netIdInfo.mRefCnt > 0) {
- // Still be referenced. Just return.
- NU_DBG("Someone is still using this interface.");
- return SUCCESS;
- }
-
- NU_DBG("Interface %s (%d) is no longer used. Tell netd to destroy.",
- GET_CHAR(mIfname), netIdInfo.mNetId);
-
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
- return CommandResult::Pending();
-}
-
-/**
- * Query the netId associated with the given network interface name.
- */
-CommandResult NetworkUtils::getNetId(NetworkParams& aOptions)
-{
- NetworkResultOptions result;
-
- if (SDK_VERSION < 20) {
- // For pre-Lollipop, use the interface name as the fallback.
- result.mNetId = GET_FIELD(mIfname);
- return result;
- }
-
- NetIdManager::NetIdInfo netIdInfo;
- if (-1 == mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- return ESRCH;
- }
- result.mNetId.AppendInt(netIdInfo.mNetId, 10);
- return result;
-}
-
-/**
- * Get existing network interfaces.
- */
-CommandResult NetworkUtils::getInterfaces(NetworkParams& aOptions)
-{
- runChain(aOptions, sGetInterfacesChain, getInterfacesFail);
- return CommandResult::Pending();
-}
-
-/**
- * Get network config of a specified interface.
- */
-CommandResult NetworkUtils::getInterfaceConfig(NetworkParams& aOptions)
-{
- runChain(aOptions, sGetInterfaceConfigChain, getInterfaceConfigFail);
- return CommandResult::Pending();
-}
-
-/**
- * Set network config for a specified interface.
- */
-CommandResult NetworkUtils::setInterfaceConfig(NetworkParams& aOptions)
-{
- runChain(aOptions, sSetInterfaceConfigChain, setInterfaceConfigFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::setMtu(NetworkParams& aOptions)
-{
- // Setting/getting mtu is supported since Kitkat.
- if (SDK_VERSION < 19) {
- ERROR("setMtu is not supported in current SDK_VERSION.");
- return -1;
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- setMtu,
- defaultAsyncSuccessHandler,
- };
-
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
- return CommandResult::Pending();
-}
-
-void NetworkUtils::sendBroadcastMessage(uint32_t code, char* reason)
-{
- NetworkResultOptions result;
- switch(code) {
- case NETD_COMMAND_INTERFACE_CHANGE:
- result.mTopic = NS_ConvertUTF8toUTF16("netd-interface-change");
- break;
- case NETD_COMMAND_BANDWIDTH_CONTROLLER:
- result.mTopic = NS_ConvertUTF8toUTF16("netd-bandwidth-control");
- break;
- default:
- return;
- }
-
- result.mBroadcast = true;
- result.mReason = NS_ConvertUTF8toUTF16(reason);
- postMessage(result);
-}
-
-inline uint32_t NetworkUtils::netdResponseType(uint32_t code)
-{
- return (code / 100) * 100;
-}
-
-inline bool NetworkUtils::isBroadcastMessage(uint32_t code)
-{
- uint32_t type = netdResponseType(code);
- return type == NETD_COMMAND_UNSOLICITED;
-}
-
-inline bool NetworkUtils::isError(uint32_t code)
-{
- uint32_t type = netdResponseType(code);
- return type != NETD_COMMAND_PROCEEDING && type != NETD_COMMAND_OKAY;
-}
-
-inline bool NetworkUtils::isComplete(uint32_t code)
-{
- uint32_t type = netdResponseType(code);
- return type != NETD_COMMAND_PROCEEDING;
-}
-
-inline bool NetworkUtils::isProceeding(uint32_t code)
-{
- uint32_t type = netdResponseType(code);
- return type == NETD_COMMAND_PROCEEDING;
-}
-
-void NetworkUtils::dumpParams(NetworkParams& aOptions, const char* aType)
-{
-#ifdef _DEBUG
- NU_DBG("Dump params:");
- NU_DBG(" ifname: %s", GET_CHAR(mIfname));
- NU_DBG(" ip: %s", GET_CHAR(mIp));
- NU_DBG(" link: %s", GET_CHAR(mLink));
- NU_DBG(" prefix: %s", GET_CHAR(mPrefix));
- NU_DBG(" wifiStartIp: %s", GET_CHAR(mWifiStartIp));
- NU_DBG(" wifiEndIp: %s", GET_CHAR(mWifiEndIp));
- NU_DBG(" usbStartIp: %s", GET_CHAR(mUsbStartIp));
- NU_DBG(" usbEndIp: %s", GET_CHAR(mUsbEndIp));
- NU_DBG(" dnsserver1: %s", GET_CHAR(mDns1));
- NU_DBG(" dnsserver2: %s", GET_CHAR(mDns2));
- NU_DBG(" internalIfname: %s", GET_CHAR(mInternalIfname));
- NU_DBG(" externalIfname: %s", GET_CHAR(mExternalIfname));
- if (!strcmp(aType, "WIFI")) {
- NU_DBG(" wifictrlinterfacename: %s", GET_CHAR(mWifictrlinterfacename));
- NU_DBG(" ssid: %s", GET_CHAR(mSsid));
- NU_DBG(" security: %s", GET_CHAR(mSecurity));
- NU_DBG(" key: %s", GET_CHAR(mKey));
- }
-#endif
-}
-
-#undef GET_CHAR
-#undef GET_FIELD
diff --git a/dom/system/gonk/NetworkUtils.h b/dom/system/gonk/NetworkUtils.h
deleted file mode 100644
index d1af35f09..000000000
--- a/dom/system/gonk/NetworkUtils.h
+++ /dev/null
@@ -1,498 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef NetworkUtils_h
-#define NetworkUtils_h
-
-#include "nsAutoPtr.h"
-#include "nsString.h"
-#include "mozilla/dom/NetworkOptionsBinding.h"
-#include "mozilla/dom/network/NetUtils.h"
-#include "mozilla/ipc/Netd.h"
-#include "nsTArray.h"
-#include "NetIdManager.h"
-
-class NetworkParams;
-class CommandChain;
-
-class CommandCallback {
-public:
- typedef void (*CallbackType)(CommandChain*, bool,
- mozilla::dom::NetworkResultOptions& aResult);
-
- typedef void (*CallbackWrapperType)(CallbackType aOriginalCallback,
- CommandChain*, bool,
- mozilla::dom::NetworkResultOptions& aResult);
-
- CommandCallback()
- : mCallback(nullptr)
- , mCallbackWrapper(nullptr)
- {
- }
-
- CommandCallback(CallbackType aCallback)
- : mCallback(aCallback)
- , mCallbackWrapper(nullptr)
- {
- }
-
- CommandCallback(CallbackWrapperType aCallbackWrapper,
- CommandCallback aOriginalCallback)
- : mCallback(aOriginalCallback.mCallback)
- , mCallbackWrapper(aCallbackWrapper)
- {
- }
-
- void operator()(CommandChain* aChain, bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- if (mCallbackWrapper) {
- return mCallbackWrapper(mCallback, aChain, aError, aResult);
- }
- if (mCallback) {
- return mCallback(aChain, aError, aResult);
- }
- }
-
-private:
- CallbackType mCallback;
- CallbackWrapperType mCallbackWrapper;
-};
-
-typedef void (*CommandFunc)(CommandChain*, CommandCallback,
- mozilla::dom::NetworkResultOptions& aResult);
-typedef void (*MessageCallback)(mozilla::dom::NetworkResultOptions& aResult);
-typedef void (*ErrorCallback)(NetworkParams& aOptions,
- mozilla::dom::NetworkResultOptions& aResult);
-
-class NetworkParams
-{
-public:
- NetworkParams() {
- }
-
- NetworkParams(const mozilla::dom::NetworkCommandOptions& aOther) {
-
-#define COPY_SEQUENCE_FIELD(prop, type) \
- if (aOther.prop.WasPassed()) { \
- mozilla::dom::Sequence<type > const & currentValue = aOther.prop.InternalValue(); \
- uint32_t length = currentValue.Length(); \
- for (uint32_t idx = 0; idx < length; idx++) { \
- prop.AppendElement(currentValue[idx]); \
- } \
- }
-
-#define COPY_OPT_STRING_FIELD(prop, defaultValue) \
- if (aOther.prop.WasPassed()) { \
- if (aOther.prop.Value().EqualsLiteral("null")) { \
- prop = defaultValue; \
- } else { \
- prop = aOther.prop.Value(); \
- } \
- } else { \
- prop = defaultValue; \
- }
-
-#define COPY_OPT_FIELD(prop, defaultValue) \
- if (aOther.prop.WasPassed()) { \
- prop = aOther.prop.Value(); \
- } else { \
- prop = defaultValue; \
- }
-
-#define COPY_FIELD(prop) prop = aOther.prop;
-
- COPY_FIELD(mId)
- COPY_FIELD(mCmd)
- COPY_OPT_STRING_FIELD(mDomain, EmptyString())
- COPY_OPT_STRING_FIELD(mGateway, EmptyString())
- COPY_SEQUENCE_FIELD(mGateways, nsString)
- COPY_OPT_STRING_FIELD(mIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mIp, EmptyString())
- COPY_OPT_FIELD(mPrefixLength, 0)
- COPY_OPT_STRING_FIELD(mMode, EmptyString())
- COPY_OPT_FIELD(mReport, false)
- COPY_OPT_FIELD(mEnabled, false)
- COPY_OPT_STRING_FIELD(mWifictrlinterfacename, EmptyString())
- COPY_OPT_STRING_FIELD(mInternalIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mExternalIfname, EmptyString())
- COPY_OPT_FIELD(mEnable, false)
- COPY_OPT_STRING_FIELD(mSsid, EmptyString())
- COPY_OPT_STRING_FIELD(mSecurity, EmptyString())
- COPY_OPT_STRING_FIELD(mKey, EmptyString())
- COPY_OPT_STRING_FIELD(mPrefix, EmptyString())
- COPY_OPT_STRING_FIELD(mLink, EmptyString())
- COPY_SEQUENCE_FIELD(mInterfaceList, nsString)
- COPY_OPT_STRING_FIELD(mWifiStartIp, EmptyString())
- COPY_OPT_STRING_FIELD(mWifiEndIp, EmptyString())
- COPY_OPT_STRING_FIELD(mUsbStartIp, EmptyString())
- COPY_OPT_STRING_FIELD(mUsbEndIp, EmptyString())
- COPY_OPT_STRING_FIELD(mDns1, EmptyString())
- COPY_OPT_STRING_FIELD(mDns2, EmptyString())
- COPY_SEQUENCE_FIELD(mDnses, nsString)
- COPY_OPT_STRING_FIELD(mStartIp, EmptyString())
- COPY_OPT_STRING_FIELD(mEndIp, EmptyString())
- COPY_OPT_STRING_FIELD(mServerIp, EmptyString())
- COPY_OPT_STRING_FIELD(mMaskLength, EmptyString())
- COPY_OPT_STRING_FIELD(mPreInternalIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mPreExternalIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mCurInternalIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mCurExternalIfname, EmptyString())
- COPY_OPT_FIELD(mThreshold, -1)
- COPY_OPT_FIELD(mIpaddr, 0)
- COPY_OPT_FIELD(mMask, 0)
- COPY_OPT_FIELD(mGateway_long, 0)
- COPY_OPT_FIELD(mDns1_long, 0)
- COPY_OPT_FIELD(mDns2_long, 0)
- COPY_OPT_FIELD(mMtu, 0)
-
- mLoopIndex = 0;
-
-#undef COPY_SEQUENCE_FIELD
-#undef COPY_OPT_STRING_FIELD
-#undef COPY_OPT_FIELD
-#undef COPY_FIELD
- }
-
- // Followings attributes are 1-to-1 mapping to NetworkCommandOptions.
- int32_t mId;
- nsString mCmd;
- nsString mDomain;
- nsString mGateway;
- nsTArray<nsString> mGateways;
- nsString mIfname;
- nsString mIp;
- uint32_t mPrefixLength;
- nsString mMode;
- bool mReport;
- bool mEnabled;
- nsString mWifictrlinterfacename;
- nsString mInternalIfname;
- nsString mExternalIfname;
- bool mEnable;
- nsString mSsid;
- nsString mSecurity;
- nsString mKey;
- nsString mPrefix;
- nsString mLink;
- nsTArray<nsString> mInterfaceList;
- nsString mWifiStartIp;
- nsString mWifiEndIp;
- nsString mUsbStartIp;
- nsString mUsbEndIp;
- nsString mDns1;
- nsString mDns2;
- nsTArray<nsString> mDnses;
- nsString mStartIp;
- nsString mEndIp;
- nsString mServerIp;
- nsString mMaskLength;
- nsString mPreInternalIfname;
- nsString mPreExternalIfname;
- nsString mCurInternalIfname;
- nsString mCurExternalIfname;
- long long mThreshold;
- long mIpaddr;
- long mMask;
- long mGateway_long;
- long mDns1_long;
- long mDns2_long;
- long mMtu;
-
- // Auxiliary information required to carry accros command chain.
- int mNetId; // A locally defined id per interface.
- uint32_t mLoopIndex; // Loop index for adding/removing multiple gateways.
-};
-
-// CommandChain store the necessary information to execute command one by one.
-// Including :
-// 1. Command parameters.
-// 2. Command list.
-// 3. Error callback function.
-// 4. Index of current execution command.
-class CommandChain final
-{
-public:
- CommandChain(const NetworkParams& aParams,
- const CommandFunc aCmds[],
- uint32_t aLength,
- ErrorCallback aError)
- : mIndex(-1)
- , mParams(aParams)
- , mCommands(aCmds)
- , mLength(aLength)
- , mError(aError) {
- }
-
- NetworkParams&
- getParams()
- {
- return mParams;
- };
-
- CommandFunc
- getNextCommand()
- {
- mIndex++;
- return mIndex < mLength ? mCommands[mIndex] : nullptr;
- };
-
- ErrorCallback
- getErrorCallback() const
- {
- return mError;
- };
-
-private:
- uint32_t mIndex;
- NetworkParams mParams;
- const CommandFunc* mCommands;
- uint32_t mLength;
- ErrorCallback mError;
-};
-
-// A helper class to easily construct a resolved
-// or a pending result for command execution.
-class CommandResult
-{
-public:
- struct Pending {};
-
-public:
- CommandResult(int32_t aResultCode);
- CommandResult(const mozilla::dom::NetworkResultOptions& aResult);
- CommandResult(const Pending&);
- bool isPending() const;
-
- mozilla::dom::NetworkResultOptions mResult;
-
-private:
- bool mIsPending;
-};
-
-class NetworkUtils final
-{
-public:
- NetworkUtils(MessageCallback aCallback);
- ~NetworkUtils();
-
- void ExecuteCommand(NetworkParams aOptions);
- void onNetdMessage(mozilla::ipc::NetdCommand* aCommand);
-
- MessageCallback getMessageCallback() { return mMessageCallback; }
-
-private:
- /**
- * Commands supported by NetworkUtils.
- */
- CommandResult configureInterface(NetworkParams& aOptions);
- CommandResult dhcpRequest(NetworkParams& aOptions);
- CommandResult stopDhcp(NetworkParams& aOptions);
- CommandResult enableInterface(NetworkParams& aOptions);
- CommandResult disableInterface(NetworkParams& aOptions);
- CommandResult resetConnections(NetworkParams& aOptions);
- CommandResult setDefaultRoute(NetworkParams& aOptions);
- CommandResult addHostRoute(NetworkParams& aOptions);
- CommandResult removeDefaultRoute(NetworkParams& aOptions);
- CommandResult removeHostRoute(NetworkParams& aOptions);
- CommandResult removeNetworkRoute(NetworkParams& aOptions);
- CommandResult setDNS(NetworkParams& aOptions);
- CommandResult addSecondaryRoute(NetworkParams& aOptions);
- CommandResult removeSecondaryRoute(NetworkParams& aOptions);
- CommandResult setNetworkInterfaceAlarm(NetworkParams& aOptions);
- CommandResult enableNetworkInterfaceAlarm(NetworkParams& aOptions);
- CommandResult disableNetworkInterfaceAlarm(NetworkParams& aOptions);
- CommandResult setTetheringAlarm(NetworkParams& aOptions);
- CommandResult removeTetheringAlarm(NetworkParams& aOptions);
- CommandResult getTetheringStatus(NetworkParams& aOptions);
- CommandResult setWifiOperationMode(NetworkParams& aOptions);
- CommandResult setDhcpServer(NetworkParams& aOptions);
- CommandResult setWifiTethering(NetworkParams& aOptions);
- CommandResult setUSBTethering(NetworkParams& aOptions);
- CommandResult enableUsbRndis(NetworkParams& aOptions);
- CommandResult updateUpStream(NetworkParams& aOptions);
- CommandResult createNetwork(NetworkParams& aOptions);
- CommandResult destroyNetwork(NetworkParams& aOptions);
- CommandResult getNetId(NetworkParams& aOptions);
- CommandResult setMtu(NetworkParams& aOptions);
- CommandResult getInterfaces(NetworkParams& aOptions);
- CommandResult getInterfaceConfig(NetworkParams& aOptions);
- CommandResult setInterfaceConfig(NetworkParams& aOptions);
-
- CommandResult addHostRouteLegacy(NetworkParams& aOptions);
- CommandResult removeHostRouteLegacy(NetworkParams& aOptions);
- CommandResult setDefaultRouteLegacy(NetworkParams& aOptions);
- CommandResult removeDefaultRouteLegacy(NetworkParams& aOptions);
- CommandResult removeNetworkRouteLegacy(NetworkParams& aOptions);
-
-
- /**
- * function pointer array holds all netd commands should be executed
- * in sequence to accomplish a given command by other module.
- */
- static const CommandFunc sWifiEnableChain[];
- static const CommandFunc sWifiDisableChain[];
- static const CommandFunc sWifiFailChain[];
- static const CommandFunc sWifiRetryChain[];
- static const CommandFunc sWifiOperationModeChain[];
- static const CommandFunc sUSBEnableChain[];
- static const CommandFunc sUSBDisableChain[];
- static const CommandFunc sUSBFailChain[];
- static const CommandFunc sUpdateUpStreamChain[];
- static const CommandFunc sStartDhcpServerChain[];
- static const CommandFunc sStopDhcpServerChain[];
- static const CommandFunc sNetworkInterfaceEnableAlarmChain[];
- static const CommandFunc sNetworkInterfaceDisableAlarmChain[];
- static const CommandFunc sNetworkInterfaceSetAlarmChain[];
- static const CommandFunc sTetheringInterfaceSetAlarmChain[];
- static const CommandFunc sTetheringInterfaceRemoveAlarmChain[];
- static const CommandFunc sTetheringGetStatusChain[];
- static const CommandFunc sGetInterfacesChain[];
- static const CommandFunc sGetInterfaceConfigChain[];
- static const CommandFunc sSetInterfaceConfigChain[];
-
- /**
- * Individual netd command stored in command chain.
- */
-#define PARAMS CommandChain* aChain, CommandCallback aCallback, \
- mozilla::dom::NetworkResultOptions& aResult
- static void wifiFirmwareReload(PARAMS);
- static void startAccessPointDriver(PARAMS);
- static void stopAccessPointDriver(PARAMS);
- static void setAccessPoint(PARAMS);
- static void cleanUpStream(PARAMS);
- static void createUpStream(PARAMS);
- static void startSoftAP(PARAMS);
- static void stopSoftAP(PARAMS);
- static void clearWifiTetherParms(PARAMS);
- static void enableAlarm(PARAMS);
- static void disableAlarm(PARAMS);
- static void setQuota(PARAMS);
- static void removeQuota(PARAMS);
- static void setAlarm(PARAMS);
- static void removeAlarm(PARAMS);
- static void setGlobalAlarm(PARAMS);
- static void removeGlobalAlarm(PARAMS);
- static void tetherInterface(PARAMS);
- static void addInterfaceToLocalNetwork(PARAMS);
- static void addRouteToLocalNetwork(PARAMS);
- static void preTetherInterfaceList(PARAMS);
- static void postTetherInterfaceList(PARAMS);
- static void addUpstreamInterface(PARAMS);
- static void removeUpstreamInterface(PARAMS);
- static void setIpForwardingEnabled(PARAMS);
- static void tetheringStatus(PARAMS);
- static void stopTethering(PARAMS);
- static void startTethering(PARAMS);
- static void untetherInterface(PARAMS);
- static void removeInterfaceFromLocalNetwork(PARAMS);
- static void setDnsForwarders(PARAMS);
- static void enableNat(PARAMS);
- static void disableNat(PARAMS);
- static void setDefaultInterface(PARAMS);
- static void setInterfaceDns(PARAMS);
- static void getInterfaceList(PARAMS);
- static void getConfig(PARAMS);
- static void setConfig(PARAMS);
- static void wifiTetheringSuccess(PARAMS);
- static void usbTetheringSuccess(PARAMS);
- static void networkInterfaceAlarmSuccess(PARAMS);
- static void updateUpStreamSuccess(PARAMS);
- static void setDhcpServerSuccess(PARAMS);
- static void wifiOperationModeSuccess(PARAMS);
- static void clearAddrForInterface(PARAMS);
- static void createNetwork(PARAMS);
- static void destroyNetwork(PARAMS);
- static void addInterfaceToNetwork(PARAMS);
- static void addDefaultRouteToNetwork(PARAMS);
- static void setDefaultNetwork(PARAMS);
- static void removeDefaultRoute(PARAMS);
- static void removeNetworkRouteSuccess(PARAMS);
- static void removeNetworkRoute(PARAMS);
- static void addRouteToInterface(PARAMS);
- static void removeRouteFromInterface(PARAMS);
- static void modifyRouteOnInterface(PARAMS, bool aDoAdd);
- static void enableIpv6(PARAMS);
- static void disableIpv6(PARAMS);
- static void setMtu(PARAMS);
- static void setIpv6Enabled(PARAMS, bool aEnabled);
- static void addRouteToSecondaryTable(PARAMS);
- static void removeRouteFromSecondaryTable(PARAMS);
- static void defaultAsyncSuccessHandler(PARAMS);
- static void getInterfacesSuccess(PARAMS);
- static void getInterfaceConfigSuccess(PARAMS);
- static void setInterfaceConfigSuccess(PARAMS);
-
-#undef PARAMS
-
- /**
- * Error callback function executed when a command is fail.
- */
-#define PARAMS NetworkParams& aOptions, \
- mozilla::dom::NetworkResultOptions& aResult
- static void wifiTetheringFail(PARAMS);
- static void wifiOperationModeFail(PARAMS);
- static void usbTetheringFail(PARAMS);
- static void updateUpStreamFail(PARAMS);
- static void setDhcpServerFail(PARAMS);
- static void networkInterfaceAlarmFail(PARAMS);
- static void setDnsFail(PARAMS);
- static void defaultAsyncFailureHandler(PARAMS);
- static void getInterfacesFail(PARAMS);
- static void getInterfaceConfigFail(PARAMS);
- static void setInterfaceConfigFail(PARAMS);
-
-#undef PARAMS
-
- /**
- * Command chain processing functions.
- */
- static void next(CommandChain* aChain, bool aError,
- mozilla::dom::NetworkResultOptions& aResult);
- static void nextNetdCommand();
- static void doCommand(const char* aCommand, CommandChain* aChain, CommandCallback aCallback);
-
- /**
- * Notify broadcast message to main thread.
- */
- void sendBroadcastMessage(uint32_t code, char* reason);
-
- /**
- * Utility functions.
- */
- CommandResult checkUsbRndisState(NetworkParams& aOptions);
- void dumpParams(NetworkParams& aOptions, const char* aType);
-
- static void escapeQuote(nsCString& aString);
- inline uint32_t netdResponseType(uint32_t code);
- inline bool isBroadcastMessage(uint32_t code);
- inline bool isError(uint32_t code);
- inline bool isComplete(uint32_t code);
- inline bool isProceeding(uint32_t code);
- void Shutdown();
- static void runNextQueuedCommandChain();
- static void finalizeSuccess(CommandChain* aChain,
- mozilla::dom::NetworkResultOptions& aResult);
-
- template<size_t N>
- static void runChain(const NetworkParams& aParams,
- const CommandFunc (&aCmds)[N],
- ErrorCallback aError);
-
- static nsCString getSubnetIp(const nsCString& aIp, int aPrefixLength);
-
- /**
- * Callback function to send netd result to main thread.
- */
- MessageCallback mMessageCallback;
-
- /*
- * Utility class to access libnetutils.
- */
- nsAutoPtr<NetUtils> mNetUtils;
-
- NetIdManager mNetIdManager;
-};
-
-#endif
diff --git a/dom/system/gonk/NetworkWorker.cpp b/dom/system/gonk/NetworkWorker.cpp
deleted file mode 100644
index caf07f375..000000000
--- a/dom/system/gonk/NetworkWorker.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NetworkWorker.h"
-#include "NetworkUtils.h"
-#include <nsThreadUtils.h>
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/ToJSValue.h"
-#include "nsAutoPtr.h"
-#include "nsXULAppAPI.h"
-
-#define NS_NETWORKWORKER_CID \
- { 0x6df093e1, 0x8127, 0x4fa7, {0x90, 0x13, 0xa3, 0xaa, 0xa7, 0x79, 0xbb, 0xdd} }
-
-using namespace mozilla;
-using namespace mozilla::dom;
-using namespace mozilla::ipc;
-
-namespace mozilla {
-
-nsCOMPtr<nsIThread> gWorkerThread;
-
-// The singleton network worker, to be used on the main thread.
-StaticRefPtr<NetworkWorker> gNetworkWorker;
-
-// The singleton networkutils class, that can be used on any thread.
-static nsAutoPtr<NetworkUtils> gNetworkUtils;
-
-// Runnable used dispatch command result on the main thread.
-class NetworkResultDispatcher : public Runnable
-{
-public:
- NetworkResultDispatcher(const NetworkResultOptions& aResult)
- : mResult(aResult)
- {
- MOZ_ASSERT(!NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- if (gNetworkWorker) {
- gNetworkWorker->DispatchNetworkResult(mResult);
- }
- return NS_OK;
- }
-private:
- NetworkResultOptions mResult;
-};
-
-// Runnable used dispatch netd command on the worker thread.
-class NetworkCommandDispatcher : public Runnable
-{
-public:
- NetworkCommandDispatcher(const NetworkParams& aParams)
- : mParams(aParams)
- {
- MOZ_ASSERT(NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- if (gNetworkUtils) {
- gNetworkUtils->ExecuteCommand(mParams);
- }
- return NS_OK;
- }
-private:
- NetworkParams mParams;
-};
-
-// Runnable used dispatch netd result on the worker thread.
-class NetdEventRunnable : public Runnable
-{
-public:
- NetdEventRunnable(NetdCommand* aCommand)
- : mCommand(aCommand)
- {
- MOZ_ASSERT(!NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- if (gNetworkUtils) {
- gNetworkUtils->onNetdMessage(mCommand);
- }
- return NS_OK;
- }
-
-private:
- nsAutoPtr<NetdCommand> mCommand;
-};
-
-class NetdMessageConsumer : public NetdConsumer
-{
-public:
- NetdMessageConsumer()
- {
- MOZ_ASSERT(NS_IsMainThread());
- }
-
- void MessageReceived(NetdCommand* aCommand)
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCOMPtr<nsIRunnable> runnable = new NetdEventRunnable(aCommand);
- if (gWorkerThread) {
- gWorkerThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
- }
- }
-};
-
-NS_IMPL_ISUPPORTS(NetworkWorker, nsINetworkWorker)
-
-NetworkWorker::NetworkWorker()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!gNetworkWorker);
-}
-
-NetworkWorker::~NetworkWorker()
-{
- MOZ_ASSERT(!gNetworkWorker);
- MOZ_ASSERT(!mListener);
-}
-
-already_AddRefed<NetworkWorker>
-NetworkWorker::FactoryCreate()
-{
- if (!XRE_IsParentProcess()) {
- return nullptr;
- }
-
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!gNetworkWorker) {
- gNetworkWorker = new NetworkWorker();
- ClearOnShutdown(&gNetworkWorker);
-
- gNetworkUtils = new NetworkUtils(NetworkWorker::NotifyResult);
- ClearOnShutdown(&gNetworkUtils);
- }
-
- RefPtr<NetworkWorker> worker = gNetworkWorker.get();
- return worker.forget();
-}
-
-NS_IMETHODIMP
-NetworkWorker::Start(nsINetworkEventListener* aListener)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(aListener);
-
- if (mListener) {
- return NS_OK;
- }
-
- nsresult rv;
-
- rv = NS_NewNamedThread("NetworkWorker", getter_AddRefs(gWorkerThread));
- if (NS_FAILED(rv)) {
- NS_WARNING("Can't create network control thread");
- return NS_ERROR_FAILURE;
- }
-
- StartNetd(new NetdMessageConsumer());
- mListener = aListener;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-NetworkWorker::Shutdown()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!mListener) {
- return NS_OK;
- }
-
- StopNetd();
-
- gWorkerThread->Shutdown();
- gWorkerThread = nullptr;
-
- mListener = nullptr;
- return NS_OK;
-}
-
-// Receive command from main thread (NetworkService.js).
-NS_IMETHODIMP
-NetworkWorker::PostMessage(JS::Handle<JS::Value> aOptions, JSContext* aCx)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- NetworkCommandOptions options;
- if (!options.Init(aCx, aOptions)) {
- NS_WARNING("Bad dictionary passed to NetworkWorker::SendCommand");
- return NS_ERROR_FAILURE;
- }
-
- // Dispatch the command to the control thread.
- NetworkParams NetworkParams(options);
- nsCOMPtr<nsIRunnable> runnable = new NetworkCommandDispatcher(NetworkParams);
- if (gWorkerThread) {
- gWorkerThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
- }
- return NS_OK;
-}
-
-void
-NetworkWorker::DispatchNetworkResult(const NetworkResultOptions& aOptions)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mozilla::AutoSafeJSContext cx;
- JS::RootedValue val(cx);
-
- if (!ToJSValue(cx, aOptions, &val)) {
- return;
- }
-
- // Call the listener with a JS value.
- if (mListener) {
- mListener->OnEvent(val);
- }
-}
-
-// Callback function from network worker thread to update result on main thread.
-void
-NetworkWorker::NotifyResult(NetworkResultOptions& aResult)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCOMPtr<nsIRunnable> runnable = new NetworkResultDispatcher(aResult);
- NS_DispatchToMainThread(runnable);
-}
-
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(NetworkWorker,
- NetworkWorker::FactoryCreate)
-
-NS_DEFINE_NAMED_CID(NS_NETWORKWORKER_CID);
-
-static const mozilla::Module::CIDEntry kNetworkWorkerCIDs[] = {
- { &kNS_NETWORKWORKER_CID, false, nullptr, NetworkWorkerConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kNetworkWorkerContracts[] = {
- { "@mozilla.org/network/worker;1", &kNS_NETWORKWORKER_CID },
- { nullptr }
-};
-
-static const mozilla::Module kNetworkWorkerModule = {
- mozilla::Module::kVersion,
- kNetworkWorkerCIDs,
- kNetworkWorkerContracts,
- nullptr
-};
-
-} // namespace mozilla
-
-NSMODULE_DEFN(NetworkWorkerModule) = &kNetworkWorkerModule;
diff --git a/dom/system/gonk/NetworkWorker.h b/dom/system/gonk/NetworkWorker.h
deleted file mode 100644
index f5c0a8fdd..000000000
--- a/dom/system/gonk/NetworkWorker.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef NetworkWorker_h
-#define NetworkWorker_h
-
-#include "mozilla/dom/NetworkOptionsBinding.h"
-#include "mozilla/ipc/Netd.h"
-#include "nsINetworkWorker.h"
-#include "nsCOMPtr.h"
-#include "nsThread.h"
-
-namespace mozilla {
-
-class NetworkWorker final : public nsINetworkWorker
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSINETWORKWORKER
-
- static already_AddRefed<NetworkWorker> FactoryCreate();
-
- void DispatchNetworkResult(const mozilla::dom::NetworkResultOptions& aOptions);
-
-private:
- NetworkWorker();
- ~NetworkWorker();
-
- static void NotifyResult(mozilla::dom::NetworkResultOptions& aResult);
-
- nsCOMPtr<nsINetworkEventListener> mListener;
-};
-
-} // namespace mozilla
-
-#endif // NetworkWorker_h
diff --git a/dom/system/gonk/OpenFileFinder.cpp b/dom/system/gonk/OpenFileFinder.cpp
deleted file mode 100644
index 388e813e1..000000000
--- a/dom/system/gonk/OpenFileFinder.cpp
+++ /dev/null
@@ -1,251 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "OpenFileFinder.h"
-
-#include "mozilla/FileUtils.h"
-#include "nsPrintfCString.h"
-
-#include <sys/stat.h>
-#include <errno.h>
-
-#undef USE_DEBUG
-#define USE_DEBUG 0
-
-#undef LOG
-#undef LOGW
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "OpenFileFinder", ## args)
-#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "OpenFileFinder", ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "OpenFileFinder", ## args)
-
-#undef DBG
-#if USE_DEBUG
-#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "OpenFileFinder" , ## args)
-#else
-#define DBG(args...)
-#endif
-
-namespace mozilla {
-namespace system {
-
-OpenFileFinder::OpenFileFinder(const nsACString& aPath,
- bool aCheckIsB2gOrDescendant /* = true */)
- : mPath(aPath),
- mProcDir(nullptr),
- mFdDir(nullptr),
- mPid(0),
- mCheckIsB2gOrDescendant(aCheckIsB2gOrDescendant)
-{
- // We assume that we're running in the parent process
- mMyPid = getpid();
-}
-
-OpenFileFinder::~OpenFileFinder()
-{
- Close();
-}
-
-bool
-OpenFileFinder::First(OpenFileFinder::Info* aInfo)
-{
- Close();
-
- mProcDir = opendir("/proc");
- if (!mProcDir) {
- return false;
- }
- mState = NEXT_PID;
- return Next(aInfo);
-}
-
-bool
-OpenFileFinder::Next(OpenFileFinder::Info* aInfo)
-{
- // NOTE: This function calls readdir and readlink, neither of which should
- // block since we're using the proc filesystem, which is a purely
- // kernel in-memory filesystem and doesn't depend on external driver
- // behaviour.
- while (mState != DONE) {
- switch (mState) {
- case NEXT_PID: {
- struct dirent *pidEntry;
- pidEntry = readdir(mProcDir);
- if (!pidEntry) {
- mState = DONE;
- break;
- }
- char *endPtr;
- mPid = strtol(pidEntry->d_name, &endPtr, 10);
- if (mPid == 0 || *endPtr != '\0') {
- // Not a +ve number - ignore
- continue;
- }
- // We've found a /proc/PID directory. Scan open file descriptors.
- if (mFdDir) {
- closedir(mFdDir);
- }
- nsPrintfCString fdDirPath("/proc/%d/fd", mPid);
- mFdDir = opendir(fdDirPath.get());
- if (!mFdDir) {
- continue;
- }
- mState = CHECK_FDS;
- }
- // Fall through
- case CHECK_FDS: {
- struct dirent *fdEntry;
- while((fdEntry = readdir(mFdDir))) {
- if (!strcmp(fdEntry->d_name, ".") ||
- !strcmp(fdEntry->d_name, "..")) {
- continue;
- }
- nsPrintfCString fdSymLink("/proc/%d/fd/%s", mPid, fdEntry->d_name);
- nsCString resolvedPath;
- if (ReadSymLink(fdSymLink, resolvedPath) && PathMatches(resolvedPath)) {
- // We found an open file contained within the directory tree passed
- // into the constructor.
- FillInfo(aInfo, resolvedPath);
- // If sCheckIsB2gOrDescendant is set false, the caller cares about
- // all processes which have open files. If sCheckIsB2gOrDescendant
- // is set false, we only care about the b2g proccess or its descendants.
- if (!mCheckIsB2gOrDescendant || aInfo->mIsB2gOrDescendant) {
- return true;
- }
- LOG("Ignore process(%d), not a b2g process or its descendant.",
- aInfo->mPid);
- }
- }
- // We've checked all of the files for this pid, move onto the next one.
- mState = NEXT_PID;
- continue;
- }
- case DONE:
- default:
- mState = DONE; // covers the default case
- break;
- }
- }
- return false;
-}
-
-void
-OpenFileFinder::Close()
-{
- if (mFdDir) {
- closedir(mFdDir);
- }
- if (mProcDir) {
- closedir(mProcDir);
- }
-}
-
-void
-OpenFileFinder::FillInfo(OpenFileFinder::Info* aInfo, const nsACString& aPath)
-{
- aInfo->mFileName = aPath;
- aInfo->mPid = mPid;
- nsPrintfCString exePath("/proc/%d/exe", mPid);
- ReadSymLink(exePath, aInfo->mExe);
- aInfo->mComm.Truncate();
- aInfo->mAppName.Truncate();
- nsPrintfCString statPath("/proc/%d/stat", mPid);
- nsCString statString;
- statString.SetLength(200);
- char *stat = statString.BeginWriting();
- if (!stat) {
- return;
- }
- ReadSysFile(statPath.get(), stat, statString.Length());
- // The stat line includes the comm field, surrounded by parenthesis.
- // However, the contents of the comm field itself is arbitrary and
- // and can include ')', so we search for the rightmost ) as being
- // the end of the comm field.
- char *closeParen = strrchr(stat, ')');
- if (!closeParen) {
- return;
- }
- char *openParen = strchr(stat, '(');
- if (!openParen) {
- return;
- }
- if (openParen >= closeParen) {
- return;
- }
- nsDependentCSubstring comm(&openParen[1], closeParen - openParen - 1);
- aInfo->mComm = comm;
- // There is a single character field after the comm and then
- // the parent pid (the field we're interested in).
- // ) X ppid
- // 01234
- int ppid = atoi(&closeParen[4]);
-
- if (mPid == mMyPid) {
- // This is chrome process
- aInfo->mIsB2gOrDescendant = true;
- DBG("Chrome process has open file(s)");
- return;
- }
- // For the rest (non-chrome process), we recursively check the ppid to know
- // it is a descendant of b2g or not. See bug 931456.
- while (ppid != mMyPid && ppid != 1) {
- DBG("Process(%d) is not forked from b2g(%d) or Init(1), keep looking",
- ppid, mMyPid);
- nsPrintfCString ppStatPath("/proc/%d/stat", ppid);
- ReadSysFile(ppStatPath.get(), stat, statString.Length());
- closeParen = strrchr(stat, ')');
- if (!closeParen) {
- return;
- }
- ppid = atoi(&closeParen[4]);
- }
- if (ppid == 1) {
- // This is a not a b2g process.
- DBG("Non-b2g process has open file(s)");
- aInfo->mIsB2gOrDescendant = false;
- return;
- }
- if (ppid == mMyPid) {
- // This is a descendant of b2g.
- DBG("Child process of chrome process has open file(s)");
- aInfo->mIsB2gOrDescendant = true;
- }
-
- // This looks like a content process. The comm field will be the
- // app name.
- aInfo->mAppName = aInfo->mComm;
-}
-
-bool
-OpenFileFinder::ReadSymLink(const nsACString& aSymLink, nsACString& aOutPath)
-{
- aOutPath.Truncate();
- const char *symLink = aSymLink.BeginReading();
-
- // Verify that we actually have a symlink.
- struct stat st;
- if (lstat(symLink, &st)) {
- return false;
- }
- if ((st.st_mode & S_IFMT) != S_IFLNK) {
- return false;
- }
-
- // Contrary to the documentation st.st_size doesn't seem to be a reliable
- // indication of the length when reading from /proc, so we use a fixed
- // size buffer instead.
-
- char resolvedSymLink[PATH_MAX];
- ssize_t pathLength = readlink(symLink, resolvedSymLink,
- sizeof(resolvedSymLink) - 1);
- if (pathLength <= 0) {
- return false;
- }
- resolvedSymLink[pathLength] = '\0';
- aOutPath.Assign(resolvedSymLink);
- return true;
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/OpenFileFinder.h b/dom/system/gonk/OpenFileFinder.h
deleted file mode 100644
index 24517965a..000000000
--- a/dom/system/gonk/OpenFileFinder.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_openfilefinder_h__
-#define mozilla_system_openfilefinder_h__
-
-#include "nsString.h"
-
-#include <dirent.h>
-
-namespace mozilla {
-namespace system {
-
-class OpenFileFinder
-{
-public:
- enum State
- {
- NEXT_PID,
- CHECK_FDS,
- DONE
- };
- class Info
- {
- public:
- nsCString mFileName; // name of the the open file
- nsCString mAppName; // App which has the file open (if it's a b2g app)
- pid_t mPid; // pid of the process which has the file open
- nsCString mComm; // comm associated with pid
- nsCString mExe; // executable name associated with pid
- bool mIsB2gOrDescendant; // this is b2g/its descendant or not
- };
-
- OpenFileFinder(const nsACString& aPath, bool aCheckIsB2gOrDescendant = true);
- ~OpenFileFinder();
-
- bool First(Info* aInfo); // Return the first open file
- bool Next(Info* aInfo); // Return the next open file
- void Close();
-
-private:
-
- void FillInfo(Info *aInfo, const nsACString& aPath);
- bool ReadSymLink(const nsACString& aSymLink, nsACString& aOutPath);
- bool PathMatches(const nsACString& aPath)
- {
- return Substring(aPath, 0, mPath.Length()).Equals(mPath);
- }
-
- State mState; // Keeps track of what we're doing.
- nsCString mPath; // Only report files contained within this directory tree
- DIR* mProcDir; // Used for scanning /proc
- DIR* mFdDir; // Used for scanning /proc/PID/fd
- int mPid; // PID currently being processed
- pid_t mMyPid; // PID of parent process, we assume we're running on it.
- bool mCheckIsB2gOrDescendant; // Do we care about non-b2g process?
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_nsvolume_h__
diff --git a/dom/system/gonk/RILSystemMessenger.jsm b/dom/system/gonk/RILSystemMessenger.jsm
deleted file mode 100644
index 81373458c..000000000
--- a/dom/system/gonk/RILSystemMessenger.jsm
+++ /dev/null
@@ -1,338 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "RIL", function () {
- let obj = {};
- Cu.import("resource://gre/modules/ril_consts.js", obj);
- return obj;
-});
-
-/**
- * RILSystemMessenger
- */
-this.RILSystemMessenger = function() {};
-RILSystemMessenger.prototype = {
-
- /**
- * Hook of Broadcast function
- *
- * @param aType
- * The type of the message to be sent.
- * @param aMessage
- * The message object to be broadcasted.
- */
- broadcastMessage: function(aType, aMessage) {
- // Function stub to be replaced by the owner of this messenger.
- },
-
- /**
- * Hook of the function to create MozStkCommand message.
- * @param aStkProactiveCmd
- * nsIStkProactiveCmd instance.
- *
- * @return a JS object which complies the dictionary of MozStkCommand defined
- * in MozStkCommandEvent.webidl
- */
- createCommandMessage: function(aStkProactiveCmd) {
- // Function stub to be replaced by the owner of this messenger.
- },
-
- /**
- * Wrapper to send "telephony-new-call" system message.
- */
- notifyNewCall: function() {
- this.broadcastMessage("telephony-new-call", {});
- },
-
- /**
- * Wrapper to send "telephony-call-ended" system message.
- */
- notifyCallEnded: function(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
- aDuration, aOutgoing, aHangUpLocal) {
- let data = {
- serviceId: aServiceId,
- number: aNumber,
- emergency: aEmergency,
- duration: aDuration,
- direction: aOutgoing ? "outgoing" : "incoming",
- hangUpLocal: aHangUpLocal
- };
-
- if (aCdmaWaitingNumber != null) {
- data.secondNumber = aCdmaWaitingNumber;
- }
-
- this.broadcastMessage("telephony-call-ended", data);
- },
-
- _convertSmsMessageClass: function(aMessageClass) {
- return RIL.GECKO_SMS_MESSAGE_CLASSES[aMessageClass] || null;
- },
-
- _convertSmsDelivery: function(aDelivery) {
- return ["received", "sending", "sent", "error"][aDelivery] || null;
- },
-
- _convertSmsDeliveryStatus: function(aDeliveryStatus) {
- return [
- RIL.GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE,
- RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
- RIL.GECKO_SMS_DELIVERY_STATUS_PENDING,
- RIL.GECKO_SMS_DELIVERY_STATUS_ERROR
- ][aDeliveryStatus] || null;
- },
-
- /**
- * Wrapper to send 'sms-received', 'sms-delivery-success', 'sms-sent',
- * 'sms-failed', 'sms-delivery-error' system message.
- */
- notifySms: function(aNotificationType, aId, aThreadId, aIccId, aDelivery,
- aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
- aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead) {
- let msgType = [
- "sms-received",
- "sms-sent",
- "sms-delivery-success",
- "sms-failed",
- "sms-delivery-error"
- ][aNotificationType];
-
- if (!msgType) {
- throw new Error("Invalid Notification Type: " + aNotificationType);
- }
-
- this.broadcastMessage(msgType, {
- iccId: aIccId,
- type: "sms",
- id: aId,
- threadId: aThreadId,
- delivery: this._convertSmsDelivery(aDelivery),
- deliveryStatus: this._convertSmsDeliveryStatus(aDeliveryStatus),
- sender: aSender,
- receiver: aReceiver,
- body: aBody,
- messageClass: this._convertSmsMessageClass(aMessageClass),
- timestamp: aTimestamp,
- sentTimestamp: aSentTimestamp,
- deliveryTimestamp: aDeliveryTimestamp,
- read: aRead
- });
- },
-
- _convertCbGsmGeographicalScope: function(aGeographicalScope) {
- return RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[aGeographicalScope] || null;
- },
-
- _convertCbMessageClass: function(aMessageClass) {
- return RIL.GECKO_SMS_MESSAGE_CLASSES[aMessageClass] || null;
- },
-
- _convertCbEtwsWarningType: function(aWarningType) {
- return RIL.CB_ETWS_WARNING_TYPE_NAMES[aWarningType] || null;
- },
-
- /**
- * Wrapper to send 'cellbroadcast-received' system message.
- */
- notifyCbMessageReceived: function(aServiceId, aGsmGeographicalScope, aMessageCode,
- aMessageId, aLanguage, aBody, aMessageClass,
- aTimestamp, aCdmaServiceCategory, aHasEtwsInfo,
- aEtwsWarningType, aEtwsEmergencyUserAlert, aEtwsPopup) {
- // Align the same layout to MozCellBroadcastMessage
- let data = {
- serviceId: aServiceId,
- gsmGeographicalScope: this._convertCbGsmGeographicalScope(aGsmGeographicalScope),
- messageCode: aMessageCode,
- messageId: aMessageId,
- language: aLanguage,
- body: aBody,
- messageClass: this._convertCbMessageClass(aMessageClass),
- timestamp: aTimestamp,
- cdmaServiceCategory: null,
- etws: null
- };
-
- if (aHasEtwsInfo) {
- data.etws = {
- warningType: this._convertCbEtwsWarningType(aEtwsWarningType),
- emergencyUserAlert: aEtwsEmergencyUserAlert,
- popup: aEtwsPopup
- };
- }
-
- if (aCdmaServiceCategory !=
- Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID) {
- data.cdmaServiceCategory = aCdmaServiceCategory;
- }
-
- this.broadcastMessage("cellbroadcast-received", data);
- },
-
- /**
- * Wrapper to send 'ussd-received' system message.
- */
- notifyUssdReceived: function(aServiceId, aMessage, aSessionEnded) {
- this.broadcastMessage("ussd-received", {
- serviceId: aServiceId,
- message: aMessage,
- sessionEnded: aSessionEnded
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Display Info.
- */
- notifyCdmaInfoRecDisplay: function(aServiceId, aDisplay) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- display: aDisplay
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Called Party
- * Number Info.
- */
- notifyCdmaInfoRecCalledPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- calledNumber: {
- type: aType,
- plan: aPlan,
- number: aNumber,
- pi: aPi,
- si: aSi
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Calling Party
- * Number Info.
- */
- notifyCdmaInfoRecCallingPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- callingNumber: {
- type: aType,
- plan: aPlan,
- number: aNumber,
- pi: aPi,
- si: aSi
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Connected Party
- * Number Info.
- */
- notifyCdmaInfoRecConnectedPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- connectedNumber: {
- type: aType,
- plan: aPlan,
- number: aNumber,
- pi: aPi,
- si: aSi
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Signal Info.
- */
- notifyCdmaInfoRecSignal: function(aServiceId, aType, aAlertPitch, aSignal) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- signal: {
- type: aType,
- alertPitch: aAlertPitch,
- signal: aSignal
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Redirecting
- * Number Info.
- */
- notifyCdmaInfoRecRedirectingNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi, aReason) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- redirect: {
- type: aType,
- plan: aPlan,
- number: aNumber,
- pi: aPi,
- si: aSi,
- reason: aReason
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Line Control Info.
- */
- notifyCdmaInfoRecLineControl: function(aServiceId, aPolarityIncluded,
- aToggle, aReverse, aPowerDenial) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- lineControl: {
- polarityIncluded: aPolarityIncluded,
- toggle: aToggle,
- reverse: aReverse,
- powerDenial: aPowerDenial
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with CLIR Info.
- */
- notifyCdmaInfoRecClir: function(aServiceId, aCause) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- clirCause: aCause
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Audio Control Info.
- */
- notifyCdmaInfoRecAudioControl: function(aServiceId, aUpLink, aDownLink) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- audioControl: {
- upLink: aUpLink,
- downLink: aDownLink
- }
- });
- },
-
- /**
- * Wrapper to send 'icc-stkcommand' system message with Audio Control Info.
- */
- notifyStkProactiveCommand: function(aIccId, aCommand) {
- this.broadcastMessage("icc-stkcommand", {
- iccId: aIccId,
- command: this.createCommandMessage(aCommand)
- });
- }
-};
-
-this.EXPORTED_SYMBOLS = [
- 'RILSystemMessenger'
-];
diff --git a/dom/system/gonk/RILSystemMessengerHelper.js b/dom/system/gonk/RILSystemMessengerHelper.js
deleted file mode 100644
index 6ef263b66..000000000
--- a/dom/system/gonk/RILSystemMessengerHelper.js
+++ /dev/null
@@ -1,169 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-var RSM = {};
-Cu.import("resource://gre/modules/RILSystemMessenger.jsm", RSM);
-
-const RILSYSTEMMESSENGERHELPER_CONTRACTID =
- "@mozilla.org/ril/system-messenger-helper;1";
-const RILSYSTEMMESSENGERHELPER_CID =
- Components.ID("{19d9a4ea-580d-11e4-8f6c-37ababfaaea9}");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
- "@mozilla.org/system-message-internal;1",
- "nsISystemMessagesInternal");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory",
- "@mozilla.org/icc/stkcmdfactory;1",
- "nsIStkCmdFactory");
-
-var DEBUG = false;
-function debug(s) {
- dump("-@- RILSystemMessenger: " + s + "\n");
-};
-
-// Read debug setting from pref.
-try {
- let debugPref = Services.prefs.getBoolPref("ril.debugging.enabled");
- DEBUG = DEBUG || debugPref;
-} catch (e) {}
-
-/**
- * RILSystemMessengerHelper
- */
-function RILSystemMessengerHelper() {
- this.messenger = new RSM.RILSystemMessenger();
- this.messenger.broadcastMessage = (aType, aMessage) => {
- if (DEBUG) {
- debug("broadcastMessage: aType: " + aType +
- ", aMessage: "+ JSON.stringify(aMessage));
- }
-
- gSystemMessenger.broadcastMessage(aType, aMessage);
- };
-
- this.messenger.createCommandMessage = (aStkProactiveCmd) => {
- return gStkCmdFactory.createCommandMessage(aStkProactiveCmd);
- };
-}
-RILSystemMessengerHelper.prototype = {
-
- classID: RILSYSTEMMESSENGERHELPER_CID,
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyMessenger,
- Ci.nsISmsMessenger,
- Ci.nsICellbroadcastMessenger,
- Ci.nsIMobileConnectionMessenger,
- Ci.nsIIccMessenger]),
-
- /**
- * RILSystemMessenger instance.
- */
- messenger: null,
-
- /**
- * nsITelephonyMessenger API
- */
- notifyNewCall: function() {
- this.messenger.notifyNewCall();
- },
-
- notifyCallEnded: function(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
- aDuration, aOutgoing, aHangUpLocal) {
- this.messenger.notifyCallEnded(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
- aDuration, aOutgoing, aHangUpLocal);
- },
-
- notifyUssdReceived: function(aServiceId, aMessage, aSessionEnded) {
- this.messenger.notifyUssdReceived(aServiceId, aMessage, aSessionEnded);
- },
-
- /**
- * nsISmsMessenger API
- */
- notifySms: function(aNotificationType, aId, aThreadId, aIccId, aDelivery,
- aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
- aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead) {
- this.messenger.notifySms(aNotificationType, aId, aThreadId, aIccId, aDelivery,
- aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
- aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead);
- },
-
- /**
- * nsICellbroadcastMessenger API
- */
- notifyCbMessageReceived: function(aServiceId, aGsmGeographicalScope, aMessageCode,
- aMessageId, aLanguage, aBody, aMessageClass,
- aTimestamp, aCdmaServiceCategory, aHasEtwsInfo,
- aEtwsWarningType, aEtwsEmergencyUserAlert, aEtwsPopup) {
- this.messenger.notifyCbMessageReceived(aServiceId, aGsmGeographicalScope, aMessageCode,
- aMessageId, aLanguage, aBody, aMessageClass,
- aTimestamp, aCdmaServiceCategory, aHasEtwsInfo,
- aEtwsWarningType, aEtwsEmergencyUserAlert, aEtwsPopup);
- },
-
- /**
- * nsIMobileConnectionMessenger API
- */
- notifyCdmaInfoRecDisplay: function(aServiceId, aDisplay) {
- this.messenger.notifyCdmaInfoRecDisplay(aServiceId, aDisplay);
- },
-
- notifyCdmaInfoRecCalledPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.messenger.notifyCdmaInfoRecCalledPartyNumber(aServiceId, aType, aPlan,
- aNumber, aPi, aSi);
- },
-
- notifyCdmaInfoRecCallingPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.messenger.notifyCdmaInfoRecCallingPartyNumber(aServiceId, aType, aPlan,
- aNumber, aPi, aSi);
- },
-
- notifyCdmaInfoRecConnectedPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.messenger.notifyCdmaInfoRecConnectedPartyNumber(aServiceId, aType, aPlan,
- aNumber, aPi, aSi);
- },
-
- notifyCdmaInfoRecSignal: function(aServiceId, aType, aAlertPitch, aSignal) {
- this.messenger.notifyCdmaInfoRecSignal(aServiceId, aType, aAlertPitch, aSignal);
- },
-
- notifyCdmaInfoRecRedirectingNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi, aReason) {
- this.messenger.notifyCdmaInfoRecRedirectingNumber(aServiceId, aType, aPlan,
- aNumber, aPi, aSi, aReason);
- },
-
- notifyCdmaInfoRecLineControl: function(aServiceId, aPolarityIncluded,
- aToggle, aReverse, aPowerDenial) {
- this.messenger.notifyCdmaInfoRecLineControl(aServiceId, aPolarityIncluded,
- aToggle, aReverse, aPowerDenial);
- },
-
- notifyCdmaInfoRecClir: function(aServiceId, aCause) {
- this.messenger.notifyCdmaInfoRecClir(aServiceId, aCause);
- },
-
- notifyCdmaInfoRecAudioControl: function(aServiceId, aUpLink, aDownLink) {
- this.messenger.notifyCdmaInfoRecAudioControl(aServiceId, aUpLink, aDownLink);
- },
-
- /**
- * nsIIccMessenger API
- */
- notifyStkProactiveCommand: function(aIccId, aCommand) {
- this.messenger.notifyStkProactiveCommand(aIccId, aCommand);
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILSystemMessengerHelper]);
diff --git a/dom/system/gonk/RILSystemMessengerHelper.manifest b/dom/system/gonk/RILSystemMessengerHelper.manifest
deleted file mode 100644
index 7d1943702..000000000
--- a/dom/system/gonk/RILSystemMessengerHelper.manifest
+++ /dev/null
@@ -1,6 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-component {19d9a4ea-580d-11e4-8f6c-37ababfaaea9} RILSystemMessengerHelper.js
-contract @mozilla.org/ril/system-messenger-helper;1 {19d9a4ea-580d-11e4-8f6c-37ababfaaea9} \ No newline at end of file
diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js
deleted file mode 100644
index f5885db5d..000000000
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ /dev/null
@@ -1,1324 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Sntp.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "RIL", function () {
- let obj = {};
- Cu.import("resource://gre/modules/ril_consts.js", obj);
- return obj;
-});
-
-// Ril quirk to always turn the radio off for the client without SIM card
-// except hw default client.
-var RILQUIRKS_RADIO_OFF_WO_CARD =
- libcutils.property_get("ro.moz.ril.radio_off_wo_card", "false") == "true";
-
-const RADIOINTERFACELAYER_CID =
- Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
-const RADIOINTERFACE_CID =
- Components.ID("{6a7c91f0-a2b3-4193-8562-8969296c0b54}");
-
-const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
-const kNetworkConnStateChangedTopic = "network-connection-state-changed";
-const kMozSettingsChangedObserverTopic = "mozsettings-changed";
-const kSysMsgListenerReadyObserverTopic = "system-message-listener-ready";
-const kSysClockChangeObserverTopic = "system-clock-change";
-const kScreenStateChangedTopic = "screen-state-changed";
-
-const kSettingsClockAutoUpdateEnabled = "time.clock.automatic-update.enabled";
-const kSettingsClockAutoUpdateAvailable = "time.clock.automatic-update.available";
-const kSettingsTimezoneAutoUpdateEnabled = "time.timezone.automatic-update.enabled";
-const kSettingsTimezoneAutoUpdateAvailable = "time.timezone.automatic-update.available";
-
-const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
-
-const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
-const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
-
-const RADIO_POWER_OFF_TIMEOUT = 30000;
-const HW_DEFAULT_CLIENT_ID = 0;
-
-const NETWORK_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
-const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
-
-// set to true in ril_consts.js to see debug messages
-var DEBUG = RIL.DEBUG_RIL;
-
-function updateDebugFlag() {
- // Read debug setting from pref
- let debugPref;
- try {
- debugPref = Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
- } catch (e) {
- debugPref = false;
- }
- DEBUG = RIL.DEBUG_RIL || debugPref;
-}
-updateDebugFlag();
-
-function debug(s) {
- dump("-*- RadioInterfaceLayer: " + s + "\n");
-}
-
-XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
- "@mozilla.org/icc/gonkiccservice;1",
- "nsIGonkIccService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageService",
- "@mozilla.org/mobilemessage/mobilemessageservice;1",
- "nsIMobileMessageService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
- "@mozilla.org/sms/gonksmsservice;1",
- "nsIGonkSmsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageBroadcaster");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gTimeService",
- "@mozilla.org/time/timeservice;1",
- "nsITimeService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSystemWorkerManager",
- "@mozilla.org/telephony/system-worker-manager;1",
- "nsISystemWorkerManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gTelephonyService",
- "@mozilla.org/telephony/telephonyservice;1",
- "nsIGonkTelephonyService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIGonkMobileConnectionService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gCellBroadcastService",
- "@mozilla.org/cellbroadcast/cellbroadcastservice;1",
- "nsIGonkCellBroadcastService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gDataCallManager",
- "@mozilla.org/datacall/manager;1",
- "nsIDataCallManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gDataCallInterfaceService",
- "@mozilla.org/datacall/interfaceservice;1",
- "nsIGonkDataCallInterfaceService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory",
- "@mozilla.org/icc/stkcmdfactory;1",
- "nsIStkCmdFactory");
-
-XPCOMUtils.defineLazyGetter(this, "gRadioEnabledController", function() {
- let _ril = null;
- let _pendingMessages = []; // For queueing "setRadioEnabled" message.
- let _isProcessingPending = false;
- let _timer = null;
- let _request = null;
- let _deactivatingDeferred = {};
- let _initializedCardState = {};
- let _allCardStateInitialized = !RILQUIRKS_RADIO_OFF_WO_CARD;
-
- return {
- init: function(ril) {
- _ril = ril;
- },
-
- receiveCardState: function(clientId) {
- if (_allCardStateInitialized) {
- return;
- }
-
- if (DEBUG) debug("RadioControl: receive cardState from " + clientId);
- _initializedCardState[clientId] = true;
- if (Object.keys(_initializedCardState).length == _ril.numRadioInterfaces) {
- _allCardStateInitialized = true;
- this._startProcessingPending();
- }
- },
-
- setRadioEnabled: function(clientId, data, callback) {
- if (DEBUG) debug("setRadioEnabled: " + clientId + ": " + JSON.stringify(data));
- let message = {
- clientId: clientId,
- data: data,
- callback: callback
- };
- _pendingMessages.push(message);
- this._startProcessingPending();
- },
-
- notifyRadioStateChanged: function(clientId, radioState) {
- gMobileConnectionService.notifyRadioStateChanged(clientId, radioState);
- },
-
- _startProcessingPending: function() {
- if (!_isProcessingPending) {
- if (DEBUG) debug("RadioControl: start dequeue");
- _isProcessingPending = true;
- this._processNextMessage();
- }
- },
-
- _processNextMessage: function() {
- if (_pendingMessages.length === 0 || !_allCardStateInitialized) {
- if (DEBUG) debug("RadioControl: stop dequeue");
- _isProcessingPending = false;
- return;
- }
-
- let msg = _pendingMessages.shift();
- this._handleMessage(msg);
- },
-
- _getNumCards: function() {
- let numCards = 0;
- for (let i = 0, N = _ril.numRadioInterfaces; i < N; ++i) {
- if (_ril.getRadioInterface(i).isCardPresent()) {
- numCards++;
- }
- }
- return numCards;
- },
-
- _isRadioAbleToEnableAtClient: function(clientId, numCards) {
- if (!RILQUIRKS_RADIO_OFF_WO_CARD) {
- return true;
- }
-
- // We could only turn on the radio for clientId if
- // 1. a SIM card is presented or
- // 2. it is the default clientId and there is no any SIM card at any client.
-
- if (_ril.getRadioInterface(clientId).isCardPresent()) {
- return true;
- }
-
- numCards = numCards == null ? this._getNumCards() : numCards;
- if (clientId === HW_DEFAULT_CLIENT_ID && numCards === 0) {
- return true;
- }
-
- return false;
- },
-
- _handleMessage: function(message) {
- if (DEBUG) debug("RadioControl: handleMessage: " + JSON.stringify(message));
- let clientId = message.clientId || 0;
- let connection =
- gMobileConnectionService.getItemByServiceId(clientId);
- let radioState = connection && connection.radioState;
-
- if (message.data.enabled) {
- if (this._isRadioAbleToEnableAtClient(clientId)) {
- this._setRadioEnabledInternal(message);
- } else {
- // Not really do it but respond success.
- message.callback(message.data);
- }
-
- this._processNextMessage();
- } else {
- _request = this._setRadioEnabledInternal.bind(this, message);
-
- // In 2G network, modem takes 35+ seconds to process deactivate data
- // call request if device has active voice call (please see bug 964974
- // for more details). Therefore we should hangup all active voice calls
- // first. And considering some DSDS architecture, toggling one radio may
- // toggle both, so we send hangUpAll to all clients.
- let hangUpCallback = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyCallback]),
- notifySuccess: function() {},
- notifyError: function() {}
- };
-
- gTelephonyService.enumerateCalls({
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
- enumerateCallState: function(aInfo) {
- gTelephonyService.hangUpCall(aInfo.clientId, aInfo.callIndex,
- hangUpCallback);
- },
- enumerateCallStateComplete: function() {}
- });
-
- // In some DSDS architecture with only one modem, toggling one radio may
- // toggle both. Therefore, for safely turning off, we should first
- // explicitly deactivate all data calls from all clients.
- this._deactivateDataCalls().then(() => {
- if (DEBUG) debug("RadioControl: deactivation done");
- this._executeRequest();
- });
-
- this._createTimer();
- }
- },
-
- _setRadioEnabledInternal: function(message) {
- let clientId = message.clientId || 0;
- let enabled = message.data.enabled || false;
- let radioInterface = _ril.getRadioInterface(clientId);
-
- radioInterface.workerMessenger.send("setRadioEnabled", message.data,
- (function(response) {
- if (response.errorMsg) {
- // If request fails, set current radio state to unknown, since we will
- // handle it in |mobileConnectionService|.
- this.notifyRadioStateChanged(clientId,
- Ci.nsIMobileConnection.MOBILE_RADIO_STATE_UNKNOWN);
- }
- return message.callback(response);
- }).bind(this));
- },
-
- _deactivateDataCalls: function() {
- if (DEBUG) debug("RadioControl: deactivating data calls...");
- _deactivatingDeferred = {};
-
- let promise = Promise.resolve();
- for (let i = 0, N = _ril.numRadioInterfaces; i < N; ++i) {
- promise = promise.then(this._deactivateDataCallsForClient(i));
- }
-
- return promise;
- },
-
- _deactivateDataCallsForClient: function(clientId) {
- return function() {
- let deferred = _deactivatingDeferred[clientId] = Promise.defer();
- let dataCallHandler = gDataCallManager.getDataCallHandler(clientId);
-
- dataCallHandler.deactivateDataCalls(function() {
- deferred.resolve();
- });
-
- return deferred.promise;
- };
- },
-
- _createTimer: function() {
- if (!_timer) {
- _timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- }
- _timer.initWithCallback(this._executeRequest.bind(this),
- RADIO_POWER_OFF_TIMEOUT,
- Ci.nsITimer.TYPE_ONE_SHOT);
- },
-
- _cancelTimer: function() {
- if (_timer) {
- _timer.cancel();
- }
- },
-
- _executeRequest: function() {
- if (typeof _request === "function") {
- if (DEBUG) debug("RadioControl: executeRequest");
- this._cancelTimer();
- _request();
- _request = null;
- }
- this._processNextMessage();
- },
- };
-});
-
-// Initialize shared preference "ril.numRadioInterfaces" according to system
-// property.
-try {
- Services.prefs.setIntPref(kPrefRilNumRadioInterfaces, (function() {
- // When Gonk property "ro.moz.ril.numclients" is not set, return 1; if
- // explicitly set to any number larger-equal than 0, return num; else, return
- // 1 for compatibility.
- try {
- let numString = libcutils.property_get("ro.moz.ril.numclients", "1");
- let num = parseInt(numString, 10);
- if (num >= 0) {
- return num;
- }
- } catch (e) {}
-
- return 1;
- })());
-} catch (e) {}
-
-function DataCall(aAttributes) {
- for (let key in aAttributes) {
- if (key === "pdpType") {
- // Convert pdp type into constant int value.
- this[key] = RIL.RIL_DATACALL_PDP_TYPES.indexOf(aAttributes[key]);
- continue;
- }
-
- this[key] = aAttributes[key];
- }
-}
-DataCall.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCall]),
-
- failCause: Ci.nsIDataCallInterface.DATACALL_FAIL_NONE,
- suggestedRetryTime: -1,
- cid: -1,
- active: -1,
- pdpType: -1,
- ifname: null,
- addreses: null,
- dnses: null,
- gateways: null,
- pcscf: null,
- mtu: -1
-};
-
-function RadioInterfaceLayer() {
- let workerMessenger = new WorkerMessenger();
- workerMessenger.init();
- this.setWorkerDebugFlag = workerMessenger.setDebugFlag.bind(workerMessenger);
-
- let numIfaces = this.numRadioInterfaces;
- if (DEBUG) debug(numIfaces + " interfaces");
- this.radioInterfaces = [];
- for (let clientId = 0; clientId < numIfaces; clientId++) {
- this.radioInterfaces.push(new RadioInterface(clientId, workerMessenger));
- }
-
- Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
- Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
-
- gRadioEnabledController.init(this);
-}
-RadioInterfaceLayer.prototype = {
-
- classID: RADIOINTERFACELAYER_CID,
- classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
- classDescription: "RadioInterfaceLayer",
- interfaces: [Ci.nsIRadioInterfaceLayer]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterfaceLayer,
- Ci.nsIObserver]),
-
- /**
- * nsIObserver interface methods.
- */
-
- observe: function(subject, topic, data) {
- switch (topic) {
- case NS_XPCOM_SHUTDOWN_OBSERVER_ID:
- for (let radioInterface of this.radioInterfaces) {
- radioInterface.shutdown();
- }
- this.radioInterfaces = null;
- Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
- break;
-
- case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
- if (data === kPrefRilDebuggingEnabled) {
- updateDebugFlag();
- this.setWorkerDebugFlag(DEBUG);
- }
- break;
- }
- },
-
- /**
- * nsIRadioInterfaceLayer interface methods.
- */
-
- getRadioInterface: function(clientId) {
- return this.radioInterfaces[clientId];
- },
-
- setMicrophoneMuted: function(muted) {
- for (let clientId = 0; clientId < this.numRadioInterfaces; clientId++) {
- let radioInterface = this.radioInterfaces[clientId];
- radioInterface.workerMessenger.send("setMute", { muted: muted });
- }
- }
-};
-
-XPCOMUtils.defineLazyGetter(RadioInterfaceLayer.prototype,
- "numRadioInterfaces", function() {
- try {
- return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces);
- } catch(e) {}
-
- return 1;
-});
-
-function WorkerMessenger() {
- // Initial owning attributes.
- this.radioInterfaces = [];
- this.tokenCallbackMap = {};
-
- this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
- this.worker.onerror = this.onerror.bind(this);
- this.worker.onmessage = this.onmessage.bind(this);
-}
-WorkerMessenger.prototype = {
- radioInterfaces: null,
- worker: null,
-
- // This gets incremented each time we send out a message.
- token: 1,
-
- // Maps tokens we send out with messages to the message callback.
- tokenCallbackMap: null,
-
- init: function() {
- let options = {
- debug: DEBUG,
- quirks: {
- callstateExtraUint32:
- libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true",
- requestUseDialEmergencyCall:
- libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true",
- simAppStateExtraFields:
- libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true",
- extraUint2ndCall:
- libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") === "true",
- haveQueryIccLockRetryCount:
- libcutils.property_get("ro.moz.ril.query_icc_count", "false") === "true",
- sendStkProfileDownload:
- libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") === "true",
- smscAddressFormat:
- libcutils.property_get("ro.moz.ril.smsc_address_format", "text"),
- dataRegistrationOnDemand:
- libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") === "true",
- subscriptionControl:
- libcutils.property_get("ro.moz.ril.subscription_control", "false") === "true",
- signalExtraInt:
- libcutils.property_get("ro.moz.ril.signal_extra_int", "false") === "true",
- availableNetworkExtraStr:
- libcutils.property_get("ro.moz.ril.avlbl_nw_extra_str", "false") === "true",
- }
- };
-
- this.send(null, "setInitialOptions", options);
- },
-
- setDebugFlag: function(aDebug) {
- let options = { debug: aDebug };
- this.send(null, "setDebugFlag", options);
- },
-
- debug: function(aClientId, aMessage) {
- // We use the same debug subject with RadioInterface's here.
- dump("-*- RadioInterface[" + aClientId + "]: " + aMessage + "\n");
- },
-
- onerror: function(event) {
- if (DEBUG) {
- this.debug("X", "Got an error: " + event.filename + ":" +
- event.lineno + ": " + event.message + "\n");
- }
- event.preventDefault();
- },
-
- /**
- * Process the incoming message from the RIL worker.
- */
- onmessage: function(event) {
- let message = event.data;
- let clientId = message.rilMessageClientId;
- if (clientId === null) {
- return;
- }
-
- if (DEBUG) {
- this.debug(clientId, "Received message from worker: " + JSON.stringify(message));
- }
-
- let token = message.rilMessageToken;
- if (token == null) {
- // That's an unsolicited message. Pass to RadioInterface directly.
- let radioInterface = this.radioInterfaces[clientId];
- radioInterface.handleUnsolicitedWorkerMessage(message);
- return;
- }
-
- let callback = this.tokenCallbackMap[message.rilMessageToken];
- if (!callback) {
- if (DEBUG) this.debug(clientId, "Ignore orphan token: " + message.rilMessageToken);
- return;
- }
-
- let keep = false;
- try {
- keep = callback(message);
- } catch(e) {
- if (DEBUG) this.debug(clientId, "callback throws an exception: " + e);
- }
-
- if (!keep) {
- delete this.tokenCallbackMap[message.rilMessageToken];
- }
- },
-
- registerClient: function(aClientId, aRadioInterface) {
- if (DEBUG) this.debug(aClientId, "Starting RIL Worker");
-
- // Keep a reference so that we can dispatch unsolicited messages to it.
- this.radioInterfaces[aClientId] = aRadioInterface;
-
- this.send(null, "registerClient", { clientId: aClientId });
- gSystemWorkerManager.registerRilWorker(aClientId, this.worker);
- },
-
- /**
- * Send arbitrary message to worker.
- *
- * @param rilMessageType
- * A text message type.
- * @param message [optional]
- * An optional message object to send.
- * @param callback [optional]
- * An optional callback function which is called when worker replies
- * with an message containing a "rilMessageToken" attribute of the
- * same value we passed. This callback function accepts only one
- * parameter -- the reply from worker. It also returns a boolean
- * value true to keep current token-callback mapping and wait for
- * another worker reply, or false to remove the mapping.
- */
- send: function(clientId, rilMessageType, message, callback) {
- message = message || {};
-
- message.rilMessageClientId = clientId;
- message.rilMessageToken = this.token;
- this.token++;
-
- if (callback) {
- // Only create the map if callback is provided. For sending a request
- // and intentionally leaving the callback undefined, that reply will
- // be dropped in |this.onmessage| because of that orphan token.
- //
- // For sending a request that never replied at all, we're fine with this
- // because no callback shall be passed and we leave nothing to be cleaned
- // up later.
- this.tokenCallbackMap[message.rilMessageToken] = callback;
- }
-
- message.rilMessageType = rilMessageType;
- this.worker.postMessage(message);
- }
-};
-
-function RadioInterface(aClientId, aWorkerMessenger) {
- this.clientId = aClientId;
- this.workerMessenger = {
- send: aWorkerMessenger.send.bind(aWorkerMessenger, aClientId)
- };
- aWorkerMessenger.registerClient(aClientId, this);
-
- this.operatorInfo = {};
-
- let lock = gSettingsService.createLock();
-
- // Read the "time.clock.automatic-update.enabled" setting to see if
- // we need to adjust the system clock time by NITZ or SNTP.
- lock.get(kSettingsClockAutoUpdateEnabled, this);
-
- // Read the "time.timezone.automatic-update.enabled" setting to see if
- // we need to adjust the system timezone by NITZ.
- lock.get(kSettingsTimezoneAutoUpdateEnabled, this);
-
- // Set "time.clock.automatic-update.available" to false when starting up.
- this.setClockAutoUpdateAvailable(false);
-
- // Set "time.timezone.automatic-update.available" to false when starting up.
- this.setTimezoneAutoUpdateAvailable(false);
-
- Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
- Services.obs.addObserver(this, kSysClockChangeObserverTopic, false);
- Services.obs.addObserver(this, kScreenStateChangedTopic, false);
-
- Services.obs.addObserver(this, kNetworkConnStateChangedTopic, false);
-
- this._sntp = new Sntp(this.setClockBySntp.bind(this),
- Services.prefs.getIntPref("network.sntp.maxRetryCount"),
- Services.prefs.getIntPref("network.sntp.refreshPeriod"),
- Services.prefs.getIntPref("network.sntp.timeout"),
- Services.prefs.getCharPref("network.sntp.pools").split(";"),
- Services.prefs.getIntPref("network.sntp.port"));
-}
-
-RadioInterface.prototype = {
-
- classID: RADIOINTERFACE_CID,
- classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACE_CID,
- classDescription: "RadioInterface",
- interfaces: [Ci.nsIRadioInterface]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterface,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- // A private wrapped WorkerMessenger instance.
- workerMessenger: null,
-
- debug: function(s) {
- dump("-*- RadioInterface[" + this.clientId + "]: " + s + "\n");
- },
-
- shutdown: function() {
- Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic);
- Services.obs.removeObserver(this, kSysClockChangeObserverTopic);
- Services.obs.removeObserver(this, kScreenStateChangedTopic);
- Services.obs.removeObserver(this, kNetworkConnStateChangedTopic);
- },
-
- isCardPresent: function() {
- let icc = gIccService.getIccByServiceId(this.clientId);
- let cardState = icc ? icc.cardState : Ci.nsIIcc.CARD_STATE_UNKNOWN;
- return cardState !== Ci.nsIIcc.CARD_STATE_UNDETECTED &&
- cardState !== Ci.nsIIcc.CARD_STATE_UNKNOWN;
- },
-
- handleUnsolicitedWorkerMessage: function(message) {
- switch (message.rilMessageType) {
- case "callRing":
- gTelephonyService.notifyCallRing();
- break;
- case "currentCalls":
- gTelephonyService.notifyCurrentCalls(this.clientId, message.calls);
- break;
- case "cdmaCallWaiting":
- gTelephonyService.notifyCdmaCallWaiting(this.clientId,
- message.waitingCall);
- break;
- case "suppSvcNotification":
- gTelephonyService.notifySupplementaryService(this.clientId,
- message.number,
- message.notification);
- break;
- case "ussdreceived":
- gTelephonyService.notifyUssdReceived(this.clientId, message.message,
- message.sessionEnded);
- break;
- case "datacalllistchanged":
- let dataCalls = message.datacalls.map(dataCall => new DataCall(dataCall));
- gDataCallInterfaceService.notifyDataCallListChanged(this.clientId,
- dataCalls.length,
- dataCalls);
- break;
- case "emergencyCbModeChange":
- gMobileConnectionService.notifyEmergencyCallbackModeChanged(this.clientId,
- message.active,
- message.timeoutMs);
- break;
- case "networkinfochanged":
- gMobileConnectionService.notifyNetworkInfoChanged(this.clientId,
- message);
- break;
- case "networkselectionmodechange":
- gMobileConnectionService.notifyNetworkSelectModeChanged(this.clientId,
- message.mode);
- break;
- case "voiceregistrationstatechange":
- gMobileConnectionService.notifyVoiceInfoChanged(this.clientId, message);
- break;
- case "dataregistrationstatechange":
- gMobileConnectionService.notifyDataInfoChanged(this.clientId, message);
- break;
- case "signalstrengthchange":
- gMobileConnectionService.notifySignalStrengthChanged(this.clientId,
- message);
- break;
- case "operatorchange":
- gMobileConnectionService.notifyOperatorChanged(this.clientId, message);
- break;
- case "otastatuschange":
- gMobileConnectionService.notifyOtaStatusChanged(this.clientId, message.status);
- break;
- case "deviceidentitieschange":
- gMobileConnectionService.notifyDeviceIdentitiesChanged(this.clientId,
- message.deviceIdentities.imei,
- message.deviceIdentities.imeisv,
- message.deviceIdentities.esn,
- message.deviceIdentities.meid);
- break;
- case "radiostatechange":
- // gRadioEnabledController should know the radio state for each client,
- // so notify gRadioEnabledController here.
- gRadioEnabledController.notifyRadioStateChanged(this.clientId,
- message.radioState);
- break;
- case "cardstatechange":
- gIccService.notifyCardStateChanged(this.clientId,
- message.cardState);
- gRadioEnabledController.receiveCardState(this.clientId);
- break;
- case "sms-received":
- this.handleSmsReceived(message);
- break;
- case "cellbroadcast-received":
- this.handleCellbroadcastMessageReceived(message);
- break;
- case "nitzTime":
- this.handleNitzTime(message);
- break;
- case "iccinfochange":
- gIccService.notifyIccInfoChanged(this.clientId,
- message.iccid ? message : null);
- break;
- case "iccimsi":
- gIccService.notifyImsiChanged(this.clientId, message.imsi);
- break;
- case "iccmbdn":
- this.handleIccMbdn(message);
- break;
- case "iccmwis":
- this.handleIccMwis(message.mwi);
- break;
- case "stkcommand":
- gIccService.notifyStkCommand(this.clientId,
- gStkCmdFactory.createCommand(message));
- break;
- case "stksessionend":
- gIccService.notifyStkSessionEnd(this.clientId);
- break;
- case "cdma-info-rec-received":
- this.handleCdmaInformationRecords(message.records);
- break;
- default:
- throw new Error("Don't know about this message type: " +
- message.rilMessageType);
- }
- },
-
- setDataRegistration: function(attach) {
- let deferred = Promise.defer();
- this.workerMessenger.send("setDataRegistration",
- {attach: attach},
- (function(response) {
- // Always resolve to proceed with the following steps.
- deferred.resolve(response.errorMsg ? response.errorMsg : null);
- }).bind(this));
-
- return deferred.promise;
- },
-
- /**
- * TODO: Bug 911713 - B2G NetworkManager: Move policy control logic to
- * NetworkManager
- */
- updateRILNetworkInterface: function() {
- let connHandler = gDataCallManager.getDataCallHandler(this.clientId);
- connHandler.updateRILNetworkInterface();
- },
-
- /**
- * handle received SMS.
- */
- handleSmsReceived: function(aMessage) {
- let header = aMessage.header;
- // Concatenation Info:
- // - segmentRef: a modulo 256 counter indicating the reference number for a
- // particular concatenated short message. '0' is a valid number.
- // - The concatenation info will not be available in |header| if
- // segmentSeq or segmentMaxSeq is 0.
- // See 3GPP TS 23.040, 9.2.3.24.1 Concatenated Short Messages.
- let segmentRef = (header && header.segmentRef !== undefined)
- ? header.segmentRef : 1;
- let segmentSeq = header && header.segmentSeq || 1;
- let segmentMaxSeq = header && header.segmentMaxSeq || 1;
- // Application Ports:
- // The port number ranges from 0 to 49151.
- // see 3GPP TS 23.040, 9.2.3.24.3/4 Application Port Addressing.
- let originatorPort = (header && header.originatorPort !== undefined)
- ? header.originatorPort
- : Ci.nsIGonkSmsService.SMS_APPLICATION_PORT_INVALID;
- let destinationPort = (header && header.destinationPort !== undefined)
- ? header.destinationPort
- : Ci.nsIGonkSmsService.SMS_APPLICATION_PORT_INVALID;
- // MWI info:
- let mwiPresent = (aMessage.mwi)? true : false;
- let mwiDiscard = (mwiPresent)? aMessage.mwi.discard: false;
- let mwiMsgCount = (mwiPresent)? aMessage.mwi.msgCount: 0;
- let mwiActive = (mwiPresent)? aMessage.mwi.active: false;
- // CDMA related attributes:
- let cdmaMessageType = aMessage.messageType || 0;
- let cdmaTeleservice = aMessage.teleservice || 0;
- let cdmaServiceCategory = aMessage.serviceCategory || 0;
-
- gSmsService
- .notifyMessageReceived(this.clientId,
- aMessage.SMSC || null,
- aMessage.sentTimestamp,
- aMessage.sender,
- aMessage.pid,
- aMessage.encoding,
- RIL.GECKO_SMS_MESSAGE_CLASSES
- .indexOf(aMessage.messageClass),
- aMessage.language || null,
- segmentRef,
- segmentSeq,
- segmentMaxSeq,
- originatorPort,
- destinationPort,
- mwiPresent,
- mwiDiscard,
- mwiMsgCount,
- mwiActive,
- cdmaMessageType,
- cdmaTeleservice,
- cdmaServiceCategory,
- aMessage.body || null,
- aMessage.data || [],
- (aMessage.data) ? aMessage.data.length : 0);
- },
-
- /**
- * Set the setting value of "time.clock.automatic-update.available".
- */
- setClockAutoUpdateAvailable: function(value) {
- gSettingsService.createLock().set(kSettingsClockAutoUpdateAvailable, value, null);
- },
-
- /**
- * Set the setting value of "time.timezone.automatic-update.available".
- */
- setTimezoneAutoUpdateAvailable: function(value) {
- gSettingsService.createLock().set(kSettingsTimezoneAutoUpdateAvailable, value, null);
- },
-
- /**
- * Set the system clock by NITZ.
- */
- setClockByNitz: function(message) {
- // To set the system clock time. Note that there could be a time diff
- // between when the NITZ was received and when the time is actually set.
- gTimeService.set(
- message.networkTimeInMS + (Date.now() - message.receiveTimeInMS));
- },
-
- /**
- * Set the system time zone by NITZ.
- */
- setTimezoneByNitz: function(message) {
- // To set the sytem timezone. Note that we need to convert the time zone
- // value to a UTC repesentation string in the format of "UTC(+/-)hh:mm".
- // Ex, time zone -480 is "UTC+08:00"; time zone 630 is "UTC-10:30".
- //
- // We can unapply the DST correction if we want the raw time zone offset:
- // message.networkTimeZoneInMinutes -= message.networkDSTInMinutes;
- if (message.networkTimeZoneInMinutes != (new Date()).getTimezoneOffset()) {
- let absTimeZoneInMinutes = Math.abs(message.networkTimeZoneInMinutes);
- let timeZoneStr = "UTC";
- timeZoneStr += (message.networkTimeZoneInMinutes > 0 ? "-" : "+");
- timeZoneStr += ("0" + Math.floor(absTimeZoneInMinutes / 60)).slice(-2);
- timeZoneStr += ":";
- timeZoneStr += ("0" + absTimeZoneInMinutes % 60).slice(-2);
- gSettingsService.createLock().set("time.timezone", timeZoneStr, null);
- }
- },
-
- /**
- * Handle the NITZ message.
- */
- handleNitzTime: function(message) {
- // Got the NITZ info received from the ril_worker.
- this.setClockAutoUpdateAvailable(true);
- this.setTimezoneAutoUpdateAvailable(true);
-
- // Cache the latest NITZ message whenever receiving it.
- this._lastNitzMessage = message;
-
- // Set the received NITZ clock if the setting is enabled.
- if (this._clockAutoUpdateEnabled) {
- this.setClockByNitz(message);
- }
- // Set the received NITZ timezone if the setting is enabled.
- if (this._timezoneAutoUpdateEnabled) {
- this.setTimezoneByNitz(message);
- }
- },
-
- /**
- * Set the system clock by SNTP.
- */
- setClockBySntp: function(offset) {
- // Got the SNTP info.
- this.setClockAutoUpdateAvailable(true);
- if (!this._clockAutoUpdateEnabled) {
- return;
- }
- if (this._lastNitzMessage) {
- if (DEBUG) debug("SNTP: NITZ available, discard SNTP");
- return;
- }
- gTimeService.set(Date.now() + offset);
- },
-
- handleIccMbdn: function(message) {
- let service = Cc["@mozilla.org/voicemail/voicemailservice;1"]
- .getService(Ci.nsIGonkVoicemailService);
- service.notifyInfoChanged(this.clientId, message.number, message.alphaId);
- },
-
- handleIccMwis: function(mwi) {
- let service = Cc["@mozilla.org/voicemail/voicemailservice;1"]
- .getService(Ci.nsIGonkVoicemailService);
- // Note: returnNumber and returnMessage is not available from UICC.
- service.notifyStatusChanged(this.clientId, mwi.active, mwi.msgCount,
- null, null);
- },
-
- _convertCbGsmGeographicalScope: function(aGeographicalScope) {
- return (aGeographicalScope != null)
- ? aGeographicalScope
- : Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_INVALID;
- },
-
- _convertCbMessageClass: function(aMessageClass) {
- let index = RIL.GECKO_SMS_MESSAGE_CLASSES.indexOf(aMessageClass);
- return (index != -1)
- ? index
- : Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_NORMAL;
- },
-
- _convertCbEtwsWarningType: function(aWarningType) {
- return (aWarningType != null)
- ? aWarningType
- : Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID;
- },
-
- handleCellbroadcastMessageReceived: function(aMessage) {
- let etwsInfo = aMessage.etws;
- let hasEtwsInfo = etwsInfo != null;
- let serviceCategory = (aMessage.serviceCategory)
- ? aMessage.serviceCategory
- : Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID;
-
- gCellBroadcastService
- .notifyMessageReceived(this.clientId,
- this._convertCbGsmGeographicalScope(aMessage.geographicalScope),
- aMessage.messageCode,
- aMessage.messageId,
- aMessage.language,
- aMessage.fullBody,
- this._convertCbMessageClass(aMessage.messageClass),
- Date.now(),
- serviceCategory,
- hasEtwsInfo,
- (hasEtwsInfo)
- ? this._convertCbEtwsWarningType(etwsInfo.warningType)
- : Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID,
- hasEtwsInfo ? etwsInfo.emergencyUserAlert : false,
- hasEtwsInfo ? etwsInfo.popup : false);
- },
-
- handleCdmaInformationRecords: function(aRecords) {
- if (DEBUG) this.debug("cdma-info-rec-received: " + JSON.stringify(aRecords));
-
- let clientId = this.clientId;
-
- aRecords.forEach(function(aRecord) {
- if (aRecord.display) {
- gMobileConnectionService
- .notifyCdmaInfoRecDisplay(clientId, aRecord.display);
- return;
- }
-
- if (aRecord.calledNumber) {
- gMobileConnectionService
- .notifyCdmaInfoRecCalledPartyNumber(clientId,
- aRecord.calledNumber.type,
- aRecord.calledNumber.plan,
- aRecord.calledNumber.number,
- aRecord.calledNumber.pi,
- aRecord.calledNumber.si);
- return;
- }
-
- if (aRecord.callingNumber) {
- gMobileConnectionService
- .notifyCdmaInfoRecCallingPartyNumber(clientId,
- aRecord.callingNumber.type,
- aRecord.callingNumber.plan,
- aRecord.callingNumber.number,
- aRecord.callingNumber.pi,
- aRecord.callingNumber.si);
- return;
- }
-
- if (aRecord.connectedNumber) {
- gMobileConnectionService
- .notifyCdmaInfoRecConnectedPartyNumber(clientId,
- aRecord.connectedNumber.type,
- aRecord.connectedNumber.plan,
- aRecord.connectedNumber.number,
- aRecord.connectedNumber.pi,
- aRecord.connectedNumber.si);
- return;
- }
-
- if (aRecord.signal) {
- gMobileConnectionService
- .notifyCdmaInfoRecSignal(clientId,
- aRecord.signal.type,
- aRecord.signal.alertPitch,
- aRecord.signal.signal);
- return;
- }
-
- if (aRecord.redirect) {
- gMobileConnectionService
- .notifyCdmaInfoRecRedirectingNumber(clientId,
- aRecord.redirect.type,
- aRecord.redirect.plan,
- aRecord.redirect.number,
- aRecord.redirect.pi,
- aRecord.redirect.si,
- aRecord.redirect.reason);
- return;
- }
-
- if (aRecord.lineControl) {
- gMobileConnectionService
- .notifyCdmaInfoRecLineControl(clientId,
- aRecord.lineControl.polarityIncluded,
- aRecord.lineControl.toggle,
- aRecord.lineControl.reverse,
- aRecord.lineControl.powerDenial);
- return;
- }
-
- if (aRecord.clirCause) {
- gMobileConnectionService
- .notifyCdmaInfoRecClir(clientId,
- aRecord.clirCause);
- return;
- }
-
- if (aRecord.audioControl) {
- gMobileConnectionService
- .notifyCdmaInfoRecAudioControl(clientId,
- aRecord.audioControl.upLink,
- aRecord.audioControl.downLink);
- return;
- }
- });
- },
-
- // nsIObserver
-
- observe: function(subject, topic, data) {
- switch (topic) {
- case kMozSettingsChangedObserverTopic:
- if ("wrappedJSObject" in subject) {
- subject = subject.wrappedJSObject;
- }
- this.handleSettingsChange(subject.key, subject.value, subject.isInternalChange);
- break;
- case kSysClockChangeObserverTopic:
- let offset = parseInt(data, 10);
- if (this._lastNitzMessage) {
- this._lastNitzMessage.receiveTimeInMS += offset;
- }
- this._sntp.updateOffset(offset);
- break;
- case kNetworkConnStateChangedTopic:
- let networkInfo = subject.QueryInterface(Ci.nsINetworkInfo);
- if (networkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- return;
- }
-
- // SNTP can only update when we have mobile or Wifi connections.
- if (networkInfo.type != NETWORK_TYPE_WIFI &&
- networkInfo.type != NETWORK_TYPE_MOBILE) {
- return;
- }
-
- // If the network comes from RIL, make sure the RIL service is matched.
- if (subject instanceof Ci.nsIRilNetworkInfo) {
- networkInfo = subject.QueryInterface(Ci.nsIRilNetworkInfo);
- if (networkInfo.serviceId != this.clientId) {
- return;
- }
- }
-
- // SNTP won't update unless the SNTP is already expired.
- if (this._sntp.isExpired()) {
- this._sntp.request();
- }
- break;
- case kScreenStateChangedTopic:
- this.workerMessenger.send("setScreenState", { on: (data === "on") });
- break;
- }
- },
-
- // Flag to determine whether to update system clock automatically. It
- // corresponds to the "time.clock.automatic-update.enabled" setting.
- _clockAutoUpdateEnabled: null,
-
- // Flag to determine whether to update system timezone automatically. It
- // corresponds to the "time.clock.automatic-update.enabled" setting.
- _timezoneAutoUpdateEnabled: null,
-
- // Remember the last NITZ message so that we can set the time based on
- // the network immediately when users enable network-based time.
- _lastNitzMessage: null,
-
- // Object that handles SNTP.
- _sntp: null,
-
- // Cell Broadcast settings values.
- _cellBroadcastSearchList: null,
-
- handleSettingsChange: function(aName, aResult, aIsInternalSetting) {
- // Don't allow any content processes to modify the setting
- // "time.clock.automatic-update.available" except for the chrome process.
- if (aName === kSettingsClockAutoUpdateAvailable &&
- !aIsInternalSetting) {
- let isClockAutoUpdateAvailable = this._lastNitzMessage !== null ||
- this._sntp.isAvailable();
- if (aResult !== isClockAutoUpdateAvailable) {
- if (DEBUG) {
- debug("Content processes cannot modify 'time.clock.automatic-update.available'. Restore!");
- }
- // Restore the setting to the current value.
- this.setClockAutoUpdateAvailable(isClockAutoUpdateAvailable);
- }
- }
-
- // Don't allow any content processes to modify the setting
- // "time.timezone.automatic-update.available" except for the chrome
- // process.
- if (aName === kSettingsTimezoneAutoUpdateAvailable &&
- !aIsInternalSetting) {
- let isTimezoneAutoUpdateAvailable = this._lastNitzMessage !== null;
- if (aResult !== isTimezoneAutoUpdateAvailable) {
- if (DEBUG) {
- this.debug("Content processes cannot modify 'time.timezone.automatic-update.available'. Restore!");
- }
- // Restore the setting to the current value.
- this.setTimezoneAutoUpdateAvailable(isTimezoneAutoUpdateAvailable);
- }
- }
-
- this.handle(aName, aResult);
- },
-
- // nsISettingsServiceCallback
- handle: function(aName, aResult) {
- switch(aName) {
- case kSettingsClockAutoUpdateEnabled:
- this._clockAutoUpdateEnabled = aResult;
- if (!this._clockAutoUpdateEnabled) {
- break;
- }
-
- // Set the latest cached NITZ time if it's available.
- if (this._lastNitzMessage) {
- this.setClockByNitz(this._lastNitzMessage);
- } else if (gNetworkManager.activeNetworkInfo &&
- gNetworkManager.activeNetworkInfo.state ==
- Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- // Set the latest cached SNTP time if it's available.
- if (!this._sntp.isExpired()) {
- this.setClockBySntp(this._sntp.getOffset());
- } else {
- // Or refresh the SNTP.
- this._sntp.request();
- }
- } else {
- // Set a sane minimum time.
- let buildTime = libcutils.property_get("ro.build.date.utc", "0") * 1000;
- let file = FileUtils.File("/system/b2g/b2g");
- if (file.lastModifiedTime > buildTime) {
- buildTime = file.lastModifiedTime;
- }
- if (buildTime > Date.now()) {
- gTimeService.set(buildTime);
- }
- }
- break;
- case kSettingsTimezoneAutoUpdateEnabled:
- this._timezoneAutoUpdateEnabled = aResult;
-
- if (this._timezoneAutoUpdateEnabled) {
- // Apply the latest cached NITZ for timezone if it's available.
- if (this._timezoneAutoUpdateEnabled && this._lastNitzMessage) {
- this.setTimezoneByNitz(this._lastNitzMessage);
- }
- }
- break;
- }
- },
-
- handleError: function(aErrorMessage) {
- if (DEBUG) {
- this.debug("There was an error while reading RIL settings.");
- }
- },
-
- // nsIRadioInterface
-
- // TODO: Bug 928861 - B2G NetworkManager: Provide a more generic function
- // for connecting
- setupDataCallByType: function(networkType) {
- let connHandler = gDataCallManager.getDataCallHandler(this.clientId);
- connHandler.setupDataCallByType(networkType);
- },
-
- // TODO: Bug 928861 - B2G NetworkManager: Provide a more generic function
- // for connecting
- deactivateDataCallByType: function(networkType) {
- let connHandler = gDataCallManager.getDataCallHandler(this.clientId);
- connHandler.deactivateDataCallByType(networkType);
- },
-
- // TODO: Bug 904514 - [meta] NetworkManager enhancement
- getDataCallStateByType: function(networkType) {
- let connHandler = gDataCallManager.getDataCallHandler(this.clientId);
- return connHandler.getDataCallStateByType(networkType);
- },
-
- sendWorkerMessage: function(rilMessageType, message, callback) {
- // Special handler for setRadioEnabled.
- if (rilMessageType === "setRadioEnabled") {
- // Forward it to gRadioEnabledController.
- gRadioEnabledController.setRadioEnabled(this.clientId, message,
- callback.handleResponse);
- return;
- }
-
- if (callback) {
- this.workerMessenger.send(rilMessageType, message, function(response) {
- return callback.handleResponse(response);
- });
- } else {
- this.workerMessenger.send(rilMessageType, message);
- }
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RadioInterfaceLayer]);
diff --git a/dom/system/gonk/RadioInterfaceLayer.manifest b/dom/system/gonk/RadioInterfaceLayer.manifest
deleted file mode 100644
index 3c7c3b808..000000000
--- a/dom/system/gonk/RadioInterfaceLayer.manifest
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2012 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# RadioInterfaceLayer.js
-component {2d831c8d-6017-435b-a80c-e5d422810cea} RadioInterfaceLayer.js
-contract @mozilla.org/ril;1 {2d831c8d-6017-435b-a80c-e5d422810cea}
-category profile-after-change RadioInterfaceLayer @mozilla.org/ril;1
diff --git a/dom/system/gonk/SystemProperty.cpp b/dom/system/gonk/SystemProperty.cpp
deleted file mode 100644
index 1f874ce90..000000000
--- a/dom/system/gonk/SystemProperty.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SystemProperty.h"
-
-#include <dlfcn.h>
-#include <string.h>
-
-#include "nsDebug.h"
-#include "prinit.h"
-
-namespace mozilla {
-namespace system {
-
-namespace {
-
-typedef int (*PropertyGet)(const char*, char*, const char*);
-typedef int (*PropertySet)(const char*, const char*);
-
-static void *sLibcUtils;
-static PRCallOnceType sInitLibcUtils;
-
-static int
-FakePropertyGet(const char* key, char* value, const char* default_value)
-{
- if(!default_value) {
- value[0] = '\0';
- return 0;
- }
-
- int len = strlen(default_value);
- if (len >= Property::VALUE_MAX_LENGTH) {
- len = Property::VALUE_MAX_LENGTH - 1;
- }
- memcpy(value, default_value, len);
- value[len] = '\0';
-
- return len;
-}
-
-static int
-FakePropertySet(const char* key, const char* value)
-{
- return 0;
-}
-
-static PRStatus
-InitLibcUtils()
-{
- sLibcUtils = dlopen("/system/lib/libcutils.so", RTLD_LAZY);
- // We will fallback to the fake getter/setter when sLibcUtils is not valid.
- return PR_SUCCESS;
-}
-
-static void*
-GetLibcUtils()
-{
- PR_CallOnce(&sInitLibcUtils, InitLibcUtils);
- return sLibcUtils;
-}
-
-} // anonymous namespace
-
-/*static*/ int
-Property::Get(const char* key, char* value, const char* default_value)
-{
- void *libcutils = GetLibcUtils();
- if (libcutils) {
- PropertyGet getter = (PropertyGet) dlsym(libcutils, "property_get");
- if (getter) {
- return getter(key, value, default_value);
- }
- NS_WARNING("Failed to get property_get() from libcutils!");
- }
- NS_WARNING("Fallback to the FakePropertyGet()");
- return FakePropertyGet(key, value, default_value);
-}
-
-/*static*/ int
-Property::Set(const char* key, const char* value)
-{
- void *libcutils = GetLibcUtils();
- if (libcutils) {
- PropertySet setter = (PropertySet) dlsym(libcutils, "property_set");
- if (setter) {
- return setter(key, value);
- }
- NS_WARNING("Failed to get property_set() from libcutils!");
- }
- NS_WARNING("Fallback to the FakePropertySet()");
- return FakePropertySet(key, value);
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/SystemProperty.h b/dom/system/gonk/SystemProperty.h
deleted file mode 100644
index 2b5ceae8b..000000000
--- a/dom/system/gonk/SystemProperty.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_Property_h
-#define mozilla_system_Property_h
-
-namespace mozilla {
-namespace system {
-
-/**
-* Abstraction of property_get/property_get in libcutils from AOSP.
-*/
-class Property
-{
-public:
- // Constants defined in system_properties.h from AOSP.
- enum {
- KEY_MAX_LENGTH = 32,
- VALUE_MAX_LENGTH = 92
- };
-
- static int
- Get(const char* key, char* value, const char* default_value);
-
- static int
- Set(const char* key, const char* value);
-
-private:
- Property() {}
- virtual ~Property() {}
-};
-
-} // namespace system
-} // namespace mozilla
-
- #endif // mozilla_system_Property_h
diff --git a/dom/system/gonk/SystemWorkerManager.cpp b/dom/system/gonk/SystemWorkerManager.cpp
deleted file mode 100644
index ee3fc8de3..000000000
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SystemWorkerManager.h"
-
-#include "nsINetworkService.h"
-#include "nsIWifi.h"
-#include "nsIWorkerHolder.h"
-#include "nsIXPConnect.h"
-
-#include "jsfriendapi.h"
-#include "mozilla/dom/workers/Workers.h"
-#include "AutoMounter.h"
-#include "TimeZoneSettingObserver.h"
-#include "AudioManager.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/ipc/KeyStore.h"
-#include "nsIObserverService.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "WifiWorker.h"
-#include "mozilla/Services.h"
-
-USING_WORKERS_NAMESPACE
-
-using namespace mozilla::dom::gonk;
-using namespace mozilla::ipc;
-using namespace mozilla::system;
-
-namespace {
-
-NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID);
-
-// Doesn't carry a reference, we're owned by services.
-SystemWorkerManager *gInstance = nullptr;
-
-} // namespace
-
-SystemWorkerManager::SystemWorkerManager()
- : mShutdown(false)
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
- NS_ASSERTION(!gInstance, "There should only be one instance!");
-}
-
-SystemWorkerManager::~SystemWorkerManager()
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
- NS_ASSERTION(!gInstance || gInstance == this,
- "There should only be one instance!");
- gInstance = nullptr;
-}
-
-nsresult
-SystemWorkerManager::Init()
-{
- if (!XRE_IsParentProcess()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread");
- NS_ASSERTION(!mShutdown, "Already shutdown!");
-
- nsresult rv = InitWifi();
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to initialize WiFi Networking!");
- return rv;
- }
-
- InitKeyStore();
-
- InitAutoMounter();
- InitializeTimeZoneSettingObserver();
- nsCOMPtr<nsIAudioManager> audioManager =
- do_GetService(NS_AUDIOMANAGER_CONTRACTID);
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (!obs) {
- NS_WARNING("Failed to get observer service!");
- return NS_ERROR_FAILURE;
- }
-
- rv = obs->AddObserver(this, WORKERS_SHUTDOWN_TOPIC, false);
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to initialize worker shutdown event!");
- return rv;
- }
-
- return NS_OK;
-}
-
-void
-SystemWorkerManager::Shutdown()
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
- mShutdown = true;
-
- ShutdownAutoMounter();
-
- nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
- if (wifi) {
- wifi->Shutdown();
- wifi = nullptr;
- }
- mWifiWorker = nullptr;
-
- if (mKeyStore) {
- mKeyStore->Shutdown();
- mKeyStore = nullptr;
- }
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- obs->RemoveObserver(this, WORKERS_SHUTDOWN_TOPIC);
- }
-}
-
-// static
-already_AddRefed<SystemWorkerManager>
-SystemWorkerManager::FactoryCreate()
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
- RefPtr<SystemWorkerManager> instance(gInstance);
-
- if (!instance) {
- instance = new SystemWorkerManager();
- if (NS_FAILED(instance->Init())) {
- instance->Shutdown();
- return nullptr;
- }
-
- gInstance = instance;
- }
-
- return instance.forget();
-}
-
-// static
-nsIInterfaceRequestor*
-SystemWorkerManager::GetInterfaceRequestor()
-{
- return gInstance;
-}
-
-NS_IMETHODIMP
-SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult)
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
- if (aIID.Equals(NS_GET_IID(nsIWifi))) {
- return CallQueryInterface(mWifiWorker,
- reinterpret_cast<nsIWifi**>(aResult));
- }
-
- NS_WARNING("Got nothing for the requested IID!");
- return NS_ERROR_NO_INTERFACE;
-}
-
-nsresult
-SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
- JS::Handle<JS::Value> aWorker,
- JSContext *aCx)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-nsresult
-SystemWorkerManager::InitWifi()
-{
- nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kWifiWorkerCID);
- NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
-
- mWifiWorker = worker;
- return NS_OK;
-}
-
-nsresult
-SystemWorkerManager::InitKeyStore()
-{
- mKeyStore = new KeyStore();
- return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(SystemWorkerManager,
- nsIObserver,
- nsIInterfaceRequestor,
- nsISystemWorkerManager)
-
-NS_IMETHODIMP
-SystemWorkerManager::Observe(nsISupports *aSubject, const char *aTopic,
- const char16_t *aData)
-{
- if (!strcmp(aTopic, WORKERS_SHUTDOWN_TOPIC)) {
- Shutdown();
- }
-
- return NS_OK;
-}
diff --git a/dom/system/gonk/SystemWorkerManager.h b/dom/system/gonk/SystemWorkerManager.h
deleted file mode 100644
index 625cda261..000000000
--- a/dom/system/gonk/SystemWorkerManager.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef mozilla_dom_system_b2g_systemworkermanager_h__
-#define mozilla_dom_system_b2g_systemworkermanager_h__
-
-#include "nsIInterfaceRequestor.h"
-#include "nsISystemWorkerManager.h"
-#include "nsIObserver.h"
-#include "nsCOMPtr.h"
-#include "nsXULAppAPI.h" // For XRE_GetProcessType
-
-class nsIWorkerHolder;
-
-namespace mozilla {
-
-namespace ipc {
- class KeyStore;
-}
-
-namespace dom {
-namespace gonk {
-
-class SystemWorkerManager final : public nsIObserver,
- public nsIInterfaceRequestor,
- public nsISystemWorkerManager
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- NS_DECL_NSIINTERFACEREQUESTOR
- NS_DECL_NSISYSTEMWORKERMANAGER
-
- nsresult Init();
- void Shutdown();
-
- static already_AddRefed<SystemWorkerManager>
- FactoryCreate();
-
- static nsIInterfaceRequestor*
- GetInterfaceRequestor();
-
-private:
- SystemWorkerManager();
- ~SystemWorkerManager();
-
- nsresult InitWifi();
- nsresult InitKeyStore();
-
- nsCOMPtr<nsIWorkerHolder> mWifiWorker;
-
- RefPtr<mozilla::ipc::KeyStore> mKeyStore;
-
- bool mShutdown;
-};
-
-}
-}
-}
-
-#endif // mozilla_dom_system_b2g_systemworkermanager_h__
diff --git a/dom/system/gonk/TetheringService.js b/dom/system/gonk/TetheringService.js
deleted file mode 100644
index c5c478180..000000000
--- a/dom/system/gonk/TetheringService.js
+++ /dev/null
@@ -1,891 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-const TETHERINGSERVICE_CONTRACTID = "@mozilla.org/tethering/service;1";
-const TETHERINGSERVICE_CID =
- Components.ID("{527a4121-ee5a-4651-be9c-f46f59cf7c01}");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIMobileConnectionService");
-
-XPCOMUtils.defineLazyGetter(this, "gRil", function() {
- try {
- return Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
- } catch (e) {}
-
- return null;
-});
-
-const TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed";
-const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const PREF_MANAGE_OFFLINE_STATUS = "network.gonk.manage-offline-status";
-const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
-
-const POSSIBLE_USB_INTERFACE_NAME = "rndis0,usb0";
-const DEFAULT_USB_INTERFACE_NAME = "rndis0";
-const DEFAULT_3G_INTERFACE_NAME = "rmnet0";
-const DEFAULT_WIFI_INTERFACE_NAME = "wlan0";
-
-// The kernel's proc entry for network lists.
-const KERNEL_NETWORK_ENTRY = "/sys/class/net";
-
-const TETHERING_TYPE_WIFI = "WiFi";
-const TETHERING_TYPE_USB = "USB";
-
-const WIFI_FIRMWARE_AP = "AP";
-const WIFI_FIRMWARE_STATION = "STA";
-const WIFI_SECURITY_TYPE_NONE = "open";
-const WIFI_SECURITY_TYPE_WPA_PSK = "wpa-psk";
-const WIFI_SECURITY_TYPE_WPA2_PSK = "wpa2-psk";
-const WIFI_CTRL_INTERFACE = "wl0.1";
-
-const NETWORK_INTERFACE_UP = "up";
-const NETWORK_INTERFACE_DOWN = "down";
-
-const TETHERING_STATE_ONGOING = "ongoing";
-const TETHERING_STATE_IDLE = "idle";
-const TETHERING_STATE_ACTIVE = "active";
-
-// Settings DB path for USB tethering.
-const SETTINGS_USB_ENABLED = "tethering.usb.enabled";
-const SETTINGS_USB_IP = "tethering.usb.ip";
-const SETTINGS_USB_PREFIX = "tethering.usb.prefix";
-const SETTINGS_USB_DHCPSERVER_STARTIP = "tethering.usb.dhcpserver.startip";
-const SETTINGS_USB_DHCPSERVER_ENDIP = "tethering.usb.dhcpserver.endip";
-const SETTINGS_USB_DNS1 = "tethering.usb.dns1";
-const SETTINGS_USB_DNS2 = "tethering.usb.dns2";
-
-// Settings DB path for WIFI tethering.
-const SETTINGS_WIFI_DHCPSERVER_STARTIP = "tethering.wifi.dhcpserver.startip";
-const SETTINGS_WIFI_DHCPSERVER_ENDIP = "tethering.wifi.dhcpserver.endip";
-
-// Settings DB patch for dun required setting.
-const SETTINGS_DUN_REQUIRED = "tethering.dun.required";
-
-// Default value for USB tethering.
-const DEFAULT_USB_IP = "192.168.0.1";
-const DEFAULT_USB_PREFIX = "24";
-const DEFAULT_USB_DHCPSERVER_STARTIP = "192.168.0.10";
-const DEFAULT_USB_DHCPSERVER_ENDIP = "192.168.0.30";
-
-const DEFAULT_DNS1 = "8.8.8.8";
-const DEFAULT_DNS2 = "8.8.4.4";
-
-const DEFAULT_WIFI_DHCPSERVER_STARTIP = "192.168.1.10";
-const DEFAULT_WIFI_DHCPSERVER_ENDIP = "192.168.1.30";
-
-const SETTINGS_DATA_DEFAULT_SERVICE_ID = "ril.data.defaultServiceId";
-const MOBILE_DUN_CONNECT_TIMEOUT = 30000;
-const MOBILE_DUN_RETRY_INTERVAL = 5000;
-const MOBILE_DUN_MAX_RETRIES = 5;
-
-var debug;
-function updateDebug() {
- let debugPref = false; // set default value here.
- try {
- debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
- } catch (e) {}
-
- if (debugPref) {
- debug = function(s) {
- dump("-*- TetheringService: " + s + "\n");
- };
- } else {
- debug = function(s) {};
- }
-}
-updateDebug();
-
-function TetheringService() {
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
- Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false);
- Services.obs.addObserver(this, TOPIC_CONNECTION_STATE_CHANGED, false);
- Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
- Services.prefs.addObserver(PREF_MANAGE_OFFLINE_STATUS, this, false);
-
- try {
- this._manageOfflineStatus =
- Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
- } catch(ex) {
- // Ignore.
- }
-
- this._dataDefaultServiceId = 0;
-
- // Possible usb tethering interfaces for different gonk platform.
- this.possibleInterface = POSSIBLE_USB_INTERFACE_NAME.split(",");
-
- // Default values for internal and external interfaces.
- this._tetheringInterface = {};
- this._tetheringInterface[TETHERING_TYPE_USB] = {
- externalInterface: DEFAULT_3G_INTERFACE_NAME,
- internalInterface: DEFAULT_USB_INTERFACE_NAME
- };
- this._tetheringInterface[TETHERING_TYPE_WIFI] = {
- externalInterface: DEFAULT_3G_INTERFACE_NAME,
- internalInterface: DEFAULT_WIFI_INTERFACE_NAME
- };
-
- this.tetheringSettings = {};
- this.initTetheringSettings();
-
- let settingsLock = gSettingsService.createLock();
- // Read the default service id for data call.
- settingsLock.get(SETTINGS_DATA_DEFAULT_SERVICE_ID, this);
-
- // Read usb tethering data from settings DB.
- settingsLock.get(SETTINGS_USB_IP, this);
- settingsLock.get(SETTINGS_USB_PREFIX, this);
- settingsLock.get(SETTINGS_USB_DHCPSERVER_STARTIP, this);
- settingsLock.get(SETTINGS_USB_DHCPSERVER_ENDIP, this);
- settingsLock.get(SETTINGS_USB_DNS1, this);
- settingsLock.get(SETTINGS_USB_DNS2, this);
- settingsLock.get(SETTINGS_USB_ENABLED, this);
-
- // Read wifi tethering data from settings DB.
- settingsLock.get(SETTINGS_WIFI_DHCPSERVER_STARTIP, this);
- settingsLock.get(SETTINGS_WIFI_DHCPSERVER_ENDIP, this);
-
- this._usbTetheringSettingsToRead = [SETTINGS_USB_IP,
- SETTINGS_USB_PREFIX,
- SETTINGS_USB_DHCPSERVER_STARTIP,
- SETTINGS_USB_DHCPSERVER_ENDIP,
- SETTINGS_USB_DNS1,
- SETTINGS_USB_DNS2,
- SETTINGS_USB_ENABLED,
- SETTINGS_WIFI_DHCPSERVER_STARTIP,
- SETTINGS_WIFI_DHCPSERVER_ENDIP];
-
- this.wantConnectionEvent = null;
-
- this.dunConnectTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- this.dunRetryTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- this._pendingTetheringRequests = [];
-}
-TetheringService.prototype = {
- classID: TETHERINGSERVICE_CID,
- classInfo: XPCOMUtils.generateCI({classID: TETHERINGSERVICE_CID,
- contractID: TETHERINGSERVICE_CONTRACTID,
- classDescription: "Tethering Service",
- interfaces: [Ci.nsITetheringService]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITetheringService,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- // Flag to record the default client id for data call.
- _dataDefaultServiceId: null,
-
- // Number of usb tehering requests to be processed.
- _usbTetheringRequestCount: 0,
-
- // Usb tethering state.
- _usbTetheringAction: TETHERING_STATE_IDLE,
-
- // Tethering settings.
- tetheringSettings: null,
-
- // Tethering settings need to be read from settings DB.
- _usbTetheringSettingsToRead: null,
-
- // Previous usb tethering enabled state.
- _oldUsbTetheringEnabledState: null,
-
- // External and internal interface name.
- _tetheringInterface: null,
-
- // Dun connection timer.
- dunConnectTimer: null,
-
- // Dun connection retry times.
- dunRetryTimes: 0,
-
- // Dun retry timer.
- dunRetryTimer: null,
-
- // Pending tethering request to handle after dun is connected.
- _pendingTetheringRequests: null,
-
- // Flag to indicate wether wifi tethering is being processed.
- _wifiTetheringRequestOngoing: false,
-
- // Arguments for pending wifi tethering request.
- _pendingWifiTetheringRequestArgs: null,
-
- // The state of tethering.
- state: Ci.nsITetheringService.TETHERING_STATE_INACTIVE,
-
- // Flag to check if we can modify the Services.io.offline.
- _manageOfflineStatus: true,
-
- // nsIObserver
-
- observe: function(aSubject, aTopic, aData) {
- let network;
-
- switch(aTopic) {
- case TOPIC_PREF_CHANGED:
- if (aData === PREF_NETWORK_DEBUG_ENABLED) {
- updateDebug();
- }
- break;
- case TOPIC_MOZSETTINGS_CHANGED:
- if ("wrappedJSObject" in aSubject) {
- aSubject = aSubject.wrappedJSObject;
- }
- this.handle(aSubject.key, aSubject.value);
- break;
- case TOPIC_CONNECTION_STATE_CHANGED:
- network = aSubject.QueryInterface(Ci.nsINetworkInfo);
- debug("Network " + network.type + "/" + network.name +
- " changed state to " + network.state);
- this.onConnectionChanged(network);
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
- Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED);
- Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
- Services.prefs.removeObserver(PREF_MANAGE_OFFLINE_STATUS, this);
-
- this.dunConnectTimer.cancel();
- this.dunRetryTimer.cancel();
- break;
- case PREF_MANAGE_OFFLINE_STATUS:
- try {
- this._manageOfflineStatus =
- Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
- } catch(ex) {
- // Ignore.
- }
- break;
- }
- },
-
- // nsISettingsServiceCallback
-
- handle: function(aName, aResult) {
- switch(aName) {
- case SETTINGS_DATA_DEFAULT_SERVICE_ID:
- this._dataDefaultServiceId = aResult || 0;
- debug("'_dataDefaultServiceId' is now " + this._dataDefaultServiceId);
- break;
- case SETTINGS_USB_ENABLED:
- this._oldUsbTetheringEnabledState = this.tetheringSettings[SETTINGS_USB_ENABLED];
- case SETTINGS_USB_IP:
- case SETTINGS_USB_PREFIX:
- case SETTINGS_USB_DHCPSERVER_STARTIP:
- case SETTINGS_USB_DHCPSERVER_ENDIP:
- case SETTINGS_USB_DNS1:
- case SETTINGS_USB_DNS2:
- case SETTINGS_WIFI_DHCPSERVER_STARTIP:
- case SETTINGS_WIFI_DHCPSERVER_ENDIP:
- if (aResult !== null) {
- this.tetheringSettings[aName] = aResult;
- }
- debug("'" + aName + "'" + " is now " + this.tetheringSettings[aName]);
- let index = this._usbTetheringSettingsToRead.indexOf(aName);
-
- if (index != -1) {
- this._usbTetheringSettingsToRead.splice(index, 1);
- }
-
- if (this._usbTetheringSettingsToRead.length) {
- debug("We haven't read completely the usb Tethering data from settings db.");
- break;
- }
-
- if (this._oldUsbTetheringEnabledState === this.tetheringSettings[SETTINGS_USB_ENABLED]) {
- debug("No changes for SETTINGS_USB_ENABLED flag. Nothing to do.");
- this.handlePendingWifiTetheringRequest();
- break;
- }
-
- this._usbTetheringRequestCount++;
- if (this._usbTetheringRequestCount === 1) {
- if (this._wifiTetheringRequestOngoing) {
- debug('USB tethering request is blocked by ongoing wifi tethering request.');
- } else {
- this.handleLastUsbTetheringRequest();
- }
- }
- break;
- };
- },
-
- handleError: function(aErrorMessage) {
- debug("There was an error while reading Tethering settings.");
- this.tetheringSettings = {};
- this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
- },
-
- initTetheringSettings: function() {
- this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
- this.tetheringSettings[SETTINGS_USB_IP] = DEFAULT_USB_IP;
- this.tetheringSettings[SETTINGS_USB_PREFIX] = DEFAULT_USB_PREFIX;
- this.tetheringSettings[SETTINGS_USB_DHCPSERVER_STARTIP] = DEFAULT_USB_DHCPSERVER_STARTIP;
- this.tetheringSettings[SETTINGS_USB_DHCPSERVER_ENDIP] = DEFAULT_USB_DHCPSERVER_ENDIP;
- this.tetheringSettings[SETTINGS_USB_DNS1] = DEFAULT_DNS1;
- this.tetheringSettings[SETTINGS_USB_DNS2] = DEFAULT_DNS2;
-
- this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP] = DEFAULT_WIFI_DHCPSERVER_STARTIP;
- this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP] = DEFAULT_WIFI_DHCPSERVER_ENDIP;
-
- this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
- libcutils.property_get("ro.tethering.dun_required") === "1";
- },
-
- getNetworkInfo: function(aType, aServiceId) {
- for (let networkId in gNetworkManager.allNetworkInfo) {
- let networkInfo = gNetworkManager.allNetworkInfo[networkId];
- if (networkInfo.type == aType) {
- try {
- if (networkInfo instanceof Ci.nsIRilNetworkInfo) {
- let rilNetwork = networkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
- if (rilNetwork.serviceId != aServiceId) {
- continue;
- }
- }
- } catch (e) {}
- return networkInfo;
- }
- }
- return null;
- },
-
- handleLastUsbTetheringRequest: function() {
- debug('handleLastUsbTetheringRequest... ' + this._usbTetheringRequestCount);
-
- if (this._usbTetheringRequestCount === 0) {
- if (this.wantConnectionEvent) {
- if (this.tetheringSettings[SETTINGS_USB_ENABLED]) {
- this.wantConnectionEvent.call(this);
- }
- this.wantConnectionEvent = null;
- }
- this.handlePendingWifiTetheringRequest();
- return;
- }
-
- // Cancel the accumlated count to 1 since we only care about the
- // last state.
- this._usbTetheringRequestCount = 1;
- this.handleUSBTetheringToggle(this.tetheringSettings[SETTINGS_USB_ENABLED]);
- this.wantConnectionEvent = null;
- },
-
- handlePendingWifiTetheringRequest: function() {
- if (this._pendingWifiTetheringRequestArgs) {
- this.setWifiTethering.apply(this, this._pendingWifiTetheringRequestArgs);
- this._pendingWifiTetheringRequestArgs = null;
- }
- },
-
- /**
- * Callback when dun connection fails to connect within timeout.
- */
- onDunConnectTimerTimeout: function() {
- while (this._pendingTetheringRequests.length > 0) {
- debug("onDunConnectTimerTimeout: callback without network info.");
- let callback = this._pendingTetheringRequests.shift();
- if (typeof callback === 'function') {
- callback();
- }
- }
- },
-
- setupDunConnection: function() {
- this.dunRetryTimer.cancel();
- let connection =
- gMobileConnectionService.getItemByServiceId(this._dataDefaultServiceId);
- let data = connection && connection.data;
- if (data && data.state === "registered") {
- let ril = gRil.getRadioInterface(this._dataDefaultServiceId);
-
- this.dunRetryTimes = 0;
- ril.setupDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN);
- this.dunConnectTimer.cancel();
- this.dunConnectTimer.
- initWithCallback(this.onDunConnectTimerTimeout.bind(this),
- MOBILE_DUN_CONNECT_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
- return;
- }
-
- if (this.dunRetryTimes++ >= this.MOBILE_DUN_MAX_RETRIES) {
- debug("setupDunConnection: max retries reached.");
- this.dunRetryTimes = 0;
- // same as dun connect timeout.
- this.onDunConnectTimerTimeout();
- return;
- }
-
- debug("Data not ready, retry dun after " + MOBILE_DUN_RETRY_INTERVAL + " ms.");
- this.dunRetryTimer.
- initWithCallback(this.setupDunConnection.bind(this),
- MOBILE_DUN_RETRY_INTERVAL, Ci.nsITimer.TYPE_ONE_SHOT);
- },
-
- _dunActiveUsers: 0,
- handleDunConnection: function(aEnable, aCallback) {
- debug("handleDunConnection: " + aEnable);
- let dun = this.getNetworkInfo(
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN, this._dataDefaultServiceId);
-
- if (!aEnable) {
- this._dunActiveUsers--;
- if (this._dunActiveUsers > 0) {
- debug("Dun still needed by others, do not disconnect.")
- return;
- }
-
- this.dunRetryTimes = 0;
- this.dunRetryTimer.cancel();
- this.dunConnectTimer.cancel();
- this._pendingTetheringRequests = [];
-
- if (dun && (dun.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) {
- gRil.getRadioInterface(this._dataDefaultServiceId)
- .deactivateDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN);
- }
- return;
- }
-
- this._dunActiveUsers++;
- if (!dun || (dun.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) {
- debug("DUN data call inactive, setup dun data call!")
- this._pendingTetheringRequests.push(aCallback);
- this.dunRetryTimes = 0;
- this.setupDunConnection();
-
- return;
- }
-
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = dun.name;
- aCallback(dun);
- },
-
- handleUSBTetheringToggle: function(aEnable) {
- debug("handleUSBTetheringToggle: " + aEnable);
- if (aEnable &&
- (this._usbTetheringAction === TETHERING_STATE_ONGOING ||
- this._usbTetheringAction === TETHERING_STATE_ACTIVE)) {
- debug("Usb tethering already connecting/connected.");
- this._usbTetheringRequestCount = 0;
- this.handlePendingWifiTetheringRequest();
- return;
- }
-
- if (!aEnable &&
- this._usbTetheringAction === TETHERING_STATE_IDLE) {
- debug("Usb tethering already disconnected.");
- this._usbTetheringRequestCount = 0;
- this.handlePendingWifiTetheringRequest();
- return;
- }
-
- if (!aEnable) {
- this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
- gNetworkService.enableUsbRndis(false, this.enableUsbRndisResult.bind(this));
- return;
- }
-
- this.tetheringSettings[SETTINGS_USB_ENABLED] = true;
- this._usbTetheringAction = TETHERING_STATE_ONGOING;
-
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(true, (aNetworkInfo) => {
- if (!aNetworkInfo){
- this.usbTetheringResultReport(aEnable, "Dun connection failed");
- return;
- }
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
- aNetworkInfo.name;
- gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this));
- });
- return;
- }
-
- if (gNetworkManager.activeNetworkInfo) {
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
- gNetworkManager.activeNetworkInfo.name;
- } else {
- let mobile = this.getNetworkInfo(
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId);
- if (mobile && mobile.name) {
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name;
- }
- }
- gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this));
- },
-
- getUSBTetheringParameters: function(aEnable, aTetheringInterface) {
- let interfaceIp = this.tetheringSettings[SETTINGS_USB_IP];
- let prefix = this.tetheringSettings[SETTINGS_USB_PREFIX];
- let wifiDhcpStartIp = this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP];
- let wifiDhcpEndIp = this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP];
- let usbDhcpStartIp = this.tetheringSettings[SETTINGS_USB_DHCPSERVER_STARTIP];
- let usbDhcpEndIp = this.tetheringSettings[SETTINGS_USB_DHCPSERVER_ENDIP];
- let dns1 = this.tetheringSettings[SETTINGS_USB_DNS1];
- let dns2 = this.tetheringSettings[SETTINGS_USB_DNS2];
- let internalInterface = aTetheringInterface.internalInterface;
- let externalInterface = aTetheringInterface.externalInterface;
-
- // Using the default values here until application support these settings.
- if (interfaceIp == "" || prefix == "" ||
- wifiDhcpStartIp == "" || wifiDhcpEndIp == "" ||
- usbDhcpStartIp == "" || usbDhcpEndIp == "") {
- debug("Invalid subnet information.");
- return null;
- }
-
- return {
- ifname: internalInterface,
- ip: interfaceIp,
- prefix: prefix,
- wifiStartIp: wifiDhcpStartIp,
- wifiEndIp: wifiDhcpEndIp,
- usbStartIp: usbDhcpStartIp,
- usbEndIp: usbDhcpEndIp,
- dns1: dns1,
- dns2: dns2,
- internalIfname: internalInterface,
- externalIfname: externalInterface,
- enable: aEnable,
- link: aEnable ? NETWORK_INTERFACE_UP : NETWORK_INTERFACE_DOWN
- };
- },
-
- notifyError: function(aResetSettings, aCallback, aMsg) {
- if (aResetSettings) {
- let settingsLock = gSettingsService.createLock();
- // Disable wifi tethering with a useful error message for the user.
- settingsLock.set("tethering.wifi.enabled", false, null, aMsg);
- }
-
- debug("setWifiTethering: " + (aMsg ? aMsg : "success"));
-
- if (aCallback) {
- // Callback asynchronously to avoid netsted toggling.
- Services.tm.currentThread.dispatch(() => {
- aCallback.wifiTetheringEnabledChange(aMsg);
- }, Ci.nsIThread.DISPATCH_NORMAL);
- }
- },
-
- enableWifiTethering: function(aEnable, aConfig, aCallback) {
- // Fill in config's required fields.
- aConfig.ifname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
- aConfig.internalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
- aConfig.externalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface;
-
- this._wifiTetheringRequestOngoing = true;
- gNetworkService.setWifiTethering(aEnable, aConfig, (aError) => {
- // Change the tethering state to WIFI if there is no error.
- if (aEnable && !aError) {
- this.state = Ci.nsITetheringService.TETHERING_STATE_WIFI;
- } else {
- // If wifi thethering is disable, or any error happens,
- // then consider the following statements.
-
- // Check whether the state is USB now or not. If no then just change
- // it to INACTIVE, if yes then just keep it.
- // It means that don't let the disable or error of WIFI affect
- // the original active state.
- if (this.state != Ci.nsITetheringService.TETHERING_STATE_USB) {
- this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE;
- }
-
- // Disconnect dun on error or when wifi tethering is disabled.
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(false);
- }
- }
-
- if (this._manageOfflineStatus) {
- Services.io.offline = !this.isAnyConnected() &&
- (this.state ===
- Ci.nsITetheringService.TETHERING_STATE_INACTIVE);
- }
-
- let resetSettings = aError;
- debug('gNetworkService.setWifiTethering finished');
- this.notifyError(resetSettings, aCallback, aError);
- this._wifiTetheringRequestOngoing = false;
- if (this._usbTetheringRequestCount > 0) {
- debug('Perform pending USB tethering requests.');
- this.handleLastUsbTetheringRequest();
- }
- });
- },
-
- // Enable/disable WiFi tethering by sending commands to netd.
- setWifiTethering: function(aEnable, aInterfaceName, aConfig, aCallback) {
- debug("setWifiTethering: " + aEnable);
- if (!aInterfaceName) {
- this.notifyError(true, aCallback, "invalid network interface name");
- return;
- }
-
- if (!aConfig) {
- this.notifyError(true, aCallback, "invalid configuration");
- return;
- }
-
- if (this._usbTetheringRequestCount > 0) {
- // If there's still pending usb tethering request, save
- // the request params and redo |setWifiTethering| on
- // usb tethering task complete.
- debug('USB tethering request is being processed. Queue this wifi tethering request.');
- this._pendingWifiTetheringRequestArgs = Array.prototype.slice.call(arguments);
- debug('Pending args: ' + JSON.stringify(this._pendingWifiTetheringRequestArgs));
- return;
- }
-
- // Re-check again, test cases set this property later.
- this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
- libcutils.property_get("ro.tethering.dun_required") === "1";
-
- if (!aEnable) {
- this.enableWifiTethering(false, aConfig, aCallback);
- return;
- }
-
- this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface =
- aInterfaceName;
-
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(true, (aNetworkInfo) => {
- if (!aNetworkInfo) {
- this.notifyError(true, aCallback, "Dun connection failed");
- return;
- }
- this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface =
- aNetworkInfo.name;
- this.enableWifiTethering(true, aConfig, aCallback);
- });
- return;
- }
-
- let mobile = this.getNetworkInfo(
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId);
- // Update the real interface name
- if (mobile && mobile.name) {
- this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name;
- }
-
- this.enableWifiTethering(true, aConfig, aCallback);
- },
-
- // Enable/disable USB tethering by sending commands to netd.
- setUSBTethering: function(aEnable, aTetheringInterface, aCallback) {
- let params = this.getUSBTetheringParameters(aEnable, aTetheringInterface);
-
- if (params === null) {
- gNetworkService.enableUsbRndis(false, function() {
- this.usbTetheringResultReport(aEnable, "Invalid parameters");
- });
- return;
- }
-
- gNetworkService.setUSBTethering(aEnable, params, aCallback);
- },
-
- getUsbInterface: function() {
- // Find the rndis interface.
- for (let i = 0; i < this.possibleInterface.length; i++) {
- try {
- let file = new FileUtils.File(KERNEL_NETWORK_ENTRY + "/" +
- this.possibleInterface[i]);
- if (file.exists()) {
- return this.possibleInterface[i];
- }
- } catch (e) {
- debug("Not " + this.possibleInterface[i] + " interface.");
- }
- }
- debug("Can't find rndis interface in possible lists.");
- return DEFAULT_USB_INTERFACE_NAME;
- },
-
- enableUsbRndisResult: function(aSuccess, aEnable) {
- if (aSuccess) {
- // If enable is false, don't find usb interface cause it is already down,
- // just use the internal interface in settings.
- if (aEnable) {
- this._tetheringInterface[TETHERING_TYPE_USB].internalInterface =
- this.getUsbInterface();
- }
- this.setUSBTethering(aEnable,
- this._tetheringInterface[TETHERING_TYPE_USB],
- this.usbTetheringResultReport.bind(this, aEnable));
- } else {
- this.usbTetheringResultReport(aEnable, "enableUsbRndisResult failure");
- throw new Error("failed to set USB Function to adb");
- }
- },
-
- usbTetheringResultReport: function(aEnable, aError) {
- this._usbTetheringRequestCount--;
-
- let settingsLock = gSettingsService.createLock();
-
- debug('usbTetheringResultReport callback. enable: ' + aEnable +
- ', error: ' + aError);
-
- // Disable tethering settings when fail to enable it.
- if (aError) {
- this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
- settingsLock.set("tethering.usb.enabled", false, null);
- // Skip others request when we found an error.
- this._usbTetheringRequestCount = 0;
- this._usbTetheringAction = TETHERING_STATE_IDLE;
- // If the thethering state is WIFI now, then just keep it,
- // if not, just change the state to INACTIVE.
- // It means that don't let the error of USB affect the original active state.
- if (this.state != Ci.nsITetheringService.TETHERING_STATE_WIFI) {
- this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE;
- }
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(false);
- }
- } else {
- if (aEnable) {
- this._usbTetheringAction = TETHERING_STATE_ACTIVE;
- this.state = Ci.nsITetheringService.TETHERING_STATE_USB;
- } else {
- this._usbTetheringAction = TETHERING_STATE_IDLE;
- // If the state is now WIFI, don't let the disable of USB affect it.
- if (this.state != Ci.nsITetheringService.TETHERING_STATE_WIFI) {
- this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE;
- }
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(false);
- }
- }
-
- if (this._manageOfflineStatus) {
- Services.io.offline = !this.isAnyConnected() &&
- (this.state ===
- Ci.nsITetheringService.TETHERING_STATE_INACTIVE);
- }
-
- this.handleLastUsbTetheringRequest();
- }
- },
-
- onConnectionChangedReport: function(aSuccess, aExternalIfname) {
- debug("onConnectionChangedReport result: success " + aSuccess);
-
- if (aSuccess) {
- // Update the external interface.
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
- aExternalIfname;
- debug("Change the interface name to " + aExternalIfname);
- }
- },
-
- onConnectionChanged: function(aNetworkInfo) {
- if (aNetworkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- debug("We are only interested in CONNECTED event");
- return;
- }
-
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
- aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
- this.dunConnectTimer.cancel();
- debug("DUN data call connected, process callbacks.");
- while (this._pendingTetheringRequests.length > 0) {
- let callback = this._pendingTetheringRequests.shift();
- if (typeof callback === 'function') {
- callback(aNetworkInfo);
- }
- }
- return;
- }
-
- if (!this.tetheringSettings[SETTINGS_USB_ENABLED]) {
- debug("Usb tethering settings is not enabled");
- return;
- }
-
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
- aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN &&
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface ===
- aNetworkInfo.name) {
- debug("Dun required and dun interface is the same");
- return;
- }
-
- if (this._tetheringInterface[TETHERING_TYPE_USB].externalInterface ===
- gNetworkManager.activeNetworkInfo.name) {
- debug("The active interface is the same");
- return;
- }
-
- let previous = {
- internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface,
- externalIfname: this._tetheringInterface[TETHERING_TYPE_USB].externalInterface
- };
-
- let current = {
- internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface,
- externalIfname: aNetworkInfo.name
- };
-
- let callback = (() => {
- // Update external network interface.
- debug("Update upstream interface to " + aNetworkInfo.name);
- gNetworkService.updateUpStream(previous, current,
- this.onConnectionChangedReport.bind(this));
- });
-
- if (this._usbTetheringAction === TETHERING_STATE_ONGOING) {
- debug("Postpone the event and handle it when state is idle.");
- this.wantConnectionEvent = callback;
- return;
- }
- this.wantConnectionEvent = null;
-
- callback.call(this);
- },
-
- isAnyConnected: function() {
- let allNetworkInfo = gNetworkManager.allNetworkInfo;
- for (let networkId in allNetworkInfo) {
- if (allNetworkInfo.hasOwnProperty(networkId) &&
- allNetworkInfo[networkId].state === Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- return true;
- }
- }
- return false;
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TetheringService]);
diff --git a/dom/system/gonk/TetheringService.manifest b/dom/system/gonk/TetheringService.manifest
deleted file mode 100644
index b8f18dec1..000000000
--- a/dom/system/gonk/TetheringService.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-# TetheringService.js
-component {527a4121-ee5a-4651-be9c-f46f59cf7c01} TetheringService.js
-contract @mozilla.org/tethering/service;1 {527a4121-ee5a-4651-be9c-f46f59cf7c01}
-category profile-after-change TetheringService @mozilla.org/tethering/service;1
diff --git a/dom/system/gonk/TimeZoneSettingObserver.cpp b/dom/system/gonk/TimeZoneSettingObserver.cpp
deleted file mode 100644
index 512f79908..000000000
--- a/dom/system/gonk/TimeZoneSettingObserver.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "base/message_loop.h"
-#include "jsapi.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/Hal.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsISettingsService.h"
-#include "nsJSUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "TimeZoneSettingObserver.h"
-#include "xpcpublic.h"
-#include "nsContentUtils.h"
-#include "nsPrintfCString.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/SettingChangeNotificationBinding.h"
-
-#undef LOG
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Time Zone Setting" , ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "Time Zone Setting" , ## args)
-
-#define TIME_TIMEZONE "time.timezone"
-#define MOZSETTINGS_CHANGED "mozsettings-changed"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-namespace {
-
-class TimeZoneSettingObserver : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- TimeZoneSettingObserver();
- static nsresult SetTimeZone(const JS::Value &aValue, JSContext *aContext);
-
-protected:
- virtual ~TimeZoneSettingObserver();
-};
-
-class TimeZoneSettingCb final : public nsISettingsServiceCallback
-{
-public:
- NS_DECL_ISUPPORTS
-
- TimeZoneSettingCb() {}
-
- NS_IMETHOD Handle(const nsAString &aName, JS::Handle<JS::Value> aResult) {
-
- JSContext *cx = nsContentUtils::GetCurrentJSContext();
- NS_ENSURE_TRUE(cx, NS_OK);
-
- // If we don't have time.timezone value in the settings, we need
- // to initialize the settings based on the current system timezone
- // to make settings consistent with system. This usually happens
- // at the very first boot. After that, settings must have a value.
- if (aResult.isNull()) {
- // Get the current system time zone offset. Note that we need to
- // convert the value to a UTC representation in the format of
- // "UTC{+,-}hh:mm", so that the Gaia end can know how to interpret.
- // E.g., -480 is "UTC+08:00"; 630 is "UTC-10:30".
- int32_t timeZoneOffset = hal::GetTimezoneOffset();
- nsPrintfCString curTimeZone("UTC%+03d:%02d",
- -timeZoneOffset / 60,
- abs(timeZoneOffset) % 60);
-
- // Convert it to a JS string.
- NS_ConvertUTF8toUTF16 utf16Str(curTimeZone);
-
- JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
- utf16Str.get(),
- utf16Str.Length()));
- if (!jsStr) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- // Set the settings based on the current system timezone.
- nsCOMPtr<nsISettingsServiceLock> lock;
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- if (!settingsService) {
- ERR("Failed to get settingsLock service!");
- return NS_OK;
- }
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- JS::Rooted<JS::Value> value(cx, JS::StringValue(jsStr));
- lock->Set(TIME_TIMEZONE, value, nullptr, nullptr);
- return NS_OK;
- }
-
- // Set the system timezone based on the current settings.
- if (aResult.isString()) {
- return TimeZoneSettingObserver::SetTimeZone(aResult, cx);
- }
-
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(const nsAString &aName) {
- ERR("TimeZoneSettingCb::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
- return NS_OK;
- }
-
-protected:
- ~TimeZoneSettingCb() {}
-};
-
-NS_IMPL_ISUPPORTS(TimeZoneSettingCb, nsISettingsServiceCallback)
-
-TimeZoneSettingObserver::TimeZoneSettingObserver()
-{
- // Setup an observer to watch changes to the setting.
- nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
- if (!observerService) {
- ERR("GetObserverService failed");
- return;
- }
- nsresult rv;
- rv = observerService->AddObserver(this, MOZSETTINGS_CHANGED, false);
- if (NS_FAILED(rv)) {
- ERR("AddObserver failed");
- return;
- }
-
- // Read the 'time.timezone' setting in order to start with a known
- // value at boot time. The handle() will be called after reading.
- nsCOMPtr<nsISettingsServiceLock> lock;
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- if (!settingsService) {
- ERR("Failed to get settingsLock service!");
- return;
- }
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- nsCOMPtr<nsISettingsServiceCallback> callback = new TimeZoneSettingCb();
- lock->Get(TIME_TIMEZONE, callback);
-}
-
-nsresult TimeZoneSettingObserver::SetTimeZone(const JS::Value &aValue, JSContext *aContext)
-{
- // Convert the JS value to a nsCString type.
- // The value should be a JS string like "America/Chicago" or "UTC-05:00".
- nsAutoJSString valueStr;
- if (!valueStr.init(aContext, aValue.toString())) {
- ERR("Failed to convert JS value to nsCString");
- return NS_ERROR_FAILURE;
- }
- NS_ConvertUTF16toUTF8 newTimezone(valueStr);
-
- // Hal expects opposite sign from general notations,
- // so we need to flip it.
- if (newTimezone.Find(NS_LITERAL_CSTRING("UTC+")) == 0) {
- if (!newTimezone.SetCharAt('-', 3)) {
- return NS_ERROR_FAILURE;
- }
- } else if (newTimezone.Find(NS_LITERAL_CSTRING("UTC-")) == 0) {
- if (!newTimezone.SetCharAt('+', 3)) {
- return NS_ERROR_FAILURE;
- }
- }
-
- // Set the timezone only when the system timezone is not identical.
- nsCString curTimezone = hal::GetTimezone();
- if (!curTimezone.Equals(newTimezone)) {
- hal::SetTimezone(newTimezone);
- }
-
- return NS_OK;
-}
-
-TimeZoneSettingObserver::~TimeZoneSettingObserver()
-{
- nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
- if (observerService) {
- observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
- }
-}
-
-NS_IMPL_ISUPPORTS(TimeZoneSettingObserver, nsIObserver)
-
-NS_IMETHODIMP
-TimeZoneSettingObserver::Observe(nsISupports *aSubject,
- const char *aTopic,
- const char16_t *aData)
-{
- if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
- return NS_OK;
- }
-
- // Note that this function gets called for any and all settings changes,
- // so we need to carefully check if we have the one we're interested in.
- //
- // The string that we're interested in will be a JSON string that looks like:
- // {"key":"time.timezone","value":"America/Chicago"} or
- // {"key":"time.timezone","value":"UTC-05:00"}
-
- AutoSafeJSContext cx;
- RootedDictionary<SettingChangeNotification> setting(cx);
- if (!WrappedJSToDictionary(cx, aSubject, setting)) {
- return NS_OK;
- }
- if (!setting.mKey.EqualsASCII(TIME_TIMEZONE)) {
- return NS_OK;
- }
- if (!setting.mValue.isString()) {
- return NS_OK;
- }
-
- // Set the system timezone.
- return SetTimeZone(setting.mValue, cx);
-}
-
-} // namespace
-
-static mozilla::StaticRefPtr<TimeZoneSettingObserver> sTimeZoneSettingObserver;
-namespace mozilla {
-namespace system {
-void
-InitializeTimeZoneSettingObserver()
-{
- sTimeZoneSettingObserver = new TimeZoneSettingObserver();
- ClearOnShutdown(&sTimeZoneSettingObserver);
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/TimeZoneSettingObserver.h b/dom/system/gonk/TimeZoneSettingObserver.h
deleted file mode 100644
index 08b7cebb3..000000000
--- a/dom/system/gonk/TimeZoneSettingObserver.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_timesetting_h__
-#define mozilla_system_timesetting_h__
-
-namespace mozilla {
-namespace system {
-
-// Initialize TimeZoneSettingObserver which observes the time zone change
-// event from settings service. When receiving the event, it modifies the
-// system time zone.
-void InitializeTimeZoneSettingObserver();
-
-} // namespace system
-} // namespace mozilla
-
-#endif // mozilla_system_timesetting_h__
-
diff --git a/dom/system/gonk/Volume.cpp b/dom/system/gonk/Volume.cpp
deleted file mode 100644
index f90c7b693..000000000
--- a/dom/system/gonk/Volume.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "Volume.h"
-#include "VolumeCommand.h"
-#include "VolumeManager.h"
-#include "VolumeManagerLog.h"
-#include "nsIVolume.h"
-#include "nsXULAppAPI.h"
-
-#include <vold/ResponseCode.h>
-
-namespace mozilla {
-namespace system {
-
-#if DEBUG_VOLUME_OBSERVER
-void
-VolumeObserverList::Broadcast(Volume* const& aVolume)
-{
- uint32_t size = mObservers.Length();
- for (uint32_t i = 0; i < size; ++i) {
- LOG("VolumeObserverList::Broadcast to [%u] %p volume '%s'",
- i, mObservers[i], aVolume->NameStr());
- mObservers[i]->Notify(aVolume);
- }
-}
-#endif
-
-VolumeObserverList Volume::sEventObserverList;
-
-// We have a feature where volumes can be locked when mounted. This
-// is used to prevent a volume from being shared with the PC while
-// it is actively being used (say for storing an update image)
-//
-// We use WakeLocks (a poor choice of name, but it does what we want)
-// from the PowerManagerService to determine when we're locked.
-// In particular we'll create a wakelock called volume-NAME-GENERATION
-// (where NAME is the volume name, and GENERATION is its generation
-// number), and if this wakelock is locked, then we'll prevent a volume
-// from being shared.
-//
-// Implementation Details:
-//
-// Since the AutoMounter can only control when something gets mounted
-// and not when it gets unmounted (for example: a user pulls the SDCard)
-// and because Volume and nsVolume data structures are maintained on
-// separate threads, we have the potential for some race conditions.
-// We eliminate the race conditions by introducing the concept of a
-// generation number. Every time a volume transitions to the Mounted
-// state, it gets assigned a new generation number. Whenever the state
-// of a Volume changes, we send the updated state and current generation
-// number to the main thread where it gets updated in the nsVolume.
-//
-// Since WakeLocks can only be queried from the main-thread, the
-// nsVolumeService looks for WakeLock status changes, and forwards
-// the results to the IOThread.
-//
-// If the Volume (IOThread) receives a volume update where the generation
-// number mismatches, then the update is simply ignored.
-//
-// When a Volume (IOThread) initially becomes mounted, we assume it to
-// be locked until we get our first update from nsVolume (MainThread).
-static int32_t sMountGeneration = 0;
-
-static uint32_t sNextId = 1;
-
-// We don't get media inserted/removed events at startup. So we
-// assume it's present, and we'll be told that it's missing.
-Volume::Volume(const nsCSubstring& aName)
- : mMediaPresent(true),
- mState(nsIVolume::STATE_INIT),
- mName(aName),
- mMountGeneration(-1),
- mMountLocked(true), // Needs to agree with nsVolume::nsVolume
- mSharingEnabled(false),
- mFormatRequested(false),
- mMountRequested(false),
- mUnmountRequested(false),
- mCanBeShared(true),
- mIsSharing(false),
- mIsFormatting(false),
- mIsUnmounting(false),
- mIsRemovable(false),
- mIsHotSwappable(false),
- mId(sNextId++)
-{
- DBG("Volume %s: created", NameStr());
-}
-
-void
-Volume::Dump(const char* aLabel) const
-{
- LOG("%s: Volume: %s (%d) is %s and %s @ %s gen %d locked %d",
- aLabel,
- NameStr(),
- Id(),
- StateStr(),
- MediaPresent() ? "inserted" : "missing",
- MountPoint().get(),
- MountGeneration(),
- (int)IsMountLocked());
- LOG("%s: Sharing %s Mounting %s Formating %s Unmounting %s",
- aLabel,
- CanBeShared() ? (IsSharingEnabled() ? (IsSharing() ? "en-y" : "en-n")
- : "dis")
- : "x",
- IsMountRequested() ? "req" : "n",
- IsFormatRequested() ? (IsFormatting() ? "req-y" : "req-n")
- : (IsFormatting() ? "y" : "n"),
- IsUnmountRequested() ? (IsUnmounting() ? "req-y" : "req-n")
- : (IsUnmounting() ? "y" : "n"));
-}
-
-void
-Volume::ResolveAndSetMountPoint(const nsCSubstring& aMountPoint)
-{
- nsCString mountPoint(aMountPoint);
- char realPathBuf[PATH_MAX];
-
- // Call realpath so that we wind up with a path which is compatible with
- // functions like nsVolumeService::GetVolumeByPath.
-
- if (realpath(mountPoint.get(), realPathBuf) < 0) {
- // The path we were handed doesn't exist. Warn about it, but use it
- // anyways assuming that the user knows what they're doing.
-
- ERR("ResolveAndSetMountPoint: realpath on '%s' failed: %d",
- mountPoint.get(), errno);
- mMountPoint = mountPoint;
- } else {
- mMountPoint = realPathBuf;
- }
- DBG("Volume %s: Setting mountpoint to '%s'", NameStr(), mMountPoint.get());
-}
-
-void Volume::SetFakeVolume(const nsACString& aMountPoint)
-{
- this->mMountLocked = false;
- this->mCanBeShared = false;
- ResolveAndSetMountPoint(aMountPoint);
- SetState(nsIVolume::STATE_MOUNTED);
-}
-
-void
-Volume::SetIsSharing(bool aIsSharing)
-{
- if (aIsSharing == mIsSharing) {
- return;
- }
- mIsSharing = aIsSharing;
- LOG("Volume %s: IsSharing set to %d state %s",
- NameStr(), (int)mIsSharing, StateStr(mState));
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetIsFormatting(bool aIsFormatting)
-{
- if (aIsFormatting == mIsFormatting) {
- return;
- }
- mIsFormatting = aIsFormatting;
- LOG("Volume %s: IsFormatting set to %d state %s",
- NameStr(), (int)mIsFormatting, StateStr(mState));
- if (mIsFormatting) {
- sEventObserverList.Broadcast(this);
- }
-}
-
-void
-Volume::SetIsUnmounting(bool aIsUnmounting)
-{
- if (aIsUnmounting == mIsUnmounting) {
- return;
- }
- mIsUnmounting = aIsUnmounting;
- LOG("Volume %s: IsUnmounting set to %d state %s",
- NameStr(), (int)mIsUnmounting, StateStr(mState));
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetIsRemovable(bool aIsRemovable)
-{
- if (aIsRemovable == mIsRemovable) {
- return;
- }
- mIsRemovable = aIsRemovable;
- if (!mIsRemovable) {
- mIsHotSwappable = false;
- }
- LOG("Volume %s: IsRemovable set to %d state %s",
- NameStr(), (int)mIsRemovable, StateStr(mState));
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetIsHotSwappable(bool aIsHotSwappable)
-{
- if (aIsHotSwappable == mIsHotSwappable) {
- return;
- }
- mIsHotSwappable = aIsHotSwappable;
- if (mIsHotSwappable) {
- mIsRemovable = true;
- }
- LOG("Volume %s: IsHotSwappable set to %d state %s",
- NameStr(), (int)mIsHotSwappable, StateStr(mState));
- sEventObserverList.Broadcast(this);
-}
-
-bool
-Volume::BoolConfigValue(const nsCString& aConfigValue, bool& aBoolValue)
-{
- if (aConfigValue.EqualsLiteral("1") ||
- aConfigValue.LowerCaseEqualsLiteral("true")) {
- aBoolValue = true;
- return true;
- }
- if (aConfigValue.EqualsLiteral("0") ||
- aConfigValue.LowerCaseEqualsLiteral("false")) {
- aBoolValue = false;
- return true;
- }
- return false;
-}
-
-void
-Volume::SetConfig(const nsCString& aConfigName, const nsCString& aConfigValue)
-{
- if (aConfigName.LowerCaseEqualsLiteral("removable")) {
- bool value = false;
- if (BoolConfigValue(aConfigValue, value)) {
- SetIsRemovable(value);
- } else {
- ERR("Volume %s: invalid value '%s' for configuration '%s'",
- NameStr(), aConfigValue.get(), aConfigName.get());
- }
- return;
- }
- if (aConfigName.LowerCaseEqualsLiteral("hotswappable")) {
- bool value = false;
- if (BoolConfigValue(aConfigValue, value)) {
- SetIsHotSwappable(value);
- } else {
- ERR("Volume %s: invalid value '%s' for configuration '%s'",
- NameStr(), aConfigValue.get(), aConfigName.get());
- }
- return;
- }
- ERR("Volume %s: invalid config '%s'", NameStr(), aConfigName.get());
-}
-
-void
-Volume::SetMediaPresent(bool aMediaPresent)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // mMediaPresent is slightly redunant to the state, however
- // when media is removed (while Idle), we get the following:
- // 631 Volume sdcard /mnt/sdcard disk removed (179:0)
- // 605 Volume sdcard /mnt/sdcard state changed from 1 (Idle-Unmounted) to 0 (No-Media)
- //
- // And on media insertion, we get:
- // 630 Volume sdcard /mnt/sdcard disk inserted (179:0)
- // 605 Volume sdcard /mnt/sdcard state changed from 0 (No-Media) to 2 (Pending)
- // 605 Volume sdcard /mnt/sdcard state changed from 2 (Pending) to 1 (Idle-Unmounted)
- //
- // On media removal while the media is mounted:
- // 632 Volume sdcard /mnt/sdcard bad removal (179:1)
- // 605 Volume sdcard /mnt/sdcard state changed from 4 (Mounted) to 5 (Unmounting)
- // 605 Volume sdcard /mnt/sdcard state changed from 5 (Unmounting) to 1 (Idle-Unmounted)
- // 631 Volume sdcard /mnt/sdcard disk removed (179:0)
- // 605 Volume sdcard /mnt/sdcard state changed from 1 (Idle-Unmounted) to 0 (No-Media)
- //
- // When sharing with a PC, it goes Mounted -> Idle -> Shared
- // When unsharing with a PC, it goes Shared -> Idle -> Mounted
- //
- // The AutoMounter needs to know whether the media is present or not when
- // processing the Idle state.
-
- if (mMediaPresent == aMediaPresent) {
- return;
- }
-
- LOG("Volume: %s media %s", NameStr(), aMediaPresent ? "inserted" : "removed");
- mMediaPresent = aMediaPresent;
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetSharingEnabled(bool aSharingEnabled)
-{
- mSharingEnabled = aSharingEnabled;
-
- LOG("SetSharingMode for volume %s to %d canBeShared = %d",
- NameStr(), (int)mSharingEnabled, (int)mCanBeShared);
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetFormatRequested(bool aFormatRequested)
-{
- mFormatRequested = aFormatRequested;
-
- LOG("SetFormatRequested for volume %s to %d CanBeFormatted = %d",
- NameStr(), (int)mFormatRequested, (int)CanBeFormatted());
-}
-
-void
-Volume::SetMountRequested(bool aMountRequested)
-{
- mMountRequested = aMountRequested;
-
- LOG("SetMountRequested for volume %s to %d CanBeMounted = %d",
- NameStr(), (int)mMountRequested, (int)CanBeMounted());
-}
-
-void
-Volume::SetUnmountRequested(bool aUnmountRequested)
-{
- mUnmountRequested = aUnmountRequested;
-
- LOG("SetUnmountRequested for volume %s to %d CanBeMounted = %d",
- NameStr(), (int)mUnmountRequested, (int)CanBeMounted());
-}
-
-void
-Volume::SetState(Volume::STATE aNewState)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (aNewState == mState) {
- return;
- }
- if (aNewState == nsIVolume::STATE_MOUNTED) {
- mMountGeneration = ++sMountGeneration;
- LOG("Volume %s (%u): changing state from %s to %s @ '%s' (%d observers) "
- "mountGeneration = %d, locked = %d",
- NameStr(), mId, StateStr(mState),
- StateStr(aNewState), mMountPoint.get(), sEventObserverList.Length(),
- mMountGeneration, (int)mMountLocked);
- } else {
- LOG("Volume %s (%u): changing state from %s to %s (%d observers)",
- NameStr(), mId, StateStr(mState),
- StateStr(aNewState), sEventObserverList.Length());
- }
-
- switch (aNewState) {
- case nsIVolume::STATE_NOMEDIA:
- // Cover the startup case where we don't get insertion/removal events
- mMediaPresent = false;
- mIsSharing = false;
- mUnmountRequested = false;
- mMountRequested = false;
- mIsUnmounting = false;
- break;
-
- case nsIVolume::STATE_MOUNTED:
- case nsIVolume::STATE_MOUNT_FAIL:
- mMountRequested = false;
- mIsFormatting = false;
- mIsSharing = false;
- mIsUnmounting = false;
- break;
-
- case nsIVolume::STATE_FORMATTING:
- mFormatRequested = false;
- mIsFormatting = true;
- mIsSharing = false;
- mIsUnmounting = false;
- break;
-
- case nsIVolume::STATE_SHARED:
- case nsIVolume::STATE_SHAREDMNT:
- // Covers startup cases. Normally, mIsSharing would be set to true
- // when we issue the command to initiate the sharing process, but
- // it's conceivable that a volume could already be in a shared state
- // when b2g starts.
- mIsSharing = true;
- mIsUnmounting = false;
- mIsFormatting = false;
- break;
-
- case nsIVolume::STATE_UNMOUNTING:
- mIsUnmounting = true;
- mIsFormatting = false;
- mIsSharing = false;
- break;
-
- case nsIVolume::STATE_IDLE: // Fall through
- case nsIVolume::STATE_CHECKMNT: // Fall through
- default:
- break;
- }
- mState = aNewState;
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetMountPoint(const nsCSubstring& aMountPoint)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (mMountPoint.Equals(aMountPoint)) {
- return;
- }
- ResolveAndSetMountPoint(aMountPoint);
-}
-
-void
-Volume::StartMount(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "mount", "", aCallback));
-}
-
-void
-Volume::StartUnmount(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "unmount", "force", aCallback));
-}
-
-void
-Volume::StartFormat(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "format", "", aCallback));
-}
-
-void
-Volume::StartShare(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "share", "ums", aCallback));
-}
-
-void
-Volume::StartUnshare(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "unshare", "ums", aCallback));
-}
-
-void
-Volume::StartCommand(VolumeCommand* aCommand)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- VolumeManager::PostCommand(aCommand);
-}
-
-//static
-void
-Volume::RegisterVolumeObserver(Volume::EventObserver* aObserver, const char* aName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- sEventObserverList.AddObserver(aObserver);
-
- DBG("Added Volume Observer '%s' @%p, length = %u",
- aName, aObserver, sEventObserverList.Length());
-
- // Send an initial event to the observer (for each volume)
- size_t numVolumes = VolumeManager::NumVolumes();
- for (size_t volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- aObserver->Notify(vol);
- }
-}
-
-//static
-void
-Volume::UnregisterVolumeObserver(Volume::EventObserver* aObserver, const char* aName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- sEventObserverList.RemoveObserver(aObserver);
-
- DBG("Removed Volume Observer '%s' @%p, length = %u",
- aName, aObserver, sEventObserverList.Length());
-}
-
-//static
-void
-Volume::UpdateMountLock(const nsACString& aVolumeName,
- const int32_t& aMountGeneration,
- const bool& aMountLocked)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol || (vol->mMountGeneration != aMountGeneration)) {
- return;
- }
- if (vol->mMountLocked != aMountLocked) {
- vol->mMountLocked = aMountLocked;
- DBG("Volume::UpdateMountLock for '%s' to %d\n", vol->NameStr(), (int)aMountLocked);
- sEventObserverList.Broadcast(vol);
- }
-}
-
-void
-Volume::HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // The volume name will have already been parsed, and the tokenizer will point
- // to the token after the volume name
- switch (aResponseCode) {
- case ::ResponseCode::VolumeListResult: {
- // Each line will look something like:
- //
- // sdcard /mnt/sdcard 1
- //
- nsDependentCSubstring mntPoint(aTokenizer.nextToken());
- SetMountPoint(mntPoint);
- nsresult errCode;
- nsCString state(aTokenizer.nextToken());
- if (state.EqualsLiteral("X")) {
- // Special state for creating fake volumes which can't be shared.
- mCanBeShared = false;
- SetState(nsIVolume::STATE_MOUNTED);
- } else {
- SetState((STATE)state.ToInteger(&errCode));
- }
- break;
- }
-
- case ::ResponseCode::VolumeStateChange: {
- // Format of the line looks something like:
- //
- // Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
- //
- // So we parse out the state after the string " to "
- while (aTokenizer.hasMoreTokens()) {
- nsAutoCString token(aTokenizer.nextToken());
- if (token.EqualsLiteral("to")) {
- nsresult errCode;
- token = aTokenizer.nextToken();
- STATE newState = (STATE)(token.ToInteger(&errCode));
- if (newState == nsIVolume::STATE_MOUNTED) {
- // We set the state to STATE_CHECKMNT here, and the once the
- // AutoMounter detects that the volume is actually accessible
- // then the AutoMounter will set the volume as STATE_MOUNTED.
- SetState(nsIVolume::STATE_CHECKMNT);
- } else {
- if (State() == nsIVolume::STATE_CHECKING && newState == nsIVolume::STATE_IDLE) {
- LOG("Mount of volume '%s' failed", NameStr());
- SetState(nsIVolume::STATE_MOUNT_FAIL);
- } else {
- SetState(newState);
- }
- }
- break;
- }
- }
- break;
- }
-
- case ::ResponseCode::VolumeDiskInserted:
- SetMediaPresent(true);
- break;
-
- case ::ResponseCode::VolumeDiskRemoved: // fall-thru
- case ::ResponseCode::VolumeBadRemoval:
- SetMediaPresent(false);
- break;
-
- default:
- LOG("Volume: %s unrecognized reponse code (ignored)", NameStr());
- break;
- }
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/Volume.h b/dom/system/gonk/Volume.h
deleted file mode 100644
index 821292a9a..000000000
--- a/dom/system/gonk/Volume.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volume_h__
-#define mozilla_system_volume_h__
-
-#include "VolumeCommand.h"
-#include "nsIVolume.h"
-#include "nsString.h"
-#include "mozilla/Observer.h"
-#include "nsISupportsImpl.h"
-#include "nsWhitespaceTokenizer.h"
-
-namespace mozilla {
-namespace system {
-
-/***************************************************************************
-*
-* There is an instance of the Volume class for each volume reported
-* from vold.
-*
-* Each volume originates from the /system/etv/vold.fstab file.
-*
-***************************************************************************/
-
-class Volume;
-
-#define DEBUG_VOLUME_OBSERVER 0
-
-#if DEBUG_VOLUME_OBSERVER
-class VolumeObserverList : public mozilla::ObserverList<Volume*>
-{
-public:
- void Broadcast(Volume* const& aVolume);
-};
-#else
-typedef mozilla::ObserverList<Volume*> VolumeObserverList;
-#endif
-
-class Volume final
-{
-public:
- NS_INLINE_DECL_REFCOUNTING(Volume)
-
- Volume(const nsCSubstring& aVolumeName);
-
- typedef long STATE; // States are now defined in nsIVolume.idl
-
- static const char* StateStr(STATE aState) { return NS_VolumeStateStr(aState); }
- const char* StateStr() const { return StateStr(mState); }
- STATE State() const { return mState; }
-
- const nsCString& Name() const { return mName; }
- const char* NameStr() const { return mName.get(); }
-
- void Dump(const char* aLabel) const;
-
- // The mount point is the name of the directory where the volume is mounted.
- // (i.e. path that leads to the files stored on the volume).
- const nsCString& MountPoint() const { return mMountPoint; }
-
- uint32_t Id() const { return mId; }
-
- int32_t MountGeneration() const { return mMountGeneration; }
- bool IsMountLocked() const { return mMountLocked; }
- bool MediaPresent() const { return mMediaPresent; }
- bool CanBeShared() const { return mCanBeShared; }
- bool CanBeFormatted() const { return CanBeShared(); }
- bool CanBeMounted() const { return CanBeShared(); }
- bool IsSharingEnabled() const { return mCanBeShared && mSharingEnabled; }
- bool IsFormatRequested() const { return CanBeFormatted() && mFormatRequested; }
- bool IsMountRequested() const { return CanBeMounted() && mMountRequested; }
- bool IsUnmountRequested() const { return CanBeMounted() && mUnmountRequested; }
- bool IsSharing() const { return mIsSharing; }
- bool IsFormatting() const { return mIsFormatting; }
- bool IsUnmounting() const { return mIsUnmounting; }
- bool IsRemovable() const { return mIsRemovable; }
- bool IsHotSwappable() const { return mIsHotSwappable; }
-
- void SetFakeVolume(const nsACString& aMountPoint);
-
- void SetSharingEnabled(bool aSharingEnabled);
- void SetFormatRequested(bool aFormatRequested);
- void SetMountRequested(bool aMountRequested);
- void SetUnmountRequested(bool aUnmountRequested);
-
- typedef mozilla::Observer<Volume *> EventObserver;
-
- // NOTE: that observers must live in the IOThread.
- static void RegisterVolumeObserver(EventObserver* aObserver, const char* aName);
- static void UnregisterVolumeObserver(EventObserver* aObserver, const char* aName);
-
-protected:
- ~Volume() {}
-
-private:
- friend class AutoMounter; // Calls StartXxx
- friend class nsVolume; // Calls UpdateMountLock
- friend class VolumeManager; // Calls HandleVoldResponse
- friend class VolumeListCallback; // Calls SetMountPoint, SetState
-
- // The StartXxx functions will queue up a command to the VolumeManager.
- // You can queue up as many commands as you like, and aCallback will
- // be called as each one completes.
- void StartMount(VolumeResponseCallback* aCallback);
- void StartUnmount(VolumeResponseCallback* aCallback);
- void StartFormat(VolumeResponseCallback* aCallback);
- void StartShare(VolumeResponseCallback* aCallback);
- void StartUnshare(VolumeResponseCallback* aCallback);
-
- void SetIsSharing(bool aIsSharing);
- void SetIsFormatting(bool aIsFormatting);
- void SetIsUnmounting(bool aIsUnmounting);
- void SetIsRemovable(bool aIsRemovable);
- void SetIsHotSwappable(bool aIsHotSwappable);
- void SetState(STATE aNewState);
- void SetMediaPresent(bool aMediaPresent);
- void SetMountPoint(const nsCSubstring& aMountPoint);
- void StartCommand(VolumeCommand* aCommand);
-
- void ResolveAndSetMountPoint(const nsCSubstring& aMountPoint);
-
- bool BoolConfigValue(const nsCString& aConfigValue, bool& aBoolValue);
- void SetConfig(const nsCString& aConfigName, const nsCString& aConfigValue);
-
- void HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer);
-
- static void UpdateMountLock(const nsACString& aVolumeName,
- const int32_t& aMountGeneration,
- const bool& aMountLocked);
-
- bool mMediaPresent;
- STATE mState;
- const nsCString mName;
- nsCString mMountPoint;
- int32_t mMountGeneration;
- bool mMountLocked;
- bool mSharingEnabled;
- bool mFormatRequested;
- bool mMountRequested;
- bool mUnmountRequested;
- bool mCanBeShared;
- bool mIsSharing;
- bool mIsFormatting;
- bool mIsUnmounting;
- bool mIsRemovable;
- bool mIsHotSwappable;
- uint32_t mId; // Unique ID (used by MTP)
-
- static VolumeObserverList sEventObserverList;
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumemanager_h__
diff --git a/dom/system/gonk/VolumeCommand.cpp b/dom/system/gonk/VolumeCommand.cpp
deleted file mode 100644
index 8095956a7..000000000
--- a/dom/system/gonk/VolumeCommand.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsString.h"
-#include "nsWhitespaceTokenizer.h"
-
-#include "Volume.h"
-#include "VolumeCommand.h"
-#include "VolumeManager.h"
-#include "VolumeManagerLog.h"
-
-namespace mozilla {
-namespace system {
-
-/***************************************************************************
-*
-* The VolumeActionCommand class is used to send commands which apply
-* to a particular volume.
-*
-* The following commands would fit into this category:
-*
-* volume mount <volname>
-* volume unmount <volname> [force]
-* volume format <volname>
-* volume share <volname> <method>
-* volume unshare <volname> <method>
-* volume shared <volname> <method>
-*
-* A typical response looks like:
-*
-* # vdc volume unshare sdcard ums
-* 605 Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
-* 200 volume operation succeeded
-*
-* Note that the 600 series of responses are considered unsolicited and
-* are dealt with directly by the VolumeManager. This command will only
-* see the terminating response code (200 in the example above).
-*
-***************************************************************************/
-
-VolumeActionCommand::VolumeActionCommand(Volume* aVolume,
- const char* aAction,
- const char* aExtraArgs,
- VolumeResponseCallback* aCallback)
- : VolumeCommand(aCallback),
- mVolume(aVolume)
-{
- nsAutoCString cmd;
-
- cmd = "volume ";
- cmd += aAction;
- cmd += " ";
- cmd += aVolume->Name().get();
-
- // vold doesn't like trailing white space, so only add it if we really need to.
- if (aExtraArgs && (*aExtraArgs != '\0')) {
- cmd += " ";
- cmd += aExtraArgs;
- }
- SetCmd(cmd);
-}
-
-/***************************************************************************
-*
-* The VolumeListCommand class is used to send the "volume list" command to
-* vold.
-*
-* A typical response looks like:
-*
-* # vdc volume list
-* 110 sdcard /mnt/sdcard 4
-* 110 sdcard1 /mnt/sdcard/external_sd 4
-* 200 Volumes listed.
-*
-***************************************************************************/
-
-VolumeListCommand::VolumeListCommand(VolumeResponseCallback* aCallback)
- : VolumeCommand(NS_LITERAL_CSTRING("volume list"), aCallback)
-{
-}
-
-} // system
-} // mozilla
-
diff --git a/dom/system/gonk/VolumeCommand.h b/dom/system/gonk/VolumeCommand.h
deleted file mode 100644
index 022965b5e..000000000
--- a/dom/system/gonk/VolumeCommand.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumecommand_h__
-#define mozilla_system_volumecommand_h__
-
-#include "nsString.h"
-#include "nsISupportsImpl.h"
-#include "mozilla/RefPtr.h"
-#include <algorithm>
-#include <vold/ResponseCode.h>
-
-namespace mozilla {
-namespace system {
-
-class Volume;
-class VolumeCommand;
-
-/***************************************************************************
-*
-* The VolumeResponseCallback class is an abstract base class. The ResponseReceived
-* method will be called for each response received.
-*
-* Depending on the command, there may be multiple responses for the
-* command. Done() will return true if this is the last response.
-*
-* The responses from vold are all of the form:
-*
-* <ResponseCode> <String>
-*
-* Valid Response codes can be found in the vold/ResponseCode.h header.
-*
-***************************************************************************/
-
-class VolumeResponseCallback
-{
-protected:
- virtual ~VolumeResponseCallback() {}
-
-public:
- NS_INLINE_DECL_REFCOUNTING(VolumeResponseCallback)
- VolumeResponseCallback()
- : mResponseCode(0), mPending(false) {}
-
- bool Done() const
- {
- // Response codes from the 200, 400, and 500 series all indicated that
- // the command has completed.
-
- return (mResponseCode >= ::ResponseCode::CommandOkay)
- && (mResponseCode < ::ResponseCode::UnsolicitedInformational);
- }
-
- bool WasSuccessful() const
- {
- return mResponseCode == ::ResponseCode::CommandOkay;
- }
-
- bool IsPending() const { return mPending; }
- int ResponseCode() const { return mResponseCode; }
- const nsCString &ResponseStr() const { return mResponseStr; }
-
-protected:
- virtual void ResponseReceived(const VolumeCommand* aCommand) = 0;
-
-private:
- friend class VolumeCommand; // Calls HandleResponse and SetPending
-
- void HandleResponse(const VolumeCommand* aCommand,
- int aResponseCode,
- nsACString& aResponseStr)
- {
- mResponseCode = aResponseCode;
-#if ANDROID_VERSION >= 17
- // There's a sequence number here that we don't care about
- // We expect it to be 0. See VolumeCommand::SetCmd
- mResponseStr = Substring(aResponseStr, 2);
-#else
- mResponseStr = aResponseStr;
-#endif
- if (mResponseCode >= ::ResponseCode::CommandOkay) {
- // This is a final response.
- mPending = false;
- }
- ResponseReceived(aCommand);
- }
-
- void SetPending(bool aPending) { mPending = aPending; }
-
- int mResponseCode; // The response code parsed from vold
- nsCString mResponseStr; // The rest of the line.
- bool mPending; // Waiting for response?
-};
-
-/***************************************************************************
-*
-* The VolumeCommand class is an abstract base class used to encapsulate
-* volume commands send to vold.
-*
-* See VolumeManager.h for a list of the volume commands.
-*
-* Commands sent to vold need an explicit null character so we add one
-* to the command to ensure that it's included in the length.
-*
-* All of these commands are asynchronous in nature, and the
-* ResponseReceived callback will be called when a response is available.
-*
-***************************************************************************/
-
-class VolumeCommand
-{
-protected:
- virtual ~VolumeCommand() {}
-
-public:
- NS_INLINE_DECL_REFCOUNTING(VolumeCommand)
-
- VolumeCommand(VolumeResponseCallback* aCallback)
- : mBytesConsumed(0),
- mCallback(aCallback)
- {
- SetCmd(NS_LITERAL_CSTRING(""));
- }
-
- VolumeCommand(const nsACString& aCommand, VolumeResponseCallback* aCallback)
- : mBytesConsumed(0),
- mCallback(aCallback)
- {
- SetCmd(aCommand);
- }
-
- void SetCmd(const nsACString& aCommand)
- {
- mCmd.Truncate();
-#if ANDROID_VERSION >= 17
- // JB requires a sequence number at the beginning of messages.
- // It doesn't matter what we use, so we use 0.
- mCmd = "0 ";
-#endif
- mCmd.Append(aCommand);
- // Add a null character. We want this to be included in the length since
- // vold uses it to determine the end of the command.
- mCmd.Append('\0');
- }
-
- const char* CmdStr() const { return mCmd.get(); }
- const char* Data() const { return mCmd.Data() + mBytesConsumed; }
- size_t BytesConsumed() const { return mBytesConsumed; }
-
- size_t BytesRemaining() const
- {
- return mCmd.Length() - std::min(mCmd.Length(), mBytesConsumed);
- }
-
- void ConsumeBytes(size_t aNumBytes)
- {
- mBytesConsumed += std::min(BytesRemaining(), aNumBytes);
- }
-
-private:
- friend class VolumeManager; // Calls SetPending & HandleResponse
-
- void SetPending(bool aPending)
- {
- if (mCallback) {
- mCallback->SetPending(aPending);
- }
- }
-
- void HandleResponse(int aResponseCode, nsACString& aResponseStr)
- {
- if (mCallback) {
- mCallback->HandleResponse(this, aResponseCode, aResponseStr);
- }
- }
-
- nsCString mCmd; // Command being sent
- size_t mBytesConsumed; // How many bytes have been sent
-
- // Called when a response to the command is received.
- RefPtr<VolumeResponseCallback> mCallback;
-};
-
-class VolumeActionCommand : public VolumeCommand
-{
-public:
- VolumeActionCommand(Volume* aVolume, const char* aAction,
- const char* aExtraArgs, VolumeResponseCallback* aCallback);
-
-private:
- RefPtr<Volume> mVolume;
-};
-
-class VolumeListCommand : public VolumeCommand
-{
-public:
- VolumeListCommand(VolumeResponseCallback* aCallback);
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumecommand_h__
diff --git a/dom/system/gonk/VolumeManager.cpp b/dom/system/gonk/VolumeManager.cpp
deleted file mode 100644
index ddfa7af09..000000000
--- a/dom/system/gonk/VolumeManager.cpp
+++ /dev/null
@@ -1,591 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "VolumeManager.h"
-
-#include "Volume.h"
-#include "VolumeCommand.h"
-#include "VolumeManagerLog.h"
-#include "VolumeServiceTest.h"
-
-#include "nsWhitespaceTokenizer.h"
-#include "nsXULAppAPI.h"
-
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "mozilla/Scoped.h"
-#include "mozilla/StaticPtr.h"
-
-#include <android/log.h>
-#include <cutils/sockets.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-
-namespace mozilla {
-namespace system {
-
-static StaticRefPtr<VolumeManager> sVolumeManager;
-
-VolumeManager::STATE VolumeManager::mState = VolumeManager::UNINITIALIZED;
-VolumeManager::StateObserverList VolumeManager::mStateObserverList;
-
-/***************************************************************************/
-
-VolumeManager::VolumeManager()
- : LineWatcher('\0', kRcvBufSize),
- mSocket(-1),
- mCommandPending(false)
-{
- DBG("VolumeManager constructor called");
-}
-
-VolumeManager::~VolumeManager()
-{
-}
-
-//static
-void
-VolumeManager::Dump(const char* aLabel)
-{
- if (!sVolumeManager) {
- LOG("%s: sVolumeManager == null", aLabel);
- return;
- }
-
- VolumeArray::size_type numVolumes = NumVolumes();
- VolumeArray::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = GetVolume(volIndex);
- vol->Dump(aLabel);
- }
-}
-
-//static
-size_t
-VolumeManager::NumVolumes()
-{
- if (!sVolumeManager) {
- return 0;
- }
- return sVolumeManager->mVolumeArray.Length();
-}
-
-//static
-already_AddRefed<Volume>
-VolumeManager::GetVolume(size_t aIndex)
-{
- MOZ_ASSERT(aIndex < NumVolumes());
- RefPtr<Volume> vol = sVolumeManager->mVolumeArray[aIndex];
- return vol.forget();
-}
-
-//static
-VolumeManager::STATE
-VolumeManager::State()
-{
- return mState;
-}
-
-//static
-const char *
-VolumeManager::StateStr(VolumeManager::STATE aState)
-{
- switch (aState) {
- case UNINITIALIZED: return "Uninitialized";
- case STARTING: return "Starting";
- case VOLUMES_READY: return "Volumes Ready";
- }
- return "???";
-}
-
-
-//static
-void
-VolumeManager::SetState(STATE aNewState)
-{
- if (mState != aNewState) {
- LOG("changing state from '%s' to '%s'",
- StateStr(mState), StateStr(aNewState));
- mState = aNewState;
- mStateObserverList.Broadcast(StateChangedEvent());
- }
-}
-
-//static
-void
-VolumeManager::RegisterStateObserver(StateObserver* aObserver)
-{
- mStateObserverList.AddObserver(aObserver);
-}
-
-//static
-void VolumeManager::UnregisterStateObserver(StateObserver* aObserver)
-{
- mStateObserverList.RemoveObserver(aObserver);
-}
-
-//static
-already_AddRefed<Volume>
-VolumeManager::FindVolumeByName(const nsCSubstring& aName)
-{
- if (!sVolumeManager) {
- return nullptr;
- }
- VolumeArray::size_type numVolumes = NumVolumes();
- VolumeArray::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = GetVolume(volIndex);
- if (vol->Name().Equals(aName)) {
- return vol.forget();
- }
- }
- return nullptr;
-}
-
-//static
-already_AddRefed<Volume>
-VolumeManager::FindAddVolumeByName(const nsCSubstring& aName)
-{
- RefPtr<Volume> vol = FindVolumeByName(aName);
- if (vol) {
- return vol.forget();
- }
- // No volume found, create and add a new one.
- vol = new Volume(aName);
- sVolumeManager->mVolumeArray.AppendElement(vol);
- return vol.forget();
-}
-
-//static
-bool
-VolumeManager::RemoveVolumeByName(const nsCSubstring& aName)
-{
- if (!sVolumeManager) {
- return false;
- }
- VolumeArray::size_type numVolumes = NumVolumes();
- VolumeArray::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = GetVolume(volIndex);
- if (vol->Name().Equals(aName)) {
- sVolumeManager->mVolumeArray.RemoveElementAt(volIndex);
- return true;
- }
- }
- // No volume found. Return false to indicate this.
- return false;
-}
-
-
-//static
-void VolumeManager::InitConfig()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // This function uses /system/etc/volume.cfg to add additional volumes
- // to the Volume Manager.
- //
- // This is useful on devices like the Nexus 4, which have no physical sd card
- // or dedicated partition.
- //
- // The format of the volume.cfg file is as follows:
- // create volume-name mount-point
- // configure volume-name preference preference-value
- // Blank lines and lines starting with the hash character "#" will be ignored.
-
- ScopedCloseFile fp;
- int n = 0;
- char line[255];
- const char *filename = "/system/etc/volume.cfg";
- if (!(fp = fopen(filename, "r"))) {
- LOG("Unable to open volume configuration file '%s' - ignoring", filename);
- return;
- }
- while(fgets(line, sizeof(line), fp)) {
- n++;
-
- if (line[0] == '#')
- continue;
-
- nsCString commandline(line);
- nsCWhitespaceTokenizer tokenizer(commandline);
- if (!tokenizer.hasMoreTokens()) {
- // Blank line - ignore
- continue;
- }
-
- nsCString command(tokenizer.nextToken());
- if (command.EqualsLiteral("create")) {
- if (!tokenizer.hasMoreTokens()) {
- ERR("No vol_name in %s line %d", filename, n);
- continue;
- }
- nsCString volName(tokenizer.nextToken());
- if (!tokenizer.hasMoreTokens()) {
- ERR("No mount point for volume '%s'. %s line %d",
- volName.get(), filename, n);
- continue;
- }
- nsCString mountPoint(tokenizer.nextToken());
- RefPtr<Volume> vol = FindAddVolumeByName(volName);
- vol->SetFakeVolume(mountPoint);
- continue;
- }
- if (command.EqualsLiteral("configure")) {
- if (!tokenizer.hasMoreTokens()) {
- ERR("No vol_name in %s line %d", filename, n);
- continue;
- }
- nsCString volName(tokenizer.nextToken());
- if (!tokenizer.hasMoreTokens()) {
- ERR("No configuration name specified for volume '%s'. %s line %d",
- volName.get(), filename, n);
- continue;
- }
- nsCString configName(tokenizer.nextToken());
- if (!tokenizer.hasMoreTokens()) {
- ERR("No value for configuration name '%s'. %s line %d",
- configName.get(), filename, n);
- continue;
- }
- nsCString configValue(tokenizer.nextToken());
- RefPtr<Volume> vol = FindVolumeByName(volName);
- if (vol) {
- vol->SetConfig(configName, configValue);
- } else {
- ERR("Invalid volume name '%s'.", volName.get());
- }
- continue;
- }
- if (command.EqualsLiteral("ignore")) {
- // This command is useful to remove volumes which are being tracked by
- // vold, but for which we have no interest.
- if (!tokenizer.hasMoreTokens()) {
- ERR("No vol_name in %s line %d", filename, n);
- continue;
- }
- nsCString volName(tokenizer.nextToken());
- RemoveVolumeByName(volName);
- continue;
- }
- ERR("Unrecognized command: '%s'", command.get());
- }
-}
-
-void
-VolumeManager::DefaultConfig()
-{
-
- VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- if (numVolumes == 0) {
- return;
- }
- if (numVolumes == 1) {
- // This is to cover early shipping phones like the Buri,
- // which had no internal storage, and only external sdcard.
- //
- // Phones line the nexus-4 which only have an internal
- // storage area will need to have a volume.cfg file with
- // removable set to false.
- RefPtr<Volume> vol = VolumeManager::GetVolume(0);
- vol->SetIsRemovable(true);
- vol->SetIsHotSwappable(true);
- return;
- }
- VolumeManager::VolumeArray::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- if (!vol->Name().EqualsLiteral("sdcard")) {
- vol->SetIsRemovable(true);
- vol->SetIsHotSwappable(true);
- }
- }
-}
-
-class VolumeListCallback : public VolumeResponseCallback
-{
- virtual void ResponseReceived(const VolumeCommand* aCommand)
- {
- switch (ResponseCode()) {
- case ::ResponseCode::VolumeListResult: {
- // Each line will look something like:
- //
- // sdcard /mnt/sdcard 1
- //
- // So for each volume that we get back, we update any volumes that
- // we have of the same name, or add new ones if they don't exist.
- nsCWhitespaceTokenizer tokenizer(ResponseStr());
- nsDependentCSubstring volName(tokenizer.nextToken());
- RefPtr<Volume> vol = VolumeManager::FindAddVolumeByName(volName);
- vol->HandleVoldResponse(ResponseCode(), tokenizer);
- break;
- }
-
- case ::ResponseCode::CommandOkay: {
- // We've received the list of volumes. Now read the Volume.cfg
- // file to perform customizations, and then tell everybody
- // that we're ready for business.
- VolumeManager::DefaultConfig();
- VolumeManager::InitConfig();
- VolumeManager::Dump("READY");
- VolumeManager::SetState(VolumeManager::VOLUMES_READY);
- break;
- }
- }
- }
-};
-
-bool
-VolumeManager::OpenSocket()
-{
- SetState(STARTING);
- if ((mSocket.rwget() = socket_local_client("vold",
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM)) < 0) {
- ERR("Error connecting to vold: (%s) - will retry", strerror(errno));
- return false;
- }
- // add FD_CLOEXEC flag
- int flags = fcntl(mSocket.get(), F_GETFD);
- if (flags == -1) {
- return false;
- }
- flags |= FD_CLOEXEC;
- if (fcntl(mSocket.get(), F_SETFD, flags) == -1) {
- return false;
- }
- // set non-blocking
- if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) {
- return false;
- }
- if (!MessageLoopForIO::current()->
- WatchFileDescriptor(mSocket.get(),
- true,
- MessageLoopForIO::WATCH_READ,
- &mReadWatcher,
- this)) {
- return false;
- }
-
- LOG("Connected to vold");
- PostCommand(new VolumeListCommand(new VolumeListCallback));
- return true;
-}
-
-//static
-void
-VolumeManager::PostCommand(VolumeCommand* aCommand)
-{
- if (!sVolumeManager) {
- ERR("VolumeManager not initialized. Dropping command '%s'", aCommand->Data());
- return;
- }
- aCommand->SetPending(true);
-
- DBG("Sending command '%s'", aCommand->Data());
- // vold can only process one command at a time, so add our command
- // to the end of the command queue.
- sVolumeManager->mCommands.push(aCommand);
- if (!sVolumeManager->mCommandPending) {
- // There aren't any commands currently being processed, so go
- // ahead and kick this one off.
- sVolumeManager->mCommandPending = true;
- sVolumeManager->WriteCommandData();
- }
-}
-
-/***************************************************************************
-* The WriteCommandData initiates sending of a command to vold. Since
-* we're running on the IOThread and not allowed to block, WriteCommandData
-* will write as much data as it can, and if not all of the data can be
-* written then it will setup a file descriptor watcher and
-* OnFileCanWriteWithoutBlocking will call WriteCommandData to write out
-* more of the command data.
-*/
-void
-VolumeManager::WriteCommandData()
-{
- if (mCommands.size() == 0) {
- return;
- }
-
- VolumeCommand* cmd = mCommands.front();
- if (cmd->BytesRemaining() == 0) {
- // All bytes have been written. We're waiting for a response.
- return;
- }
- // There are more bytes left to write. Try to write them all.
- ssize_t bytesWritten = write(mSocket.get(), cmd->Data(), cmd->BytesRemaining());
- if (bytesWritten < 0) {
- ERR("Failed to write %d bytes to vold socket", cmd->BytesRemaining());
- Restart();
- return;
- }
- DBG("Wrote %d bytes (of %d)", bytesWritten, cmd->BytesRemaining());
- cmd->ConsumeBytes(bytesWritten);
- if (cmd->BytesRemaining() == 0) {
- return;
- }
- // We were unable to write all of the command bytes. Setup a watcher
- // so we'll get called again when we can write without blocking.
- if (!MessageLoopForIO::current()->
- WatchFileDescriptor(mSocket.get(),
- false, // one-shot
- MessageLoopForIO::WATCH_WRITE,
- &mWriteWatcher,
- this)) {
- ERR("Failed to setup write watcher for vold socket");
- Restart();
- }
-}
-
-void
-VolumeManager::OnLineRead(int aFd, nsDependentCSubstring& aMessage)
-{
- MOZ_ASSERT(aFd == mSocket.get());
- char* endPtr;
- int responseCode = strtol(aMessage.Data(), &endPtr, 10);
- if (*endPtr == ' ') {
- endPtr++;
- }
-
- // Now fish out the rest of the line after the response code
- nsDependentCString responseLine(endPtr, aMessage.Length() - (endPtr - aMessage.Data()));
- DBG("Rcvd: %d '%s'", responseCode, responseLine.Data());
-
- if (responseCode >= ::ResponseCode::UnsolicitedInformational) {
- // These are unsolicited broadcasts. We intercept these and process
- // them ourselves
- HandleBroadcast(responseCode, responseLine);
- } else {
- // Everything else is considered to be part of the command response.
- if (mCommands.size() > 0) {
- VolumeCommand* cmd = mCommands.front();
- cmd->HandleResponse(responseCode, responseLine);
- if (responseCode >= ::ResponseCode::CommandOkay) {
- // That's a terminating response. We can remove the command.
- mCommands.pop();
- mCommandPending = false;
- // Start the next command, if there is one.
- WriteCommandData();
- }
- } else {
- ERR("Response with no command");
- }
- }
-}
-
-void
-VolumeManager::OnFileCanWriteWithoutBlocking(int aFd)
-{
- MOZ_ASSERT(aFd == mSocket.get());
- WriteCommandData();
-}
-
-void
-VolumeManager::HandleBroadcast(int aResponseCode, nsCString& aResponseLine)
-{
- // Format of the line is something like:
- //
- // Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
- //
- // So we parse out the volume name and the state after the string " to "
- nsCWhitespaceTokenizer tokenizer(aResponseLine);
- tokenizer.nextToken(); // The word "Volume"
- nsDependentCSubstring volName(tokenizer.nextToken());
-
- RefPtr<Volume> vol = FindVolumeByName(volName);
- if (!vol) {
- return;
- }
- vol->HandleVoldResponse(aResponseCode, tokenizer);
-}
-
-void
-VolumeManager::Restart()
-{
- mReadWatcher.StopWatchingFileDescriptor();
- mWriteWatcher.StopWatchingFileDescriptor();
-
- while (!mCommands.empty()) {
- mCommands.pop();
- }
- mCommandPending = false;
- mSocket.dispose();
- Start();
-}
-
-//static
-void
-VolumeManager::Start()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (!sVolumeManager) {
- return;
- }
- SetState(STARTING);
- if (!sVolumeManager->OpenSocket()) {
- // Socket open failed, try again in a second.
- MessageLoopForIO::current()->
- PostDelayedTask(NewRunnableFunction(VolumeManager::Start),
- 1000);
- }
-}
-
-void
-VolumeManager::OnError()
-{
- Restart();
-}
-
-/***************************************************************************/
-
-static void
-InitVolumeManagerIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(!sVolumeManager);
-
- sVolumeManager = new VolumeManager();
- VolumeManager::Start();
-
- InitVolumeServiceTestIOThread();
-}
-
-static void
-ShutdownVolumeManagerIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- sVolumeManager = nullptr;
-}
-
-/**************************************************************************
-*
-* Public API
-*
-* Since the VolumeManager runs in IO Thread context, we need to switch
-* to IOThread context before we can do anything.
-*
-**************************************************************************/
-
-void
-InitVolumeManager()
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(InitVolumeManagerIOThread));
-}
-
-void
-ShutdownVolumeManager()
-{
- ShutdownVolumeServiceTest();
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(ShutdownVolumeManagerIOThread));
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/VolumeManager.h b/dom/system/gonk/VolumeManager.h
deleted file mode 100644
index 7c0503389..000000000
--- a/dom/system/gonk/VolumeManager.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumemanager_h__
-#define mozilla_system_volumemanager_h__
-
-#include <vector>
-#include <queue>
-
-#include "base/message_loop.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/Observer.h"
-#include "nsISupportsImpl.h"
-#include "nsString.h"
-#include "nsTArray.h"
-
-#include "Volume.h"
-#include "VolumeCommand.h"
-
-namespace mozilla {
-namespace system {
-
-/***************************************************************************
-*
-* All of the public API mentioned in this file (unless otherwise
-* mentioned) must run from the IOThread.
-*
-***************************************************************************/
-
-/***************************************************************************
-*
-* The VolumeManager class is a front-end for android's vold service.
-*
-* Vold uses a unix socket interface and accepts null-terminated string
-* commands. The following commands were determined by examining the vold
-* source code:
-*
-* volume list
-* volume mount <volname>
-* volume unmount <volname> [force]
-* volume debug [on|off]
-* volume format <volname>
-* volume share <volname> <method>
-* volume unshare <volname> <method>
-* volume shared <volname> <method>
-*
-* <volname> is the name of the volume as used in /system/etc/vold.fstab
-* <method> is ums
-*
-* dump
-*
-* share status <method> (Determines if a particular sharing method is available)
-* (GB only - not available in ICS)
-*
-* storage users (??? always crashes vold ???)
-*
-* asec list
-* asec ...lots more...
-*
-* obb list
-* obb ...lots more...
-*
-* xwarp enable
-* xwarp disable
-* xwarp status
-*
-* There is also a command line tool called vdc, which can be used to send
-* the above commands to vold.
-*
-* Currently, only the volume list, share/unshare, and mount/unmount
-* commands are being used.
-*
-***************************************************************************/
-
-class VolumeManager final : public MessageLoopForIO::LineWatcher
-{
- virtual ~VolumeManager();
-
-public:
- NS_INLINE_DECL_REFCOUNTING(VolumeManager)
-
- typedef nsTArray<RefPtr<Volume>> VolumeArray;
-
- VolumeManager();
-
- //-----------------------------------------------------------------------
- //
- // State related methods.
- //
- // The VolumeManager starts off in the STARTING state. Once a connection
- // is established with vold, it asks for a list of volumes, and once the
- // volume list has been received, then the VolumeManager enters the
- // VOLUMES_READY state.
- //
- // If vold crashes, then the VolumeManager will once again enter the
- // STARTING state and try to reestablish a connection with vold.
-
- enum STATE
- {
- UNINITIALIZED,
- STARTING,
- VOLUMES_READY
- };
-
- static STATE State();
- static const char* StateStr(STATE aState);
- static const char* StateStr() { return StateStr(State()); }
-
- class StateChangedEvent
- {
- public:
- StateChangedEvent() {}
- };
-
- typedef mozilla::Observer<StateChangedEvent> StateObserver;
- typedef mozilla::ObserverList<StateChangedEvent> StateObserverList;
-
- static void RegisterStateObserver(StateObserver* aObserver);
- static void UnregisterStateObserver(StateObserver* aObserver);
-
- //-----------------------------------------------------------------------
-
- static void Start();
- static void Dump(const char* aLabel);
-
- static VolumeArray::size_type NumVolumes();
- static already_AddRefed<Volume> GetVolume(VolumeArray::index_type aIndex);
- static already_AddRefed<Volume> FindVolumeByName(const nsCSubstring& aName);
- static already_AddRefed<Volume> FindAddVolumeByName(const nsCSubstring& aName);
- static bool RemoveVolumeByName(const nsCSubstring& aName);
- static void InitConfig();
-
- static void PostCommand(VolumeCommand* aCommand);
-
-protected:
-
- virtual void OnLineRead(int aFd, nsDependentCSubstring& aMessage);
- virtual void OnFileCanWriteWithoutBlocking(int aFd);
- virtual void OnError();
-
- static void DefaultConfig();
-
-private:
- bool OpenSocket();
-
- friend class VolumeListCallback; // Calls SetState
-
- static void SetState(STATE aNewState);
-
- void Restart();
- void WriteCommandData();
- void HandleBroadcast(int aResponseCode, nsCString& aResponseLine);
-
- typedef std::queue<RefPtr<VolumeCommand> > CommandQueue;
-
- static STATE mState;
- static StateObserverList mStateObserverList;
-
- static const int kRcvBufSize = 1024;
- ScopedClose mSocket;
- VolumeArray mVolumeArray;
- CommandQueue mCommands;
- bool mCommandPending;
- MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
- MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
- RefPtr<VolumeResponseCallback> mBroadcastCallback;
-};
-
-/***************************************************************************
-*
-* The initialization/shutdown functions do not need to be called from
-* the IOThread context.
-*
-***************************************************************************/
-
-/**
- * Initialize the Volume Manager. On initialization, the VolumeManager will
- * attempt to connect with vold and collect the list of volumes that vold
- * knows about.
- */
-void InitVolumeManager();
-
-/**
- * Shuts down the Volume Manager.
- */
-void ShutdownVolumeManager();
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumemanager_h__
diff --git a/dom/system/gonk/VolumeManagerLog.h b/dom/system/gonk/VolumeManagerLog.h
deleted file mode 100644
index 793f4889c..000000000
--- a/dom/system/gonk/VolumeManagerLog.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumemanagerlog_h__
-#define mozilla_system_volumemanagerlog_h__
-
-#undef USE_DEBUG
-#define USE_DEBUG 0
-
-#if !defined(VOLUME_MANAGER_LOG_TAG)
-#define VOLUME_MANAGER_LOG_TAG "VolumeManager"
-#endif
-
-#undef LOG
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, VOLUME_MANAGER_LOG_TAG, ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, VOLUME_MANAGER_LOG_TAG, ## args)
-
-#undef DBG
-#if USE_DEBUG
-#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, VOLUME_MANAGER_LOG_TAG, ## args)
-#else
-#define DBG(args...)
-#endif
-
-#endif // mozilla_system_volumemanagerlog_h__
diff --git a/dom/system/gonk/VolumeServiceIOThread.cpp b/dom/system/gonk/VolumeServiceIOThread.cpp
deleted file mode 100644
index 7eda843c0..000000000
--- a/dom/system/gonk/VolumeServiceIOThread.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "VolumeServiceIOThread.h"
-#include "base/message_loop.h"
-#include "nsVolumeService.h"
-#include "nsXULAppAPI.h"
-#include "Volume.h"
-#include "VolumeManager.h"
-
-namespace mozilla {
-namespace system {
-
-VolumeServiceIOThread::VolumeServiceIOThread(nsVolumeService* aVolumeService)
- : mVolumeService(aVolumeService)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- VolumeManager::RegisterStateObserver(this);
- Volume::RegisterVolumeObserver(this, "VolumeServiceIOThread");
- UpdateAllVolumes();
-}
-
-VolumeServiceIOThread::~VolumeServiceIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- Volume::UnregisterVolumeObserver(this, "VolumeServiceIOThread");
- VolumeManager::UnregisterStateObserver(this);
-}
-
-void
-VolumeServiceIOThread::Notify(Volume* const & aVolume)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
- mVolumeService->UpdateVolumeIOThread(aVolume);
-}
-
-void
-VolumeServiceIOThread::Notify(const VolumeManager::StateChangedEvent& aEvent)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- UpdateAllVolumes();
-}
-
-void
-VolumeServiceIOThread::UpdateAllVolumes()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
- VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- VolumeManager::VolumeArray::index_type volIndex;
-
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- mVolumeService->UpdateVolumeIOThread(vol);
- }
-}
-
-static StaticRefPtr<VolumeServiceIOThread> sVolumeServiceIOThread;
-
-void
-InitVolumeServiceIOThread(nsVolumeService* const & aVolumeService)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- sVolumeServiceIOThread = new VolumeServiceIOThread(aVolumeService);
-}
-
-void
-ShutdownVolumeServiceIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- sVolumeServiceIOThread = nullptr;
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/VolumeServiceIOThread.h b/dom/system/gonk/VolumeServiceIOThread.h
deleted file mode 100644
index 0c2a6a62f..000000000
--- a/dom/system/gonk/VolumeServiceIOThread.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumeserviceiothread_h__
-#define mozilla_system_volumeserviceiothread_h__
-
-#include "Volume.h"
-#include "VolumeManager.h"
-#include "mozilla/RefPtr.h"
-
-namespace mozilla {
-namespace system {
-
-class nsVolumeService;
-
-/***************************************************************************
-* The nsVolumeServiceIOThread is a companion class to the nsVolumeService
-* class, but whose methods are called from IOThread.
-*/
-class VolumeServiceIOThread : public VolumeManager::StateObserver,
- public Volume::EventObserver
-{
- ~VolumeServiceIOThread();
-
-public:
- NS_INLINE_DECL_REFCOUNTING(VolumeServiceIOThread)
-
- VolumeServiceIOThread(nsVolumeService* aVolumeService);
-
-private:
- void UpdateAllVolumes();
-
- virtual void Notify(const VolumeManager::StateChangedEvent& aEvent);
- virtual void Notify(Volume* const & aVolume);
-
- RefPtr<nsVolumeService> mVolumeService;
-};
-
-void InitVolumeServiceIOThread(nsVolumeService* const & aVolumeService);
-void ShutdownVolumeServiceIOThread();
-void FormatVolume(const nsCString& aVolume);
-void MountVolume(const nsCString& aVolume);
-void UnmountVolume(const nsCString& aVolume);
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumeserviceiothread_h__
diff --git a/dom/system/gonk/VolumeServiceTest.cpp b/dom/system/gonk/VolumeServiceTest.cpp
deleted file mode 100644
index 4082e3889..000000000
--- a/dom/system/gonk/VolumeServiceTest.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "VolumeServiceTest.h"
-
-#include "base/message_loop.h"
-#include "nsCOMPtr.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "nsIVolume.h"
-#include "nsIVolumeService.h"
-#include "nsIVolumeStat.h"
-#include "nsXULAppAPI.h"
-
-#include "mozilla/Services.h"
-
-#undef VOLUME_MANAGER_LOG_TAG
-#define VOLUME_MANAGER_LOG_TAG "VolumeServiceTest"
-#include "VolumeManagerLog.h"
-
-using namespace mozilla::services;
-
-namespace mozilla {
-namespace system {
-
-#define TEST_NSVOLUME_OBSERVER 0
-
-#if TEST_NSVOLUME_OBSERVER
-
-/***************************************************************************
-* A test class to verify that the Observer stuff is working properly.
-*/
-class VolumeTestObserver : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- VolumeTestObserver()
- {
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- if (!obs) {
- return;
- }
- obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false);
- }
- ~VolumeTestObserver()
- {
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- if (!obs) {
- return;
- }
- obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
- }
-
- void LogVolume(nsIVolume* vol)
- {
- nsString volName;
- nsString mountPoint;
- int32_t volState;
-
- vol->GetName(volName);
- vol->GetMountPoint(mountPoint);
- vol->GetState(&volState);
-
- LOG(" Volume: %s MountPoint: %s State: %s",
- NS_LossyConvertUTF16toASCII(volName).get(),
- NS_LossyConvertUTF16toASCII(mountPoint).get(),
- NS_VolumeStateStr(volState));
-
- nsCOMPtr<nsIVolumeStat> stat;
- nsresult rv = vol->GetStats(getter_AddRefs(stat));
- if (NS_SUCCEEDED(rv)) {
- int64_t totalBytes;
- int64_t freeBytes;
-
- stat->GetTotalBytes(&totalBytes);
- stat->GetFreeBytes(&freeBytes);
-
- LOG(" Total Space: %llu Mb Free Bytes: %llu Mb",
- totalBytes / (1024LL * 1024LL), freeBytes / (1024LL * 1024LL));
- }
- else {
- LOG(" Unable to retrieve stats");
- }
- }
-};
-static nsCOMPtr<VolumeTestObserver> sTestObserver;
-
-NS_IMPL_ISUPPORTS(VolumeTestObserver, nsIObserver)
-
-NS_IMETHODIMP
-VolumeTestObserver::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- LOG("TestObserver: topic: %s", aTopic);
-
- if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
- return NS_OK;
- }
- nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
- if (vol) {
- LogVolume(vol);
- }
-
- // Since this observe method was called then we know that the service
- // has been initialized so we can do the VolumeService tests.
-
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
- if (!vs) {
- ERR("do_GetService('%s') failed", NS_VOLUMESERVICE_CONTRACTID);
- return NS_ERROR_FAILURE;
- }
-
- nsresult rv = vs->GetVolumeByName(NS_LITERAL_STRING("sdcard"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- LOG("GetVolumeByName( 'sdcard' ) succeeded (expected)");
- LogVolume(vol);
- } else {
- ERR("GetVolumeByName( 'sdcard' ) failed (unexpected)");
- }
-
- rv = vs->GetVolumeByName(NS_LITERAL_STRING("foo"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- ERR("GetVolumeByName( 'foo' ) succeeded (unexpected)");
- } else {
- LOG("GetVolumeByName( 'foo' ) failed (expected)");
- }
-
- rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcard"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- LOG("GetVolumeByPath( '/mnt/sdcard' ) succeeded (expected)");
- LogVolume(vol);
- } else {
- ERR("GetVolumeByPath( '/mnt/sdcard' ) failed (unexpected");
- }
-
- rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcard/foo"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- LOG("GetVolumeByPath( '/mnt/sdcard/foo' ) succeeded (expected)");
- LogVolume(vol);
- } else {
- LOG("GetVolumeByPath( '/mnt/sdcard/foo' ) failed (unexpected)");
- }
-
- rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcardfoo"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- ERR("GetVolumeByPath( '/mnt/sdcardfoo' ) succeeded (unexpected)");
- } else {
- LOG("GetVolumeByPath( '/mnt/sdcardfoo' ) failed (expected)");
- }
-
- return NS_OK;
-}
-
-class InitVolumeServiceTestIO : public Runnable
-{
-public:
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- DBG("InitVolumeServiceTest called");
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
- if (!vs) {
- ERR("do_GetService('%s') failed", NS_VOLUMESERVICE_CONTRACTID);
- return NS_ERROR_FAILURE;
- }
- sTestObserver = new VolumeTestObserver();
-
- return NS_OK;
- }
-};
-#endif // TEST_NSVOLUME_OBSERVER
-
-void
-InitVolumeServiceTestIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
-#if TEST_NSVOLUME_OBSERVER
- // Now that the volume manager is initialized we can go
- // ahead and do our test (on main thread).
- NS_DispatchToMainThread(new InitVolumeServiceTestIO());
-#endif
-}
-
-void
-ShutdownVolumeServiceTest()
-{
-#if TEST_NSVOLUME_OBSERVER
- DBG("ShutdownVolumeServiceTestIOThread called");
- sTestObserver = nullptr;
-#endif
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/VolumeServiceTest.h b/dom/system/gonk/VolumeServiceTest.h
deleted file mode 100644
index 71a92bf6c..000000000
--- a/dom/system/gonk/VolumeServiceTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumeservicetest_h__
-#define mozilla_system_volumeservicetest_h__
-
-
-namespace mozilla {
-namespace system {
-
-void InitVolumeServiceTestIOThread();
-void ShutdownVolumeServiceTest();
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumeservicetest_h__
-
diff --git a/dom/system/gonk/android_audio/AudioSystem.h b/dom/system/gonk/android_audio/AudioSystem.h
deleted file mode 100644
index d5841eaaa..000000000
--- a/dom/system/gonk/android_audio/AudioSystem.h
+++ /dev/null
@@ -1,1134 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIOSYSTEM_H_
-#define ANDROID_AUDIOSYSTEM_H_
-
-#pragma GCC visibility push(default)
-
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-#include "IAudioFlinger.h"
-
-#ifndef VANILLA_ANDROID
-/* request to open a direct output with get_output() (by opposition to
- * sharing an output with other AudioTracks)
- */
-typedef enum {
- AUDIO_POLICY_OUTPUT_FLAG_INDIRECT = 0x0,
- AUDIO_POLICY_OUTPUT_FLAG_DIRECT = 0x1
-} audio_policy_output_flags_t;
-
-/* device categories used for audio_policy->set_force_use() */
-typedef enum {
- AUDIO_POLICY_FORCE_NONE,
- AUDIO_POLICY_FORCE_SPEAKER,
- AUDIO_POLICY_FORCE_HEADPHONES,
- AUDIO_POLICY_FORCE_BT_SCO,
- AUDIO_POLICY_FORCE_BT_A2DP,
- AUDIO_POLICY_FORCE_WIRED_ACCESSORY,
- AUDIO_POLICY_FORCE_BT_CAR_DOCK,
- AUDIO_POLICY_FORCE_BT_DESK_DOCK,
- AUDIO_POLICY_FORCE_ANALOG_DOCK,
- AUDIO_POLICY_FORCE_DIGITAL_DOCK,
- AUDIO_POLICY_FORCE_NO_BT_A2DP,
- AUDIO_POLICY_FORCE_CFG_CNT,
- AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
-
- AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
-} audio_policy_forced_cfg_t;
-
-/* usages used for audio_policy->set_force_use() */
-typedef enum {
- AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
- AUDIO_POLICY_FORCE_FOR_MEDIA,
- AUDIO_POLICY_FORCE_FOR_RECORD,
- AUDIO_POLICY_FORCE_FOR_DOCK,
-
- AUDIO_POLICY_FORCE_USE_CNT,
- AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
-} audio_policy_force_use_t;
-
-typedef enum {
- AUDIO_STREAM_DEFAULT = -1,
- AUDIO_STREAM_VOICE_CALL = 0,
- AUDIO_STREAM_SYSTEM = 1,
- AUDIO_STREAM_RING = 2,
- AUDIO_STREAM_MUSIC = 3,
- AUDIO_STREAM_ALARM = 4,
- AUDIO_STREAM_NOTIFICATION = 5,
- AUDIO_STREAM_BLUETOOTH_SCO = 6,
- AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */
- AUDIO_STREAM_DTMF = 8,
- AUDIO_STREAM_TTS = 9,
-#if ANDROID_VERSION < 19
- AUDIO_STREAM_FM = 10,
-#endif
-
- AUDIO_STREAM_CNT,
- AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1,
-} audio_stream_type_t;
-
-/* PCM sub formats */
-typedef enum {
- AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
- AUDIO_FORMAT_PCM_SUB_8_BIT = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
- AUDIO_FORMAT_PCM_SUB_32_BIT = 0x3, /* PCM signed .31 fixed point */
- AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4, /* PCM signed 7.24 fixed point */
-} audio_format_pcm_sub_fmt_t;
-
-/* Audio format consists in a main format field (upper 8 bits) and a sub format
- * field (lower 24 bits).
- *
- * The main format indicates the main codec type. The sub format field
- * indicates options and parameters for each format. The sub format is mainly
- * used for record to indicate for instance the requested bitrate or profile.
- * It can also be used for certain formats to give informations not present in
- * the encoded audio stream (e.g. octet alignement for AMR).
- */
-typedef enum {
- AUDIO_FORMAT_INVALID = 0xFFFFFFFFUL,
- AUDIO_FORMAT_DEFAULT = 0,
- AUDIO_FORMAT_PCM = 0x00000000UL, /* DO NOT CHANGE */
- AUDIO_FORMAT_MP3 = 0x01000000UL,
- AUDIO_FORMAT_AMR_NB = 0x02000000UL,
- AUDIO_FORMAT_AMR_WB = 0x03000000UL,
- AUDIO_FORMAT_AAC = 0x04000000UL,
- AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL,
- AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL,
- AUDIO_FORMAT_VORBIS = 0x07000000UL,
- AUDIO_FORMAT_MAIN_MASK = 0xFF000000UL,
- AUDIO_FORMAT_SUB_MASK = 0x00FFFFFFUL,
-
- /* Aliases */
- AUDIO_FORMAT_PCM_16_BIT = (AUDIO_FORMAT_PCM |
- AUDIO_FORMAT_PCM_SUB_16_BIT),
- AUDIO_FORMAT_PCM_8_BIT = (AUDIO_FORMAT_PCM |
- AUDIO_FORMAT_PCM_SUB_8_BIT),
- AUDIO_FORMAT_PCM_32_BIT = (AUDIO_FORMAT_PCM |
- AUDIO_FORMAT_PCM_SUB_32_BIT),
- AUDIO_FORMAT_PCM_8_24_BIT = (AUDIO_FORMAT_PCM |
- AUDIO_FORMAT_PCM_SUB_8_24_BIT),
-} audio_format_t;
-
-typedef enum {
- /* output channels */
- AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1,
- AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2,
- AUDIO_CHANNEL_OUT_FRONT_CENTER = 0x4,
- AUDIO_CHANNEL_OUT_LOW_FREQUENCY = 0x8,
- AUDIO_CHANNEL_OUT_BACK_LEFT = 0x10,
- AUDIO_CHANNEL_OUT_BACK_RIGHT = 0x20,
- AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40,
- AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80,
- AUDIO_CHANNEL_OUT_BACK_CENTER = 0x100,
- AUDIO_CHANNEL_OUT_SIDE_LEFT = 0x200,
- AUDIO_CHANNEL_OUT_SIDE_RIGHT = 0x400,
- AUDIO_CHANNEL_OUT_TOP_CENTER = 0x800,
- AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000,
- AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000,
- AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000,
- AUDIO_CHANNEL_OUT_TOP_BACK_LEFT = 0x8000,
- AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000,
- AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000,
-
- AUDIO_CHANNEL_OUT_MONO = AUDIO_CHANNEL_OUT_FRONT_LEFT,
- AUDIO_CHANNEL_OUT_STEREO = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT),
- AUDIO_CHANNEL_OUT_QUAD = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_BACK_LEFT |
- AUDIO_CHANNEL_OUT_BACK_RIGHT),
- AUDIO_CHANNEL_OUT_SURROUND = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_CENTER |
- AUDIO_CHANNEL_OUT_BACK_CENTER),
- AUDIO_CHANNEL_OUT_5POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_CENTER |
- AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
- AUDIO_CHANNEL_OUT_BACK_LEFT |
- AUDIO_CHANNEL_OUT_BACK_RIGHT),
- // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1
- AUDIO_CHANNEL_OUT_7POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_CENTER |
- AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
- AUDIO_CHANNEL_OUT_BACK_LEFT |
- AUDIO_CHANNEL_OUT_BACK_RIGHT |
- AUDIO_CHANNEL_OUT_SIDE_LEFT |
- AUDIO_CHANNEL_OUT_SIDE_RIGHT),
- AUDIO_CHANNEL_OUT_ALL = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_CENTER |
- AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
- AUDIO_CHANNEL_OUT_BACK_LEFT |
- AUDIO_CHANNEL_OUT_BACK_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER |
- AUDIO_CHANNEL_OUT_BACK_CENTER|
- AUDIO_CHANNEL_OUT_SIDE_LEFT|
- AUDIO_CHANNEL_OUT_SIDE_RIGHT|
- AUDIO_CHANNEL_OUT_TOP_CENTER|
- AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT|
- AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER|
- AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT|
- AUDIO_CHANNEL_OUT_TOP_BACK_LEFT|
- AUDIO_CHANNEL_OUT_TOP_BACK_CENTER|
- AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
-
- /* input channels */
- AUDIO_CHANNEL_IN_LEFT = 0x4,
- AUDIO_CHANNEL_IN_RIGHT = 0x8,
- AUDIO_CHANNEL_IN_FRONT = 0x10,
- AUDIO_CHANNEL_IN_BACK = 0x20,
- AUDIO_CHANNEL_IN_LEFT_PROCESSED = 0x40,
- AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 0x80,
- AUDIO_CHANNEL_IN_FRONT_PROCESSED = 0x100,
- AUDIO_CHANNEL_IN_BACK_PROCESSED = 0x200,
- AUDIO_CHANNEL_IN_PRESSURE = 0x400,
- AUDIO_CHANNEL_IN_X_AXIS = 0x800,
- AUDIO_CHANNEL_IN_Y_AXIS = 0x1000,
- AUDIO_CHANNEL_IN_Z_AXIS = 0x2000,
- AUDIO_CHANNEL_IN_VOICE_UPLINK = 0x4000,
- AUDIO_CHANNEL_IN_VOICE_DNLINK = 0x8000,
-
- AUDIO_CHANNEL_IN_MONO = AUDIO_CHANNEL_IN_FRONT,
- AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT),
- AUDIO_CHANNEL_IN_ALL = (AUDIO_CHANNEL_IN_LEFT |
- AUDIO_CHANNEL_IN_RIGHT |
- AUDIO_CHANNEL_IN_FRONT |
- AUDIO_CHANNEL_IN_BACK|
- AUDIO_CHANNEL_IN_LEFT_PROCESSED |
- AUDIO_CHANNEL_IN_RIGHT_PROCESSED |
- AUDIO_CHANNEL_IN_FRONT_PROCESSED |
- AUDIO_CHANNEL_IN_BACK_PROCESSED|
- AUDIO_CHANNEL_IN_PRESSURE |
- AUDIO_CHANNEL_IN_X_AXIS |
- AUDIO_CHANNEL_IN_Y_AXIS |
- AUDIO_CHANNEL_IN_Z_AXIS |
- AUDIO_CHANNEL_IN_VOICE_UPLINK |
- AUDIO_CHANNEL_IN_VOICE_DNLINK),
-} audio_channels_t;
-
-#if ANDROID_VERSION >= 17
-typedef enum {
- AUDIO_MODE_INVALID = -2,
- AUDIO_MODE_CURRENT = -1,
- AUDIO_MODE_NORMAL = 0,
- AUDIO_MODE_RINGTONE = 1,
- AUDIO_MODE_IN_CALL = 2,
- AUDIO_MODE_IN_COMMUNICATION = 3,
-
- AUDIO_MODE_CNT,
- AUDIO_MODE_MAX = AUDIO_MODE_CNT - 1,
-} audio_mode_t;
-#endif
-#endif
-
-#if ANDROID_VERSION < 17
-typedef enum {
- AUDIO_DEVICE_NONE = 0x0,
- /* output devices */
- AUDIO_DEVICE_OUT_EARPIECE = 0x1,
- AUDIO_DEVICE_OUT_SPEAKER = 0x2,
- AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400,
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000,
- AUDIO_DEVICE_OUT_FM = 0x2000,
- AUDIO_DEVICE_OUT_ANC_HEADSET = 0x4000,
- AUDIO_DEVICE_OUT_ANC_HEADPHONE = 0x8000,
- AUDIO_DEVICE_OUT_FM_TX = 0x10000,
- AUDIO_DEVICE_OUT_DIRECTOUTPUT = 0x20000,
- AUDIO_DEVICE_OUT_PROXY = 0x40000,
- AUDIO_DEVICE_OUT_DEFAULT = 0x80000,
- AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
- AUDIO_DEVICE_OUT_SPEAKER |
- AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_FM |
- AUDIO_DEVICE_OUT_ANC_HEADSET |
- AUDIO_DEVICE_OUT_ANC_HEADPHONE |
- AUDIO_DEVICE_OUT_FM_TX |
- AUDIO_DEVICE_OUT_DIRECTOUTPUT |
- AUDIO_DEVICE_OUT_PROXY |
- AUDIO_DEVICE_OUT_DEFAULT),
- AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
- AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
- /* input devices */
- AUDIO_DEVICE_IN_COMMUNICATION = 0x100000,
- AUDIO_DEVICE_IN_AMBIENT = 0x200000,
- AUDIO_DEVICE_IN_BUILTIN_MIC = 0x400000,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x800000,
- AUDIO_DEVICE_IN_WIRED_HEADSET = 0x1000000,
- AUDIO_DEVICE_IN_AUX_DIGITAL = 0x2000000,
- AUDIO_DEVICE_IN_VOICE_CALL = 0x4000000,
- AUDIO_DEVICE_IN_BACK_MIC = 0x8000000,
- AUDIO_DEVICE_IN_ANC_HEADSET = 0x10000000,
- AUDIO_DEVICE_IN_FM_RX = 0x20000000,
- AUDIO_DEVICE_IN_FM_RX_A2DP = 0x40000000,
- AUDIO_DEVICE_IN_DEFAULT = 0x80000000,
-
- AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
- AUDIO_DEVICE_IN_AMBIENT |
- AUDIO_DEVICE_IN_BUILTIN_MIC |
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_IN_WIRED_HEADSET |
- AUDIO_DEVICE_IN_AUX_DIGITAL |
- AUDIO_DEVICE_IN_VOICE_CALL |
- AUDIO_DEVICE_IN_BACK_MIC |
- AUDIO_DEVICE_IN_ANC_HEADSET |
- AUDIO_DEVICE_IN_FM_RX |
- AUDIO_DEVICE_IN_FM_RX_A2DP |
- AUDIO_DEVICE_IN_DEFAULT),
- AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
-} audio_devices_t;
-#elif ANDROID_VERSION < 21
-enum {
- AUDIO_DEVICE_NONE = 0x0,
- /* reserved bits */
- AUDIO_DEVICE_BIT_IN = 0x80000000,
- AUDIO_DEVICE_BIT_DEFAULT = 0x40000000,
- /* output devices */
- AUDIO_DEVICE_OUT_EARPIECE = 0x1,
- AUDIO_DEVICE_OUT_SPEAKER = 0x2,
- AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400,
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000,
- AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000,
- AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 0x8000,
- AUDIO_DEVICE_OUT_ANC_HEADSET = 0x10000,
- AUDIO_DEVICE_OUT_ANC_HEADPHONE = 0x20000,
- AUDIO_DEVICE_OUT_PROXY = 0x40000,
- AUDIO_DEVICE_OUT_FM = 0x80000,
- AUDIO_DEVICE_OUT_FM_TX = 0x100000,
- AUDIO_DEVICE_OUT_DEFAULT = AUDIO_DEVICE_BIT_DEFAULT,
- AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
- AUDIO_DEVICE_OUT_SPEAKER |
- AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_USB_ACCESSORY |
- AUDIO_DEVICE_OUT_USB_DEVICE |
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
- AUDIO_DEVICE_OUT_ANC_HEADSET |
- AUDIO_DEVICE_OUT_ANC_HEADPHONE |
- AUDIO_DEVICE_OUT_PROXY |
- AUDIO_DEVICE_OUT_FM |
- AUDIO_DEVICE_OUT_FM_TX |
- AUDIO_DEVICE_OUT_DEFAULT),
- AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
- AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
- AUDIO_DEVICE_OUT_ALL_USB = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
- AUDIO_DEVICE_OUT_USB_DEVICE),
-
- /* input devices */
- AUDIO_DEVICE_IN_COMMUNICATION = AUDIO_DEVICE_BIT_IN | 0x1,
- AUDIO_DEVICE_IN_AMBIENT = AUDIO_DEVICE_BIT_IN | 0x2,
- AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN | 0x4,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
- AUDIO_DEVICE_IN_WIRED_HEADSET = AUDIO_DEVICE_BIT_IN | 0x10,
- AUDIO_DEVICE_IN_AUX_DIGITAL = AUDIO_DEVICE_BIT_IN | 0x20,
- AUDIO_DEVICE_IN_VOICE_CALL = AUDIO_DEVICE_BIT_IN | 0x40,
- AUDIO_DEVICE_IN_BACK_MIC = AUDIO_DEVICE_BIT_IN | 0x80,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX = AUDIO_DEVICE_BIT_IN | 0x100,
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x200,
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x400,
- AUDIO_DEVICE_IN_USB_ACCESSORY = AUDIO_DEVICE_BIT_IN | 0x800,
- AUDIO_DEVICE_IN_USB_DEVICE = AUDIO_DEVICE_BIT_IN | 0x1000,
- AUDIO_DEVICE_IN_ANC_HEADSET = AUDIO_DEVICE_BIT_IN | 0x2000,
- AUDIO_DEVICE_IN_PROXY = AUDIO_DEVICE_BIT_IN | 0x4000,
- AUDIO_DEVICE_IN_FM_RX = AUDIO_DEVICE_BIT_IN | 0x8000,
- AUDIO_DEVICE_IN_FM_RX_A2DP = AUDIO_DEVICE_BIT_IN | 0x10000,
- AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
-
- AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
- AUDIO_DEVICE_IN_AMBIENT |
- AUDIO_DEVICE_IN_BUILTIN_MIC |
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_IN_WIRED_HEADSET |
- AUDIO_DEVICE_IN_AUX_DIGITAL |
- AUDIO_DEVICE_IN_VOICE_CALL |
- AUDIO_DEVICE_IN_BACK_MIC |
- AUDIO_DEVICE_IN_REMOTE_SUBMIX |
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_IN_USB_ACCESSORY |
- AUDIO_DEVICE_IN_USB_DEVICE |
- AUDIO_DEVICE_IN_ANC_HEADSET |
- AUDIO_DEVICE_IN_FM_RX |
- AUDIO_DEVICE_IN_FM_RX_A2DP |
- AUDIO_DEVICE_IN_PROXY |
- AUDIO_DEVICE_IN_DEFAULT),
- AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
-};
-
-typedef uint32_t audio_devices_t;
-#else
-enum {
- AUDIO_DEVICE_NONE = 0x0,
- /* reserved bits */
- AUDIO_DEVICE_BIT_IN = 0x80000000,
- AUDIO_DEVICE_BIT_DEFAULT = 0x40000000,
- /* output devices */
- AUDIO_DEVICE_OUT_EARPIECE = 0x1,
- AUDIO_DEVICE_OUT_SPEAKER = 0x2,
- AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400,
- AUDIO_DEVICE_OUT_HDMI = AUDIO_DEVICE_OUT_AUX_DIGITAL,
- /* uses an analog connection (multiplexed over the USB connector pins for instance) */
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000,
- /* USB accessory mode: your Android device is a USB device and the dock is a USB host */
- AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000,
- /* USB host mode: your Android device is a USB host and the dock is a USB device */
- AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 0x8000,
- /* Telephony voice TX path */
- AUDIO_DEVICE_OUT_TELEPHONY_TX = 0x10000,
- /* Analog jack with line impedance detected */
- AUDIO_DEVICE_OUT_LINE = 0x20000,
- /* HDMI Audio Return Channel */
- AUDIO_DEVICE_OUT_HDMI_ARC = 0x40000,
- /* S/PDIF out */
- AUDIO_DEVICE_OUT_SPDIF = 0x80000,
- /* FM transmitter out */
- AUDIO_DEVICE_OUT_FM = 0x100000,
- /* Line out for av devices */
- AUDIO_DEVICE_OUT_AUX_LINE = 0x200000,
- /* limited-output speaker device for acoustic safety */
- AUDIO_DEVICE_OUT_SPEAKER_SAFE = 0x400000,
- AUDIO_DEVICE_OUT_DEFAULT = AUDIO_DEVICE_BIT_DEFAULT,
- AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
- AUDIO_DEVICE_OUT_SPEAKER |
- AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_USB_ACCESSORY |
- AUDIO_DEVICE_OUT_USB_DEVICE |
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
- AUDIO_DEVICE_OUT_TELEPHONY_TX |
- AUDIO_DEVICE_OUT_LINE |
- AUDIO_DEVICE_OUT_HDMI_ARC |
- AUDIO_DEVICE_OUT_SPDIF |
- AUDIO_DEVICE_OUT_FM |
- AUDIO_DEVICE_OUT_AUX_LINE |
- AUDIO_DEVICE_OUT_SPEAKER_SAFE |
- AUDIO_DEVICE_OUT_DEFAULT),
- AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
- AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
- AUDIO_DEVICE_OUT_ALL_USB = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
- AUDIO_DEVICE_OUT_USB_DEVICE),
- /* input devices */
- AUDIO_DEVICE_IN_COMMUNICATION = AUDIO_DEVICE_BIT_IN | 0x1,
- AUDIO_DEVICE_IN_AMBIENT = AUDIO_DEVICE_BIT_IN | 0x2,
- AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN | 0x4,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
- AUDIO_DEVICE_IN_WIRED_HEADSET = AUDIO_DEVICE_BIT_IN | 0x10,
- AUDIO_DEVICE_IN_AUX_DIGITAL = AUDIO_DEVICE_BIT_IN | 0x20,
- AUDIO_DEVICE_IN_HDMI = AUDIO_DEVICE_IN_AUX_DIGITAL,
- /* Telephony voice RX path */
- AUDIO_DEVICE_IN_VOICE_CALL = AUDIO_DEVICE_BIT_IN | 0x40,
- AUDIO_DEVICE_IN_BACK_MIC = AUDIO_DEVICE_BIT_IN | 0x80,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX = AUDIO_DEVICE_BIT_IN | 0x100,
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x200,
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x400,
- AUDIO_DEVICE_IN_USB_ACCESSORY = AUDIO_DEVICE_BIT_IN | 0x800,
- AUDIO_DEVICE_IN_USB_DEVICE = AUDIO_DEVICE_BIT_IN | 0x1000,
- /* FM tuner input */
- AUDIO_DEVICE_IN_FM_TUNER = AUDIO_DEVICE_BIT_IN | 0x2000,
- /* TV tuner input */
- AUDIO_DEVICE_IN_TV_TUNER = AUDIO_DEVICE_BIT_IN | 0x4000,
- /* Analog jack with line impedance detected */
- AUDIO_DEVICE_IN_LINE = AUDIO_DEVICE_BIT_IN | 0x8000,
- /* S/PDIF in */
- AUDIO_DEVICE_IN_SPDIF = AUDIO_DEVICE_BIT_IN | 0x10000,
- AUDIO_DEVICE_IN_BLUETOOTH_A2DP = AUDIO_DEVICE_BIT_IN | 0x20000,
- AUDIO_DEVICE_IN_LOOPBACK = AUDIO_DEVICE_BIT_IN | 0x40000,
- AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
- AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
- AUDIO_DEVICE_IN_AMBIENT |
- AUDIO_DEVICE_IN_BUILTIN_MIC |
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_IN_WIRED_HEADSET |
- AUDIO_DEVICE_IN_AUX_DIGITAL |
- AUDIO_DEVICE_IN_VOICE_CALL |
- AUDIO_DEVICE_IN_BACK_MIC |
- AUDIO_DEVICE_IN_REMOTE_SUBMIX |
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_IN_USB_ACCESSORY |
- AUDIO_DEVICE_IN_USB_DEVICE |
- AUDIO_DEVICE_IN_FM_TUNER |
- AUDIO_DEVICE_IN_TV_TUNER |
- AUDIO_DEVICE_IN_LINE |
- AUDIO_DEVICE_IN_SPDIF |
- AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
- AUDIO_DEVICE_IN_LOOPBACK |
- AUDIO_DEVICE_IN_DEFAULT),
- AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
- AUDIO_DEVICE_IN_ALL_USB = (AUDIO_DEVICE_IN_USB_ACCESSORY |
- AUDIO_DEVICE_IN_USB_DEVICE),
-};
-
-typedef uint32_t audio_devices_t;
-#endif
-
-static inline bool audio_is_output_device(uint32_t device)
-{
-#if ANDROID_VERSION < 17
- if ((__builtin_popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
- return true;
- else
- return false;
-#else
- if (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
- (__builtin_popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
- return true;
- else
- return false;
-#endif
-}
-
-/* device connection states used for audio_policy->set_device_connection_state()
- * */
-typedef enum {
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-
- AUDIO_POLICY_DEVICE_STATE_CNT,
- AUDIO_POLICY_DEVICE_STATE_MAX = AUDIO_POLICY_DEVICE_STATE_CNT - 1,
-} audio_policy_dev_state_t;
-
-namespace android {
-
-typedef void (*audio_error_callback)(status_t err);
-typedef int audio_io_handle_t;
-
-class IAudioPolicyService;
-class String8;
-
-class AudioSystem
-{
-public:
-
- enum stream_type {
- DEFAULT =-1,
- VOICE_CALL = 0,
- SYSTEM = 1,
- RING = 2,
- MUSIC = 3,
- ALARM = 4,
- NOTIFICATION = 5,
- BLUETOOTH_SCO = 6,
- ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker
- DTMF = 8,
- TTS = 9,
- FM = 10,
- NUM_STREAM_TYPES
- };
-
- // Audio sub formats (see AudioSystem::audio_format).
- enum pcm_sub_format {
- PCM_SUB_16_BIT = 0x1, // must be 1 for backward compatibility
- PCM_SUB_8_BIT = 0x2, // must be 2 for backward compatibility
- };
-
- // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to specify
- // bit rate, stereo mode, version...
- enum mp3_sub_format {
- //TODO
- };
-
- // AMR NB/WB sub format field definition: specify frame block interleaving, bandwidth efficient or octet aligned,
- // encoding mode for recording...
- enum amr_sub_format {
- //TODO
- };
-
- // AAC sub format field definition: specify profile or bitrate for recording...
- enum aac_sub_format {
- //TODO
- };
-
- // VORBIS sub format field definition: specify quality for recording...
- enum vorbis_sub_format {
- //TODO
- };
-
- // Audio format consists in a main format field (upper 8 bits) and a sub format field (lower 24 bits).
- // The main format indicates the main codec type. The sub format field indicates options and parameters
- // for each format. The sub format is mainly used for record to indicate for instance the requested bitrate
- // or profile. It can also be used for certain formats to give informations not present in the encoded
- // audio stream (e.g. octet alignement for AMR).
- enum audio_format {
- INVALID_FORMAT = -1,
- FORMAT_DEFAULT = 0,
- PCM = 0x00000000, // must be 0 for backward compatibility
- MP3 = 0x01000000,
- AMR_NB = 0x02000000,
- AMR_WB = 0x03000000,
- AAC = 0x04000000,
- HE_AAC_V1 = 0x05000000,
- HE_AAC_V2 = 0x06000000,
- VORBIS = 0x07000000,
- EVRC = 0x08000000,
- QCELP = 0x09000000,
- VOIP_PCM_INPUT = 0x0A000000,
- MAIN_FORMAT_MASK = 0xFF000000,
- SUB_FORMAT_MASK = 0x00FFFFFF,
- // Aliases
- PCM_16_BIT = (PCM|PCM_SUB_16_BIT),
- PCM_8_BIT = (PCM|PCM_SUB_8_BIT)
- };
-
-
- // Channel mask definitions must be kept in sync with JAVA values in /media/java/android/media/AudioFormat.java
- enum audio_channels {
- // output channels
- CHANNEL_OUT_FRONT_LEFT = 0x4,
- CHANNEL_OUT_FRONT_RIGHT = 0x8,
- CHANNEL_OUT_FRONT_CENTER = 0x10,
- CHANNEL_OUT_LOW_FREQUENCY = 0x20,
- CHANNEL_OUT_BACK_LEFT = 0x40,
- CHANNEL_OUT_BACK_RIGHT = 0x80,
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100,
- CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200,
- CHANNEL_OUT_BACK_CENTER = 0x400,
- CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT,
- CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT),
- CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
- CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER),
- CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
- CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
- CHANNEL_OUT_ALL = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | CHANNEL_OUT_BACK_CENTER),
-
- // input channels
- CHANNEL_IN_LEFT = 0x4,
- CHANNEL_IN_RIGHT = 0x8,
- CHANNEL_IN_FRONT = 0x10,
- CHANNEL_IN_BACK = 0x20,
- CHANNEL_IN_LEFT_PROCESSED = 0x40,
- CHANNEL_IN_RIGHT_PROCESSED = 0x80,
- CHANNEL_IN_FRONT_PROCESSED = 0x100,
- CHANNEL_IN_BACK_PROCESSED = 0x200,
- CHANNEL_IN_PRESSURE = 0x400,
- CHANNEL_IN_X_AXIS = 0x800,
- CHANNEL_IN_Y_AXIS = 0x1000,
- CHANNEL_IN_Z_AXIS = 0x2000,
- CHANNEL_IN_VOICE_UPLINK = 0x4000,
- CHANNEL_IN_VOICE_DNLINK = 0x8000,
- CHANNEL_IN_MONO = CHANNEL_IN_FRONT,
- CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT),
- CHANNEL_IN_ALL = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK|
- CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED | CHANNEL_IN_FRONT_PROCESSED | CHANNEL_IN_BACK_PROCESSED|
- CHANNEL_IN_PRESSURE | CHANNEL_IN_X_AXIS | CHANNEL_IN_Y_AXIS | CHANNEL_IN_Z_AXIS |
- CHANNEL_IN_VOICE_UPLINK | CHANNEL_IN_VOICE_DNLINK)
- };
-
- enum audio_mode {
- MODE_INVALID = -2,
- MODE_CURRENT = -1,
- MODE_NORMAL = 0,
- MODE_RINGTONE,
- MODE_IN_CALL,
- MODE_IN_COMMUNICATION,
- NUM_MODES // not a valid entry, denotes end-of-list
- };
-
- enum audio_in_acoustics {
- AGC_ENABLE = 0x0001,
- AGC_DISABLE = 0,
- NS_ENABLE = 0x0002,
- NS_DISABLE = 0,
- TX_IIR_ENABLE = 0x0004,
- TX_DISABLE = 0
- };
-
- // special audio session values
- enum audio_sessions {
- SESSION_OUTPUT_STAGE = -1, // session for effects attached to a particular output stream
- // (value must be less than 0)
- SESSION_OUTPUT_MIX = 0, // session for effects applied to output mix. These effects can
- // be moved by audio policy manager to another output stream
- // (value must be 0)
- };
-
- /* These are static methods to control the system-wide AudioFlinger
- * only privileged processes can have access to them
- */
-
- // mute/unmute microphone
- static status_t muteMicrophone(bool state);
- static status_t isMicrophoneMuted(bool *state);
-
- // set/get master volume
- static status_t setMasterVolume(float value);
- static status_t getMasterVolume(float* volume);
- // mute/unmute audio outputs
- static status_t setMasterMute(bool mute);
- static status_t getMasterMute(bool* mute);
-
- // set/get stream volume on specified output
- static status_t setStreamVolume(int stream, float value, int output);
- static status_t getStreamVolume(int stream, float* volume, int output);
-
- // mute/unmute stream
- static status_t setStreamMute(int stream, bool mute);
- static status_t getStreamMute(int stream, bool* mute);
-
- // set audio mode in audio hardware (see AudioSystem::audio_mode)
- static status_t setMode(int mode);
-
- // returns true in *state if tracks are active on the specified stream
- static status_t isStreamActive(int stream, bool *state);
-
- // set/get audio hardware parameters. The function accepts a list of parameters
- // key value pairs in the form: key1=value1;key2=value2;...
- // Some keys are reserved for standard parameters (See AudioParameter class).
- static status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
- static String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
-
- static void setErrorCallback(audio_error_callback cb);
-
- // helper function to obtain AudioFlinger service handle
- static const sp<IAudioFlinger>& get_audio_flinger();
-
- static float linearToLog(int volume);
- static int logToLinear(float volume);
-
- static status_t getOutputSamplingRate(int* samplingRate, int stream = DEFAULT);
- static status_t getOutputFrameCount(int* frameCount, int stream = DEFAULT);
- static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT);
-
- static bool routedToA2dpOutput(int streamType);
-
- static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
- size_t* buffSize);
-
- static status_t setVoiceVolume(float volume);
-
- // return the number of audio frames written by AudioFlinger to audio HAL and
- // audio dsp to DAC since the output on which the specificed stream is playing
- // has exited standby.
- // returned status (from utils/Errors.h) can be:
- // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data
- // - INVALID_OPERATION: Not supported on current hardware platform
- // - BAD_VALUE: invalid parameter
- // NOTE: this feature is not supported on all hardware platforms and it is
- // necessary to check returned status before using the returned values.
- static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT);
-
- static unsigned int getInputFramesLost(audio_io_handle_t ioHandle);
-
- static int newAudioSessionId();
- //
- // AudioPolicyService interface
- //
-
- enum audio_devices {
- // output devices
- DEVICE_OUT_EARPIECE = 0x1,
- DEVICE_OUT_SPEAKER = 0x2,
- DEVICE_OUT_WIRED_HEADSET = 0x4,
- DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- DEVICE_OUT_AUX_DIGITAL = 0x400,
- DEVICE_OUT_DEFAULT = 0x8000,
- DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET |
- DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT | DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_DEFAULT),
- DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-
- // input devices
- DEVICE_IN_COMMUNICATION = 0x10000,
- DEVICE_IN_AMBIENT = 0x20000,
- DEVICE_IN_BUILTIN_MIC = 0x40000,
- DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
- DEVICE_IN_WIRED_HEADSET = 0x100000,
- DEVICE_IN_AUX_DIGITAL = 0x200000,
- DEVICE_IN_VOICE_CALL = 0x400000,
- DEVICE_IN_BACK_MIC = 0x800000,
- DEVICE_IN_DEFAULT = 0x80000000,
-
- DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC |
- DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL |
- DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC | DEVICE_IN_DEFAULT)
- };
-
- // device connection states used for setDeviceConnectionState()
- enum device_connection_state {
- DEVICE_STATE_UNAVAILABLE,
- DEVICE_STATE_AVAILABLE,
- NUM_DEVICE_STATES
- };
-
- // request to open a direct output with getOutput() (by opposition to sharing an output with other AudioTracks)
- enum output_flags {
- OUTPUT_FLAG_INDIRECT = 0x0,
- OUTPUT_FLAG_DIRECT = 0x1
- };
-
- // device categories used for setForceUse()
- enum forced_config {
- FORCE_NONE,
- FORCE_SPEAKER,
- FORCE_HEADPHONES,
- FORCE_BT_SCO,
- FORCE_BT_A2DP,
- FORCE_WIRED_ACCESSORY,
- FORCE_BT_CAR_DOCK,
- FORCE_BT_DESK_DOCK,
- FORCE_ANALOG_DOCK,
- FORCE_DIGITAL_DOCK,
- FORCE_NO_BT_A2DP,
- NUM_FORCE_CONFIG,
- FORCE_DEFAULT = FORCE_NONE
- };
-
- // usages used for setForceUse()
- enum force_use {
- FOR_COMMUNICATION,
- FOR_MEDIA,
- FOR_RECORD,
- FOR_DOCK,
- NUM_FORCE_USE
- };
-
- // types of io configuration change events received with ioConfigChanged()
- enum io_config_event {
- OUTPUT_OPENED,
- OUTPUT_CLOSED,
- OUTPUT_CONFIG_CHANGED,
- INPUT_OPENED,
- INPUT_CLOSED,
- INPUT_CONFIG_CHANGED,
- STREAM_CONFIG_CHANGED,
- NUM_CONFIG_EVENTS
- };
-
- // audio output descritor used to cache output configurations in client process to avoid frequent calls
- // through IAudioFlinger
- class OutputDescriptor {
- public:
- OutputDescriptor()
- : samplingRate(0), format(0), channels(0), frameCount(0), latency(0) {}
-
- uint32_t samplingRate;
- int32_t format;
- int32_t channels;
- size_t frameCount;
- uint32_t latency;
- };
-
- //
- // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
- //
- static status_t setDeviceConnectionState(audio_devices device, device_connection_state state, const char *device_address);
- static device_connection_state getDeviceConnectionState(audio_devices device, const char *device_address);
- static status_t setPhoneState(int state);
-#if ANDROID_VERSION >= 17
- static status_t setPhoneState(audio_mode_t state);
-#endif
- static status_t setRingerMode(uint32_t mode, uint32_t mask);
-#ifdef VANILLA_ANDROID
- static status_t setForceUse(force_use usage, forced_config config);
- static forced_config getForceUse(force_use usage);
- static audio_io_handle_t getOutput(stream_type stream,
- uint32_t samplingRate = 0,
- uint32_t format = FORMAT_DEFAULT,
- uint32_t channels = CHANNEL_OUT_STEREO,
- output_flags flags = OUTPUT_FLAG_INDIRECT);
- static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address);
- static status_t setFmVolume(float volume);
- static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address);
-#else
- static status_t setForceUse(force_use usage, forced_config config) __attribute__((weak));
- static forced_config getForceUse(force_use usage) __attribute__((weak));
- static audio_io_handle_t getOutput(stream_type stream,
- uint32_t samplingRate = 0,
- uint32_t format = FORMAT_DEFAULT,
- uint32_t channels = CHANNEL_OUT_STEREO,
- output_flags flags = OUTPUT_FLAG_INDIRECT) __attribute__((weak));
-
- static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) __attribute__((weak));
- static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) __attribute__((weak));
- static audio_io_handle_t getOutput(audio_stream_type_t stream,
- uint32_t samplingRate = 0,
- uint32_t format = AUDIO_FORMAT_DEFAULT,
- uint32_t channels = AUDIO_CHANNEL_OUT_STEREO,
- audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_INDIRECT) __attribute__((weak));
- static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address) __attribute__((weak));
- static status_t setFmVolume(float volume) __attribute__((weak));
- static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address) __attribute__((weak));
-
-#endif
- static status_t startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
- int session = 0);
- static status_t stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
- int session = 0);
- static void releaseOutput(audio_io_handle_t output);
- static audio_io_handle_t getInput(int inputSource,
- uint32_t samplingRate = 0,
- uint32_t format = FORMAT_DEFAULT,
- uint32_t channels = CHANNEL_IN_MONO,
- audio_in_acoustics acoustics = (audio_in_acoustics)0);
- static status_t startInput(audio_io_handle_t input);
- static status_t stopInput(audio_io_handle_t input);
- static void releaseInput(audio_io_handle_t input);
- static status_t initStreamVolume(stream_type stream,
- int indexMin,
- int indexMax);
- static status_t initStreamVolume(audio_stream_type_t stream,
- int indexMin,
- int indexMax);
- static status_t setStreamVolumeIndex(stream_type stream, int index);
- static status_t setStreamVolumeIndex(audio_stream_type_t stream, int index);
-#if ANDROID_VERSION >= 17
- static status_t setStreamVolumeIndex(audio_stream_type_t stream,
- int index,
- audio_devices_t device);
- static status_t getStreamVolumeIndex(audio_stream_type_t stream,
- int *index,
- audio_devices_t device);
-#endif
- static status_t getStreamVolumeIndex(stream_type stream, int *index);
- static status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index);
-
- static uint32_t getStrategyForStream(stream_type stream);
-#if ANDROID_VERSION >= 17
- static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
-#endif
-
- static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
- static status_t registerEffect(effect_descriptor_t *desc,
- audio_io_handle_t output,
- uint32_t strategy,
- int session,
- int id);
- static status_t unregisterEffect(int id);
-
- static const sp<IAudioPolicyService>& get_audio_policy_service();
-
- // ----------------------------------------------------------------------------
-
- static uint32_t popCount(uint32_t u);
- static bool isOutputDevice(audio_devices device);
- static bool isInputDevice(audio_devices device);
- static bool isA2dpDevice(audio_devices device);
- static bool isBluetoothScoDevice(audio_devices device);
- static bool isSeperatedStream(stream_type stream);
- static bool isLowVisibility(stream_type stream);
- static bool isOutputChannel(uint32_t channel);
- static bool isInputChannel(uint32_t channel);
- static bool isValidFormat(uint32_t format);
- static bool isLinearPCM(uint32_t format);
- static bool isModeInCall();
-
-#if ANDROID_VERSION >= 21
- class AudioPortCallback : public RefBase
- {
- public:
-
- AudioPortCallback() {}
- virtual ~AudioPortCallback() {}
-
- virtual void onAudioPortListUpdate() = 0;
- virtual void onAudioPatchListUpdate() = 0;
- virtual void onServiceDied() = 0;
-
- };
-
- static void setAudioPortCallback(sp<AudioPortCallback> callBack);
-#endif
-
-private:
-
- class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
- {
- public:
- AudioFlingerClient() {
- }
-
- // DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
-
- // IAudioFlingerClient
-
- // indicate a change in the configuration of an output or input: keeps the cached
- // values for output/input parameters upto date in client process
- virtual void ioConfigChanged(int event, int ioHandle, void *param2);
- };
-
- class AudioPolicyServiceClient: public IBinder::DeathRecipient
- {
- public:
- AudioPolicyServiceClient() {
- }
-
- // DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
- };
-
- static sp<AudioFlingerClient> gAudioFlingerClient;
- static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient;
- friend class AudioFlingerClient;
- friend class AudioPolicyServiceClient;
-
- static Mutex gLock;
- static sp<IAudioFlinger> gAudioFlinger;
- static audio_error_callback gAudioErrorCallback;
-
- static size_t gInBuffSize;
- // previous parameters for recording buffer size queries
- static uint32_t gPrevInSamplingRate;
- static int gPrevInFormat;
- static int gPrevInChannelCount;
-
- static sp<IAudioPolicyService> gAudioPolicyService;
-
- // mapping between stream types and outputs
- static DefaultKeyedVector<int, audio_io_handle_t> gStreamOutputMap;
- // list of output descritor containing cached parameters (sampling rate, framecount, channel count...)
- static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
-};
-
-class AudioParameter {
-
-public:
- AudioParameter() {}
- AudioParameter(const String8& keyValuePairs);
- virtual ~AudioParameter();
-
- // reserved parameter keys for changing standard parameters with setParameters() function.
- // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
- // configuration changes and act accordingly.
- // keyRouting: to change audio routing, value is an int in AudioSystem::audio_devices
- // keySamplingRate: to change sampling rate routing, value is an int
- // keyFormat: to change audio format, value is an int in AudioSystem::audio_format
- // keyChannels: to change audio channel configuration, value is an int in AudioSystem::audio_channels
- // keyFrameCount: to change audio output frame count, value is an int
- // keyInputSource: to change audio input source, value is an int in audio_source
- // (defined in media/mediarecorder.h)
- static const char *keyRouting;
- static const char *keySamplingRate;
- static const char *keyFormat;
- static const char *keyChannels;
- static const char *keyFrameCount;
- static const char *keyInputSource;
-
- String8 toString();
-
- status_t add(const String8& key, const String8& value);
- status_t addInt(const String8& key, const int value);
- status_t addFloat(const String8& key, const float value);
-
- status_t remove(const String8& key);
-
- status_t get(const String8& key, String8& value);
- status_t getInt(const String8& key, int& value);
- status_t getFloat(const String8& key, float& value);
- status_t getAt(size_t index, String8& key, String8& value);
-
- size_t size() { return mParameters.size(); }
-
-private:
- String8 mKeyValuePairs;
- KeyedVector <String8, String8> mParameters;
-};
-
-}; // namespace android
-
-#pragma GCC visibility pop
-
-#endif /*ANDROID_AUDIOSYSTEM_H_*/
diff --git a/dom/system/gonk/android_audio/AudioTrack.h b/dom/system/gonk/android_audio/AudioTrack.h
deleted file mode 100644
index 6f8c6bb28..000000000
--- a/dom/system/gonk/android_audio/AudioTrack.h
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIOTRACK_H
-#define ANDROID_AUDIOTRACK_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "IAudioFlinger.h"
-#include "IAudioTrack.h"
-#include "AudioSystem.h"
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-#include <utils/threads.h>
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class audio_track_cblk_t;
-
-// ----------------------------------------------------------------------------
-
-class AudioTrack
-{
-public:
- enum channel_index {
- MONO = 0,
- LEFT = 0,
- RIGHT = 1
- };
-
- /* Events used by AudioTrack callback function (audio_track_cblk_t).
- */
- enum event_type {
- EVENT_MORE_DATA = 0, // Request to write more data to PCM buffer.
- EVENT_UNDERRUN = 1, // PCM buffer underrun occured.
- EVENT_LOOP_END = 2, // Sample loop end was reached; playback restarted from loop start if loop count was not 0.
- EVENT_MARKER = 3, // Playback head is at the specified marker position (See setMarkerPosition()).
- EVENT_NEW_POS = 4, // Playback head is at a new position (See setPositionUpdatePeriod()).
- EVENT_BUFFER_END = 5 // Playback head is at the end of the buffer.
- };
-
- /* Create Buffer on the stack and pass it to obtainBuffer()
- * and releaseBuffer().
- */
-
- class Buffer
- {
- public:
- enum {
- MUTE = 0x00000001
- };
- uint32_t flags;
- int channelCount;
- int format;
- size_t frameCount;
- size_t size;
- union {
- void* raw;
- short* i16;
- int8_t* i8;
- };
- };
-
-
- /* As a convenience, if a callback is supplied, a handler thread
- * is automatically created with the appropriate priority. This thread
- * invokes the callback when a new buffer becomes availlable or an underrun condition occurs.
- * Parameters:
- *
- * event: type of event notified (see enum AudioTrack::event_type).
- * user: Pointer to context for use by the callback receiver.
- * info: Pointer to optional parameter according to event type:
- * - EVENT_MORE_DATA: pointer to AudioTrack::Buffer struct. The callback must not write
- * more bytes than indicated by 'size' field and update 'size' if less bytes are
- * written.
- * - EVENT_UNDERRUN: unused.
- * - EVENT_LOOP_END: pointer to an int indicating the number of loops remaining.
- * - EVENT_MARKER: pointer to an uin32_t containing the marker position in frames.
- * - EVENT_NEW_POS: pointer to an uin32_t containing the new position in frames.
- * - EVENT_BUFFER_END: unused.
- */
-
- typedef void (*callback_t)(int event, void* user, void *info);
-
- /* Returns the minimum frame count required for the successful creation of
- * an AudioTrack object.
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - NO_INIT: audio server or audio hardware not initialized
- */
-
- static status_t getMinFrameCount(int* frameCount,
- int streamType =-1,
- uint32_t sampleRate = 0);
-
- /* Constructs an uninitialized AudioTrack. No connection with
- * AudioFlinger takes place.
- */
- AudioTrack();
-
- /* Creates an audio track and registers it with AudioFlinger.
- * Once created, the track needs to be started before it can be used.
- * Unspecified values are set to the audio hardware's current
- * values.
- *
- * Parameters:
- *
- * streamType: Select the type of audio stream this track is attached to
- * (e.g. AudioSystem::MUSIC).
- * sampleRate: Track sampling rate in Hz.
- * format: Audio format (e.g AudioSystem::PCM_16_BIT for signed
- * 16 bits per sample).
- * channels: Channel mask: see AudioSystem::audio_channels.
- * frameCount: Total size of track PCM buffer in frames. This defines the
- * latency of the track.
- * flags: Reserved for future use.
- * cbf: Callback function. If not null, this function is called periodically
- * to request new PCM data.
- * notificationFrames: The callback function is called each time notificationFrames PCM
- * frames have been comsumed from track input buffer.
- * user Context for use by the callback receiver.
- */
-
- AudioTrack( int streamType,
- uint32_t sampleRate = 0,
- int format = 0,
- int channels = 0,
- int frameCount = 0,
- uint32_t flags = 0,
- callback_t cbf = 0,
- void* user = 0,
- int notificationFrames = 0,
- int sessionId = 0);
-
- /* Creates an audio track and registers it with AudioFlinger. With this constructor,
- * The PCM data to be rendered by AudioTrack is passed in a shared memory buffer
- * identified by the argument sharedBuffer. This prototype is for static buffer playback.
- * PCM data must be present into memory before the AudioTrack is started.
- * The Write() and Flush() methods are not supported in this case.
- * It is recommented to pass a callback function to be notified of playback end by an
- * EVENT_UNDERRUN event.
- */
-
- AudioTrack( int streamType,
- uint32_t sampleRate = 0,
- int format = 0,
- int channels = 0,
- const sp<IMemory>& sharedBuffer = 0,
- uint32_t flags = 0,
- callback_t cbf = 0,
- void* user = 0,
- int notificationFrames = 0,
- int sessionId = 0);
-
- /* Terminates the AudioTrack and unregisters it from AudioFlinger.
- * Also destroys all resources assotiated with the AudioTrack.
- */
- ~AudioTrack();
-
-
- /* Initialize an uninitialized AudioTrack.
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful intialization
- * - INVALID_OPERATION: AudioTrack is already intitialized
- * - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
- * - NO_INIT: audio server or audio hardware not initialized
- * */
- status_t set(int streamType =-1,
- uint32_t sampleRate = 0,
- int format = 0,
- int channels = 0,
- int frameCount = 0,
- uint32_t flags = 0,
- callback_t cbf = 0,
- void* user = 0,
- int notificationFrames = 0,
- const sp<IMemory>& sharedBuffer = 0,
- bool threadCanCallJava = false,
- int sessionId = 0);
-
-
- /* Result of constructing the AudioTrack. This must be checked
- * before using any AudioTrack API (except for set()), using
- * an uninitialized AudioTrack produces undefined results.
- * See set() method above for possible return codes.
- */
- status_t initCheck() const;
-
- /* Returns this track's latency in milliseconds.
- * This includes the latency due to AudioTrack buffer size, AudioMixer (if any)
- * and audio hardware driver.
- */
- uint32_t latency() const;
-
- /* getters, see constructor */
-
- int streamType() const;
- int format() const;
- int channelCount() const;
- uint32_t frameCount() const;
- int frameSize() const;
- sp<IMemory>& sharedBuffer();
-
-
- /* After it's created the track is not active. Call start() to
- * make it active. If set, the callback will start being called.
- */
- void start();
-
- /* Stop a track. If set, the callback will cease being called and
- * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
- * and will fill up buffers until the pool is exhausted.
- */
- void stop();
- bool stopped() const;
-
- /* flush a stopped track. All pending buffers are discarded.
- * This function has no effect if the track is not stoped.
- */
- void flush();
-
- /* Pause a track. If set, the callback will cease being called and
- * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
- * and will fill up buffers until the pool is exhausted.
- */
- void pause();
-
- /* mute or unmutes this track.
- * While mutted, the callback, if set, is still called.
- */
- void mute(bool);
- bool muted() const;
-
-
- /* set volume for this track, mostly used for games' sound effects
- * left and right volumes. Levels must be <= 1.0.
- */
- status_t setVolume(float left, float right);
- void getVolume(float* left, float* right);
-
- /* set the send level for this track. An auxiliary effect should be attached
- * to the track with attachEffect(). Level must be <= 1.0.
- */
- status_t setAuxEffectSendLevel(float level);
- void getAuxEffectSendLevel(float* level);
-
- /* set sample rate for this track, mostly used for games' sound effects
- */
- status_t setSampleRate(int sampleRate);
- uint32_t getSampleRate();
-
- /* Enables looping and sets the start and end points of looping.
- *
- * Parameters:
- *
- * loopStart: loop start expressed as the number of PCM frames played since AudioTrack start.
- * loopEnd: loop end expressed as the number of PCM frames played since AudioTrack start.
- * loopCount: number of loops to execute. Calling setLoop() with loopCount == 0 cancels any pending or
- * active loop. loopCount = -1 means infinite looping.
- *
- * For proper operation the following condition must be respected:
- * (loopEnd-loopStart) <= framecount()
- */
- status_t setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount);
- status_t getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount);
-
-
- /* Sets marker position. When playback reaches the number of frames specified, a callback with event
- * type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker notification
- * callback.
- * If the AudioTrack has been opened with no callback function associated, the operation will fail.
- *
- * Parameters:
- *
- * marker: marker position expressed in frames.
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the AudioTrack has no callback installed.
- */
- status_t setMarkerPosition(uint32_t marker);
- status_t getMarkerPosition(uint32_t *marker);
-
-
- /* Sets position update period. Every time the number of frames specified has been played,
- * a callback with event type EVENT_NEW_POS is called.
- * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
- * callback.
- * If the AudioTrack has been opened with no callback function associated, the operation will fail.
- *
- * Parameters:
- *
- * updatePeriod: position update notification period expressed in frames.
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the AudioTrack has no callback installed.
- */
- status_t setPositionUpdatePeriod(uint32_t updatePeriod);
- status_t getPositionUpdatePeriod(uint32_t *updatePeriod);
-
-
- /* Sets playback head position within AudioTrack buffer. The new position is specified
- * in number of frames.
- * This method must be called with the AudioTrack in paused or stopped state.
- * Note that the actual position set is <position> modulo the AudioTrack buffer size in frames.
- * Therefore using this method makes sense only when playing a "static" audio buffer
- * as opposed to streaming.
- * The getPosition() method on the other hand returns the total number of frames played since
- * playback start.
- *
- * Parameters:
- *
- * position: New playback head position within AudioTrack buffer.
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the AudioTrack is not stopped.
- * - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack buffer
- */
- status_t setPosition(uint32_t position);
- status_t getPosition(uint32_t *position);
-
- /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids
- * rewriting the buffer before restarting playback after a stop.
- * This method must be called with the AudioTrack in paused or stopped state.
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the AudioTrack is not stopped.
- */
- status_t reload();
-
- /* returns a handle on the audio output used by this AudioTrack.
- *
- * Parameters:
- * none.
- *
- * Returned value:
- * handle on audio hardware output
- */
- audio_io_handle_t getOutput();
-
- /* returns the unique ID associated to this track.
- *
- * Parameters:
- * none.
- *
- * Returned value:
- * AudioTrack ID.
- */
- int getSessionId();
-
-
- /* Attach track auxiliary output to specified effect. Used effectId = 0
- * to detach track from effect.
- *
- * Parameters:
- *
- * effectId: effectId obtained from AudioEffect::id().
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the effect is not an auxiliary effect.
- * - BAD_VALUE: The specified effect ID is invalid
- */
- status_t attachAuxEffect(int effectId);
-
- /* obtains a buffer of "frameCount" frames. The buffer must be
- * filled entirely. If the track is stopped, obtainBuffer() returns
- * STOPPED instead of NO_ERROR as long as there are buffers availlable,
- * at which point NO_MORE_BUFFERS is returned.
- * Buffers will be returned until the pool (buffercount())
- * is exhausted, at which point obtainBuffer() will either block
- * or return WOULD_BLOCK depending on the value of the "blocking"
- * parameter.
- */
-
- enum {
- NO_MORE_BUFFERS = 0x80000001,
- STOPPED = 1
- };
-
- status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
- void releaseBuffer(Buffer* audioBuffer);
-
-
- /* As a convenience we provide a write() interface to the audio buffer.
- * This is implemented on top of lockBuffer/unlockBuffer. For best
- * performance
- *
- */
- ssize_t write(const void* buffer, size_t size);
-
- /*
- * Dumps the state of an audio track.
- */
- status_t dump(int fd, const Vector<String16>& args) const;
-
-private:
- /* copying audio tracks is not allowed */
- AudioTrack(const AudioTrack& other);
- AudioTrack& operator = (const AudioTrack& other);
-
- /* a small internal class to handle the callback */
- class AudioTrackThread : public Thread
- {
- public:
- AudioTrackThread(AudioTrack& receiver, bool bCanCallJava = false);
- private:
- friend class AudioTrack;
- virtual bool threadLoop();
- virtual status_t readyToRun();
- virtual void onFirstRef();
- AudioTrack& mReceiver;
- Mutex mLock;
- };
-
- bool processAudioBuffer(const sp<AudioTrackThread>& thread);
- status_t createTrack(int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- const sp<IMemory>& sharedBuffer,
- audio_io_handle_t output,
- bool enforceFrameCount);
-
- sp<IAudioTrack> mAudioTrack;
- sp<IMemory> mCblkMemory;
- sp<AudioTrackThread> mAudioTrackThread;
-
- float mVolume[2];
- float mSendLevel;
- uint32_t mFrameCount;
-
- audio_track_cblk_t* mCblk;
- uint8_t mStreamType;
- uint8_t mFormat;
- uint8_t mChannelCount;
- uint8_t mMuted;
- uint32_t mChannels;
- status_t mStatus;
- uint32_t mLatency;
-
- volatile int32_t mActive;
-
- callback_t mCbf;
- void* mUserData;
- uint32_t mNotificationFramesReq; // requested number of frames between each notification callback
- uint32_t mNotificationFramesAct; // actual number of frames between each notification callback
- sp<IMemory> mSharedBuffer;
- int mLoopCount;
- uint32_t mRemainingFrames;
- uint32_t mMarkerPosition;
- bool mMarkerReached;
- uint32_t mNewPosition;
- uint32_t mUpdatePeriod;
- uint32_t mFlags;
- int mSessionId;
- int mAuxEffectId;
- uint32_t mPadding[8];
-};
-
-
-}; // namespace android
-
-#endif // ANDROID_AUDIOTRACK_H
diff --git a/dom/system/gonk/android_audio/EffectApi.h b/dom/system/gonk/android_audio/EffectApi.h
deleted file mode 100644
index 729545d0c..000000000
--- a/dom/system/gonk/android_audio/EffectApi.h
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_EFFECTAPI_H_
-#define ANDROID_EFFECTAPI_H_
-
-#include <errno.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-/////////////////////////////////////////////////
-// Effect control interface
-/////////////////////////////////////////////////
-
-// The effect control interface is exposed by each effect engine implementation. It consists of
-// a set of functions controlling the configuration, activation and process of the engine.
-// The functions are grouped in a structure of type effect_interface_s:
-// struct effect_interface_s {
-// effect_process_t process;
-// effect_command_t command;
-// };
-
-
-// effect_interface_t: Effect control interface handle.
-// The effect_interface_t serves two purposes regarding the implementation of the effect engine:
-// - 1 it is the address of a pointer to an effect_interface_s structure where the functions
-// of the effect control API for a particular effect are located.
-// - 2 it is the address of the context of a particular effect instance.
-// A typical implementation in the effect library would define a structure as follows:
-// struct effect_module_s {
-// const struct effect_interface_s *itfe;
-// effect_config_t config;
-// effect_context_t context;
-// }
-// The implementation of EffectCreate() function would then allocate a structure of this
-// type and return its address as effect_interface_t
-typedef struct effect_interface_s **effect_interface_t;
-
-
-// Effect API version 1.0
-#define EFFECT_API_VERSION 0x0100 // Format 0xMMmm MM: Major version, mm: minor version
-
-// Maximum length of character strings in structures defines by this API.
-#define EFFECT_STRING_LEN_MAX 64
-
-//
-//--- Effect descriptor structure effect_descriptor_t
-//
-
-// Unique effect ID (can be generated from the following site:
-// http://www.itu.int/ITU-T/asn1/uuid.html)
-// This format is used for both "type" and "uuid" fields of the effect descriptor structure.
-// - When used for effect type and the engine is implementing and effect corresponding to a standard
-// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface.
-// - When used as uuid, it should be a unique UUID for this particular implementation.
-typedef struct effect_uuid_s {
- uint32_t timeLow;
- uint16_t timeMid;
- uint16_t timeHiAndVersion;
- uint16_t clockSeq;
- uint8_t node[6];
-} effect_uuid_t;
-
-// NULL UUID definition (matches SL_IID_NULL_)
-#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \
- { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } }
-static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER;
-const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_;
-const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210";
-
-// The effect descriptor contains necessary information to facilitate the enumeration of the effect
-// engines present in a library.
-typedef struct effect_descriptor_s {
- effect_uuid_t type; // UUID of to the OpenSL ES interface implemented by this effect
- effect_uuid_t uuid; // UUID for this particular implementation
- uint16_t apiVersion; // Version of the effect API implemented: matches EFFECT_API_VERSION
- uint32_t flags; // effect engine capabilities/requirements flags (see below)
- uint16_t cpuLoad; // CPU load indication (see below)
- uint16_t memoryUsage; // Data Memory usage (see below)
- char name[EFFECT_STRING_LEN_MAX]; // human readable effect name
- char implementor[EFFECT_STRING_LEN_MAX]; // human readable effect implementor name
-} effect_descriptor_t;
-
-// CPU load and memory usage indication: each effect implementation must provide an indication of
-// its CPU and memory usage for the audio effect framework to limit the number of effects
-// instantiated at a given time on a given platform.
-// The CPU load is expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS.
-// The memory usage is expressed in KB and includes only dynamically allocated memory
-
-// Definitions for flags field of effect descriptor.
-// +---------------------------+-----------+-----------------------------------
-// | description | bits | values
-// +---------------------------+-----------+-----------------------------------
-// | connection mode | 0..1 | 0 insert: after track process
-// | | | 1 auxiliary: connect to track auxiliary
-// | | | output and use send level
-// | | | 2 replace: replaces track process function;
-// | | | must implement SRC, volume and mono to stereo.
-// | | | 3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | insertion preference | 2..4 | 0 none
-// | | | 1 first of the chain
-// | | | 2 last of the chain
-// | | | 3 exclusive (only effect in the insert chain)
-// | | | 4..7 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Volume management | 5..6 | 0 none
-// | | | 1 implements volume control
-// | | | 2 requires volume indication
-// | | | 3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Device indication | 7..8 | 0 none
-// | | | 1 requires device updates
-// | | | 2..3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Sample input mode | 9..10 | 0 direct: process() function or EFFECT_CMD_CONFIGURE
-// | | | command must specify a buffer descriptor
-// | | | 1 provider: process() function uses the
-// | | | bufferProvider indicated by the
-// | | | EFFECT_CMD_CONFIGURE command to request input.
-// | | | buffers.
-// | | | 2 both: both input modes are supported
-// | | | 3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Sample output mode | 11..12 | 0 direct: process() function or EFFECT_CMD_CONFIGURE
-// | | | command must specify a buffer descriptor
-// | | | 1 provider: process() function uses the
-// | | | bufferProvider indicated by the
-// | | | EFFECT_CMD_CONFIGURE command to request output
-// | | | buffers.
-// | | | 2 both: both output modes are supported
-// | | | 3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Hardware acceleration | 13..15 | 0 No hardware acceleration
-// | | | 1 non tunneled hw acceleration: the process() function
-// | | | reads the samples, send them to HW accelerated
-// | | | effect processor, reads back the processed samples
-// | | | and returns them to the output buffer.
-// | | | 2 tunneled hw acceleration: the process() function is
-// | | | transparent. The effect interface is only used to
-// | | | control the effect engine. This mode is relevant for
-// | | | global effects actually applied by the audio
-// | | | hardware on the output stream.
-// +---------------------------+-----------+-----------------------------------
-// | Audio Mode indication | 16..17 | 0 none
-// | | | 1 requires audio mode updates
-// | | | 2..3 reserved
-// +---------------------------+-----------+-----------------------------------
-
-// Insert mode
-#define EFFECT_FLAG_TYPE_MASK 0x00000003
-#define EFFECT_FLAG_TYPE_INSERT 0x00000000
-#define EFFECT_FLAG_TYPE_AUXILIARY 0x00000001
-#define EFFECT_FLAG_TYPE_REPLACE 0x00000002
-
-// Insert preference
-#define EFFECT_FLAG_INSERT_MASK 0x0000001C
-#define EFFECT_FLAG_INSERT_ANY 0x00000000
-#define EFFECT_FLAG_INSERT_FIRST 0x00000004
-#define EFFECT_FLAG_INSERT_LAST 0x00000008
-#define EFFECT_FLAG_INSERT_EXCLUSIVE 0x0000000C
-
-
-// Volume control
-#define EFFECT_FLAG_VOLUME_MASK 0x00000060
-#define EFFECT_FLAG_VOLUME_CTRL 0x00000020
-#define EFFECT_FLAG_VOLUME_IND 0x00000040
-#define EFFECT_FLAG_VOLUME_NONE 0x00000000
-
-// Device indication
-#define EFFECT_FLAG_DEVICE_MASK 0x00000180
-#define EFFECT_FLAG_DEVICE_IND 0x00000080
-#define EFFECT_FLAG_DEVICE_NONE 0x00000000
-
-// Sample input modes
-#define EFFECT_FLAG_INPUT_MASK 0x00000600
-#define EFFECT_FLAG_INPUT_DIRECT 0x00000000
-#define EFFECT_FLAG_INPUT_PROVIDER 0x00000200
-#define EFFECT_FLAG_INPUT_BOTH 0x00000400
-
-// Sample output modes
-#define EFFECT_FLAG_OUTPUT_MASK 0x00001800
-#define EFFECT_FLAG_OUTPUT_DIRECT 0x00000000
-#define EFFECT_FLAG_OUTPUT_PROVIDER 0x00000800
-#define EFFECT_FLAG_OUTPUT_BOTH 0x00001000
-
-// Hardware acceleration mode
-#define EFFECT_FLAG_HW_ACC_MASK 0x00006000
-#define EFFECT_FLAG_HW_ACC_SIMPLE 0x00002000
-#define EFFECT_FLAG_HW_ACC_TUNNEL 0x00004000
-
-// Audio mode indication
-#define EFFECT_FLAG_AUDIO_MODE_MASK 0x00018000
-#define EFFECT_FLAG_AUDIO_MODE_IND 0x00008000
-#define EFFECT_FLAG_AUDIO_MODE_NONE 0x00000000
-
-// Forward definition of type audio_buffer_t
-typedef struct audio_buffer_s audio_buffer_t;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: process
-//
-// Description: Effect process function. Takes input samples as specified
-// (count and location) in input buffer descriptor and output processed
-// samples as specified in output buffer descriptor. If the buffer descriptor
-// is not specified the function must use either the buffer or the
-// buffer provider function installed by the EFFECT_CMD_CONFIGURE command.
-// The effect framework will call the process() function after the EFFECT_CMD_ENABLE
-// command is received and until the EFFECT_CMD_DISABLE is received. When the engine
-// receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully
-// and when done indicate that it is OK to stop calling the process() function by
-// returning the -ENODATA status.
-//
-// NOTE: the process() function implementation should be "real-time safe" that is
-// it should not perform blocking calls: malloc/free, sleep, read/write/open/close,
-// pthread_cond_wait/pthread_mutex_lock...
-//
-// Input:
-// effect_interface_t: handle to the effect interface this function
-// is called on.
-// inBuffer: buffer descriptor indicating where to read samples to process.
-// If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command.
-//
-// inBuffer: buffer descriptor indicating where to write processed samples.
-// If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command.
-//
-// Output:
-// returned value: 0 successful operation
-// -ENODATA the engine has finished the disable phase and the framework
-// can stop calling process()
-// -EINVAL invalid interface handle or
-// invalid input/output buffer description
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_process_t)(effect_interface_t self,
- audio_buffer_t *inBuffer,
- audio_buffer_t *outBuffer);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: command
-//
-// Description: Send a command and receive a response to/from effect engine.
-//
-// Input:
-// effect_interface_t: handle to the effect interface this function
-// is called on.
-// cmdCode: command code: the command can be a standardized command defined in
-// effect_command_e (see below) or a proprietary command.
-// cmdSize: size of command in bytes
-// pCmdData: pointer to command data
-// pReplyData: pointer to reply data
-//
-// Input/Output:
-// replySize: maximum size of reply data as input
-// actual size of reply data as output
-//
-// Output:
-// returned value: 0 successful operation
-// -EINVAL invalid interface handle or
-// invalid command/reply size or format according to command code
-// The return code should be restricted to indicate problems related to the this
-// API specification. Status related to the execution of a particular command should be
-// indicated as part of the reply field.
-//
-// *pReplyData updated with command response
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_command_t)(effect_interface_t self,
- uint32_t cmdCode,
- uint32_t cmdSize,
- void *pCmdData,
- uint32_t *replySize,
- void *pReplyData);
-
-
-// Effect control interface definition
-struct effect_interface_s {
- effect_process_t process;
- effect_command_t command;
-};
-
-
-//
-//--- Standardized command codes for command() function
-//
-enum effect_command_e {
- EFFECT_CMD_INIT, // initialize effect engine
- EFFECT_CMD_CONFIGURE, // configure effect engine (see effect_config_t)
- EFFECT_CMD_RESET, // reset effect engine
- EFFECT_CMD_ENABLE, // enable effect process
- EFFECT_CMD_DISABLE, // disable effect process
- EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t)
- EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred
- EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred
- EFFECT_CMD_GET_PARAM, // get parameter
- EFFECT_CMD_SET_DEVICE, // set audio device (see audio_device_e)
- EFFECT_CMD_SET_VOLUME, // set volume
- EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...)
- EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
-};
-
-//==================================================================================================
-// command: EFFECT_CMD_INIT
-//--------------------------------------------------------------------------------------------------
-// description:
-// Initialize effect engine: All configurations return to default
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_CONFIGURE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Apply new audio parameters configurations for input and output buffers
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(effect_config_t)
-// data: effect_config_t
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_RESET
-//--------------------------------------------------------------------------------------------------
-// description:
-// Reset the effect engine. Keep configuration but resets state and buffer content
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: 0
-// data: N/A
-//==================================================================================================
-// command: EFFECT_CMD_ENABLE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Enable the process. Called by the framework before the first call to process()
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_DISABLE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Disable the process. Called by the framework after the last call to process()
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_SET_PARAM
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set a parameter and apply it immediately
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(effect_param_t) + size of param and value
-// data: effect_param_t + param + value. See effect_param_t definition below for value offset
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_SET_PARAM_DEFERRED
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set a parameter but apply it only when receiving EFFECT_CMD_SET_PARAM_COMMIT command
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(effect_param_t) + size of param and value
-// data: effect_param_t + param + value. See effect_param_t definition below for value offset
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: 0
-// data: N/A
-//==================================================================================================
-// command: EFFECT_CMD_SET_PARAM_COMMIT
-//--------------------------------------------------------------------------------------------------
-// description:
-// Apply all previously received EFFECT_CMD_SET_PARAM_DEFERRED commands
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_GET_PARAM
-//--------------------------------------------------------------------------------------------------
-// description:
-// Get a parameter value
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(effect_param_t) + size of param
-// data: effect_param_t + param
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(effect_param_t) + size of param and value
-// data: effect_param_t + param + value. See effect_param_t definition below for value offset
-//==================================================================================================
-// command: EFFECT_CMD_SET_DEVICE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set the rendering device the audio output path is connected to. See audio_device_e for device
-// values.
-// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this
-// command when the device changes
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(uint32_t)
-// data: audio_device_e
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: 0
-// data: N/A
-//==================================================================================================
-// command: EFFECT_CMD_SET_VOLUME
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set and get volume. Used by audio framework to delegate volume control to effect engine.
-// The effect implementation must set EFFECT_FLAG_VOLUME_IND or EFFECT_FLAG_VOLUME_CTRL flag in
-// its descriptor to receive this command before every call to process() function
-// If EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return
-// the volume that should be applied before the effect is processed. The overall volume (the volume
-// actually applied by the effect engine multiplied by the returned value) should match the value
-// indicated in the command.
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: n * sizeof(uint32_t)
-// data: volume for each channel defined in effect_config_t for output buffer expressed in
-// 8.24 fixed point format
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: n * sizeof(uint32_t) / 0
-// data: - if EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor:
-// volume for each channel defined in effect_config_t for output buffer expressed in
-// 8.24 fixed point format
-// - if EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor:
-// N/A
-// It is legal to receive a null pointer as pReplyData in which case the effect framework has
-// delegated volume control to another effect
-//==================================================================================================
-// command: EFFECT_CMD_SET_AUDIO_MODE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set the audio mode. The effect implementation must set EFFECT_FLAG_AUDIO_MODE_IND flag in its
-// descriptor to receive this command when the audio mode changes.
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(uint32_t)
-// data: audio_mode_e
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: 0
-// data: N/A
-//==================================================================================================
-// command: EFFECT_CMD_FIRST_PROPRIETARY
-//--------------------------------------------------------------------------------------------------
-// description:
-// All proprietary effect commands must use command codes above this value. The size and format of
-// command and response fields is free in this case
-//==================================================================================================
-
-
-// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t
-// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with
-// regard to the channel mask definition in audio_channels_e e.g :
-// Stereo: left, right
-// 5 point 1: front left, front right, front center, low frequency, back left, back right
-// The buffer size is expressed in frame count, a frame being composed of samples for all
-// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by
-// definition
-struct audio_buffer_s {
- size_t frameCount; // number of frames in buffer
- union {
- void* raw; // raw pointer to start of buffer
- int32_t* s32; // pointer to signed 32 bit data at start of buffer
- int16_t* s16; // pointer to signed 16 bit data at start of buffer
- uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer
- };
-};
-
-// The buffer_provider_s structure contains functions that can be used
-// by the effect engine process() function to query and release input
-// or output audio buffer.
-// The getBuffer() function is called to retrieve a buffer where data
-// should read from or written to by process() function.
-// The releaseBuffer() function MUST be called when the buffer retrieved
-// with getBuffer() is not needed anymore.
-// The process function should use the buffer provider mechanism to retrieve
-// input or output buffer if the inBuffer or outBuffer passed as argument is NULL
-// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_CONFIGURE
-// command did not specify an audio buffer.
-
-typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer);
-
-typedef struct buffer_provider_s {
- buffer_function_t getBuffer; // retrieve next buffer
- buffer_function_t releaseBuffer; // release used buffer
- void *cookie; // for use by client of buffer provider functions
-} buffer_provider_t;
-
-
-// The buffer_config_s structure specifies the input or output audio format
-// to be used by the effect engine. It is part of the effect_config_t
-// structure that defines both input and output buffer configurations and is
-// passed by the EFFECT_CMD_CONFIGURE command.
-typedef struct buffer_config_s {
- audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly
- uint32_t samplingRate; // sampling rate
- uint32_t channels; // channel mask (see audio_channels_e)
- buffer_provider_t bufferProvider; // buffer provider
- uint8_t format; // Audio format (see audio_format_e)
- uint8_t accessMode; // read/write or accumulate in buffer (effect_buffer_access_e)
- uint16_t mask; // indicates which of the above fields is valid
-} buffer_config_t;
-
-// Sample format
-enum audio_format_e {
- SAMPLE_FORMAT_PCM_S15, // PCM signed 16 bits
- SAMPLE_FORMAT_PCM_U8, // PCM unsigned 8 bits
- SAMPLE_FORMAT_PCM_S7_24, // PCM signed 7.24 fixed point representation
- SAMPLE_FORMAT_OTHER // other format (e.g. compressed)
-};
-
-// Channel mask
-enum audio_channels_e {
- CHANNEL_FRONT_LEFT = 0x1, // front left channel
- CHANNEL_FRONT_RIGHT = 0x2, // front right channel
- CHANNEL_FRONT_CENTER = 0x4, // front center channel
- CHANNEL_LOW_FREQUENCY = 0x8, // low frequency channel
- CHANNEL_BACK_LEFT = 0x10, // back left channel
- CHANNEL_BACK_RIGHT = 0x20, // back right channel
- CHANNEL_FRONT_LEFT_OF_CENTER = 0x40, // front left of center channel
- CHANNEL_FRONT_RIGHT_OF_CENTER = 0x80, // front right of center channel
- CHANNEL_BACK_CENTER = 0x100, // back center channel
- CHANNEL_MONO = CHANNEL_FRONT_LEFT,
- CHANNEL_STEREO = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT),
- CHANNEL_QUAD = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
- CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT),
- CHANNEL_SURROUND = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
- CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER),
- CHANNEL_5POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
- CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT),
- CHANNEL_7POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
- CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT |
- CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER),
-};
-
-// Render device
-enum audio_device_e {
- DEVICE_EARPIECE = 0x1, // earpiece
- DEVICE_SPEAKER = 0x2, // speaker
- DEVICE_WIRED_HEADSET = 0x4, // wired headset, with microphone
- DEVICE_WIRED_HEADPHONE = 0x8, // wired headphone, without microphone
- DEVICE_BLUETOOTH_SCO = 0x10, // generic bluetooth SCO
- DEVICE_BLUETOOTH_SCO_HEADSET = 0x20, // bluetooth SCO headset
- DEVICE_BLUETOOTH_SCO_CARKIT = 0x40, // bluetooth SCO car kit
- DEVICE_BLUETOOTH_A2DP = 0x80, // generic bluetooth A2DP
- DEVICE_BLUETOOTH_A2DP_HEADPHONES = 0x100, // bluetooth A2DP headphones
- DEVICE_BLUETOOTH_A2DP_SPEAKER = 0x200, // bluetooth A2DP speakers
- DEVICE_AUX_DIGITAL = 0x400, // digital output
- DEVICE_EXTERNAL_SPEAKER = 0x800 // external speaker (stereo and High quality)
-};
-
-#if ANDROID_VERSION < 17
-// Audio mode
-enum audio_mode_e {
- AUDIO_MODE_NORMAL, // device idle
- AUDIO_MODE_RINGTONE, // device ringing
- AUDIO_MODE_IN_CALL // audio call connected (VoIP or telephony)
-};
-#endif
-
-// Values for "accessMode" field of buffer_config_t:
-// overwrite, read only, accumulate (read/modify/write)
-enum effect_buffer_access_e {
- EFFECT_BUFFER_ACCESS_WRITE,
- EFFECT_BUFFER_ACCESS_READ,
- EFFECT_BUFFER_ACCESS_ACCUMULATE
-
-};
-
-// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field
-// in buffer_config_t must be taken into account when executing the EFFECT_CMD_CONFIGURE command
-#define EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account
-#define EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account
-#define EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account
-#define EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account
-#define EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account
-#define EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account
-#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \
- EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \
- EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER)
-
-
-// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_CONFIGURE
-// command to configure audio parameters and buffers for effect engine input and output.
-typedef struct effect_config_s {
- buffer_config_t inputCfg;
- buffer_config_t outputCfg;;
-} effect_config_t;
-
-
-// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM
-// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command.
-// psize and vsize represent the actual size of parameter and value.
-//
-// NOTE: the start of value field inside the data field is always on a 32 bit boundary:
-//
-// +-----------+
-// | status | sizeof(int)
-// +-----------+
-// | psize | sizeof(int)
-// +-----------+
-// | vsize | sizeof(int)
-// +-----------+
-// | | | |
-// ~ parameter ~ > psize |
-// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int)
-// +-----------+ |
-// | padding | |
-// +-----------+
-// | | |
-// ~ value ~ > vsize
-// | | |
-// +-----------+
-
-typedef struct effect_param_s {
- int32_t status; // Transaction status (unused for command, used for reply)
- uint32_t psize; // Parameter size
- uint32_t vsize; // Value size
- char data[]; // Start of Parameter + Value data
-} effect_param_t;
-
-
-/////////////////////////////////////////////////
-// Effect library interface
-/////////////////////////////////////////////////
-
-// An effect library is required to implement and expose the following functions
-// to enable effect enumeration and instantiation. The name of these functions must be as
-// specified here as the effect framework will get the function address with dlsym():
-//
-// - effect_QueryNumberEffects_t EffectQueryNumberEffects;
-// - effect_QueryEffect_t EffectQueryEffect;
-// - effect_CreateEffect_t EffectCreate;
-// - effect_ReleaseEffect_t EffectRelease;
-
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: EffectQueryNumberEffects
-//
-// Description: Returns the number of different effects exposed by the
-// library. Each effect must have a unique effect uuid (see
-// effect_descriptor_t). This function together with EffectQueryEffect()
-// is used to enumerate all effects present in the library.
-//
-// Input/Output:
-// pNumEffects: address where the number of effects should be returned.
-//
-// Output:
-// returned value: 0 successful operation.
-// -ENODEV library failed to initialize
-// -EINVAL invalid pNumEffects
-// *pNumEffects: updated with number of effects in library
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_QueryNumberEffects_t)(uint32_t *pNumEffects);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: EffectQueryEffect
-//
-// Description: Returns the descriptor of the effect engine which index is
-// given as first argument.
-// See effect_descriptor_t for details on effect descriptors.
-// This function together with EffectQueryNumberEffects() is used to enumerate all
-// effects present in the library. The enumeration sequence is:
-// EffectQueryNumberEffects(&num_effects);
-// for (i = 0; i < num_effects; i++)
-// EffectQueryEffect(i,...);
-//
-// Input/Output:
-// index: index of the effect
-// pDescriptor: address where to return the effect descriptor.
-//
-// Output:
-// returned value: 0 successful operation.
-// -ENODEV library failed to initialize
-// -EINVAL invalid pDescriptor or index
-// -ENOSYS effect list has changed since last execution of
-// EffectQueryNumberEffects()
-// -ENOENT no more effect available
-// *pDescriptor: updated with the effect descriptor.
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_QueryEffect_t)(uint32_t index,
- effect_descriptor_t *pDescriptor);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: EffectCreate
-//
-// Description: Creates an effect engine of the specified type and returns an
-// effect control interface on this engine. The function will allocate the
-// resources for an instance of the requested effect engine and return
-// a handle on the effect control interface.
-//
-// Input:
-// uuid: pointer to the effect uuid.
-// sessionId: audio session to which this effect instance will be attached. All effects
-// created with the same session ID are connected in series and process the same signal
-// stream. Knowing that two effects are part of the same effect chain can help the
-// library implement some kind of optimizations.
-// ioId: identifies the output or input stream this effect is directed to at audio HAL.
-// For future use especially with tunneled HW accelerated effects
-//
-// Input/Output:
-// pInterface: address where to return the effect interface.
-//
-// Output:
-// returned value: 0 successful operation.
-// -ENODEV library failed to initialize
-// -EINVAL invalid pEffectUuid or pInterface
-// -ENOENT no effect with this uuid found
-// *pInterface: updated with the effect interface handle.
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_CreateEffect_t)(effect_uuid_t *uuid,
- int32_t sessionId,
- int32_t ioId,
- effect_interface_t *pInterface);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: EffectRelease
-//
-// Description: Releases the effect engine whose handle is given as argument.
-// All resources allocated to this particular instance of the effect are
-// released.
-//
-// Input:
-// interface: handle on the effect interface to be released.
-//
-// Output:
-// returned value: 0 successful operation.
-// -ENODEV library failed to initialize
-// -EINVAL invalid interface handle
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_ReleaseEffect_t)(effect_interface_t interface);
-
-
-#if __cplusplus
-} // extern "C"
-#endif
-
-
-#endif /*ANDROID_EFFECTAPI_H_*/
diff --git a/dom/system/gonk/android_audio/IAudioFlinger.h b/dom/system/gonk/android_audio/IAudioFlinger.h
deleted file mode 100644
index b10d3ab93..000000000
--- a/dom/system/gonk/android_audio/IAudioFlinger.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IAUDIOFLINGER_H
-#define ANDROID_IAUDIOFLINGER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include "IAudioTrack.h"
-#include "IAudioRecord.h"
-#include "IAudioFlingerClient.h"
-#include "EffectApi.h"
-#include "IEffect.h"
-#include "IEffectClient.h"
-#include <utils/String8.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IAudioFlinger : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioFlinger);
-
- /* create an audio track and registers it with AudioFlinger.
- * return null if the track cannot be created.
- */
- virtual sp<IAudioTrack> createTrack(
- pid_t pid,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- const sp<IMemory>& sharedBuffer,
- int output,
- int *sessionId,
- status_t *status) = 0;
-
- virtual sp<IAudioRecord> openRecord(
- pid_t pid,
- int input,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- int *sessionId,
- status_t *status) = 0;
-
- /* query the audio hardware state. This state never changes,
- * and therefore can be cached.
- */
- virtual uint32_t sampleRate(int output) const = 0;
- virtual int channelCount(int output) const = 0;
- virtual int format(int output) const = 0;
- virtual size_t frameCount(int output) const = 0;
- virtual uint32_t latency(int output) const = 0;
-
- /* set/get the audio hardware state. This will probably be used by
- * the preference panel, mostly.
- */
- virtual status_t setMasterVolume(float value) = 0;
- virtual status_t setMasterMute(bool muted) = 0;
-
- virtual float masterVolume() const = 0;
- virtual bool masterMute() const = 0;
-
- /* set/get stream type state. This will probably be used by
- * the preference panel, mostly.
- */
- virtual status_t setStreamVolume(int stream, float value, int output) = 0;
- virtual status_t setStreamMute(int stream, bool muted) = 0;
-
- virtual float streamVolume(int stream, int output) const = 0;
- virtual bool streamMute(int stream) const = 0;
-
- // set audio mode
- virtual status_t setMode(int mode) = 0;
-
- // mic mute/state
- virtual status_t setMicMute(bool state) = 0;
- virtual bool getMicMute() const = 0;
-
- // is any track active on this stream?
- virtual bool isStreamActive(int stream) const = 0;
-
- virtual status_t setParameters(int ioHandle, const String8& keyValuePairs) = 0;
- virtual String8 getParameters(int ioHandle, const String8& keys) = 0;
-
- // register a current process for audio output change notifications
- virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
-
- // retrieve the audio recording buffer size
- virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0;
-
- virtual int openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- uint32_t flags) = 0;
- virtual int openDuplicateOutput(int output1, int output2) = 0;
- virtual status_t closeOutput(int output) = 0;
- virtual status_t suspendOutput(int output) = 0;
- virtual status_t restoreOutput(int output) = 0;
-
- virtual int openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t acoustics) = 0;
- virtual status_t closeInput(int input) = 0;
-
- virtual status_t setStreamOutput(uint32_t stream, int output) = 0;
-
- virtual status_t setVoiceVolume(float volume) = 0;
-
- virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) = 0;
-
- virtual unsigned int getInputFramesLost(int ioHandle) = 0;
-
- virtual int newAudioSessionId() = 0;
-
- virtual status_t loadEffectLibrary(const char *libPath, int *handle) = 0;
-
- virtual status_t unloadEffectLibrary(int handle) = 0;
-
- virtual status_t queryNumberEffects(uint32_t *numEffects) = 0;
-
- virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) = 0;
-
- virtual status_t getEffectDescriptor(effect_uuid_t *pEffectUUID, effect_descriptor_t *pDescriptor) = 0;
-
- virtual sp<IEffect> createEffect(pid_t pid,
- effect_descriptor_t *pDesc,
- const sp<IEffectClient>& client,
- int32_t priority,
- int output,
- int sessionId,
- status_t *status,
- int *id,
- int *enabled) = 0;
-
- virtual status_t moveEffects(int session, int srcOutput, int dstOutput) = 0;
-};
-
-
-// ----------------------------------------------------------------------------
-
-class BnAudioFlinger : public BnInterface<IAudioFlinger>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IAUDIOFLINGER_H
diff --git a/dom/system/gonk/android_audio/IAudioFlingerClient.h b/dom/system/gonk/android_audio/IAudioFlingerClient.h
deleted file mode 100644
index aa0cdcff1..000000000
--- a/dom/system/gonk/android_audio/IAudioFlingerClient.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IAUDIOFLINGERCLIENT_H
-#define ANDROID_IAUDIOFLINGERCLIENT_H
-
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <utils/KeyedVector.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IAudioFlingerClient : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioFlingerClient);
-
- // Notifies a change of audio input/output configuration.
- virtual void ioConfigChanged(int event, int ioHandle, void *param2) = 0;
-
-};
-
-
-// ----------------------------------------------------------------------------
-
-class BnAudioFlingerClient : public BnInterface<IAudioFlingerClient>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IAUDIOFLINGERCLIENT_H
diff --git a/dom/system/gonk/android_audio/IAudioRecord.h b/dom/system/gonk/android_audio/IAudioRecord.h
deleted file mode 100644
index 46735def2..000000000
--- a/dom/system/gonk/android_audio/IAudioRecord.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef IAUDIORECORD_H_
-#define IAUDIORECORD_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IAudioRecord : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioRecord);
-
- /* After it's created the track is not active. Call start() to
- * make it active. If set, the callback will start being called.
- */
- virtual status_t start() = 0;
-
- /* Stop a track. If set, the callback will cease being called and
- * obtainBuffer will return an error. Buffers that are already released
- * will be processed, unless flush() is called.
- */
- virtual void stop() = 0;
-
- /* get this tracks control block */
- virtual sp<IMemory> getCblk() const = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnAudioRecord : public BnInterface<IAudioRecord>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif /*IAUDIORECORD_H_*/
diff --git a/dom/system/gonk/android_audio/IAudioTrack.h b/dom/system/gonk/android_audio/IAudioTrack.h
deleted file mode 100644
index 47d530be5..000000000
--- a/dom/system/gonk/android_audio/IAudioTrack.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IAUDIOTRACK_H
-#define ANDROID_IAUDIOTRACK_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IAudioTrack : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioTrack);
-
- /* After it's created the track is not active. Call start() to
- * make it active. If set, the callback will start being called.
- */
- virtual status_t start() = 0;
-
- /* Stop a track. If set, the callback will cease being called and
- * obtainBuffer will return an error. Buffers that are already released
- * will be processed, unless flush() is called.
- */
- virtual void stop() = 0;
-
- /* flush a stopped track. All pending buffers are discarded.
- * This function has no effect if the track is not stoped.
- */
- virtual void flush() = 0;
-
- /* mute or unmutes this track.
- * While mutted, the callback, if set, is still called.
- */
- virtual void mute(bool) = 0;
-
- /* Pause a track. If set, the callback will cease being called and
- * obtainBuffer will return an error. Buffers that are already released
- * will be processed, unless flush() is called.
- */
- virtual void pause() = 0;
-
- /* Attach track auxiliary output to specified effect. Use effectId = 0
- * to detach track from effect.
- */
- virtual status_t attachAuxEffect(int effectId) = 0;
-
- /* get this tracks control block */
- virtual sp<IMemory> getCblk() const = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnAudioTrack : public BnInterface<IAudioTrack>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IAUDIOTRACK_H
diff --git a/dom/system/gonk/android_audio/IEffect.h b/dom/system/gonk/android_audio/IEffect.h
deleted file mode 100644
index ff04869e0..000000000
--- a/dom/system/gonk/android_audio/IEffect.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IEFFECT_H
-#define ANDROID_IEFFECT_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-
-namespace android {
-
-class IEffect: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(Effect);
-
- virtual status_t enable() = 0;
-
- virtual status_t disable() = 0;
-
- virtual status_t command(uint32_t cmdCode,
- uint32_t cmdSize,
- void *pCmdData,
- uint32_t *pReplySize,
- void *pReplyData) = 0;
-
- virtual void disconnect() = 0;
-
- virtual sp<IMemory> getCblk() const = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnEffect: public BnInterface<IEffect>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IEFFECT_H
diff --git a/dom/system/gonk/android_audio/IEffectClient.h b/dom/system/gonk/android_audio/IEffectClient.h
deleted file mode 100644
index 2f78c98f1..000000000
--- a/dom/system/gonk/android_audio/IEffectClient.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IEFFECTCLIENT_H
-#define ANDROID_IEFFECTCLIENT_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-
-namespace android {
-
-class IEffectClient: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(EffectClient);
-
- virtual void controlStatusChanged(bool controlGranted) = 0;
- virtual void enableStatusChanged(bool enabled) = 0;
- virtual void commandExecuted(uint32_t cmdCode,
- uint32_t cmdSize,
- void *pCmdData,
- uint32_t replySize,
- void *pReplyData) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnEffectClient: public BnInterface<IEffectClient>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IEFFECTCLIENT_H
diff --git a/dom/system/gonk/moz.build b/dom/system/gonk/moz.build
deleted file mode 100644
index 229baaab4..000000000
--- a/dom/system/gonk/moz.build
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# Copyright 2013 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-XPIDL_SOURCES += [
- 'nsIAudioManager.idl',
- 'nsINetworkInterface.idl',
- 'nsINetworkInterfaceListService.idl',
- 'nsINetworkManager.idl',
- 'nsINetworkService.idl',
- 'nsINetworkWorker.idl',
- 'nsISystemWorkerManager.idl',
- 'nsITetheringService.idl',
- 'nsIVolume.idl',
- 'nsIVolumeMountLock.idl',
- 'nsIVolumeService.idl',
- 'nsIVolumeStat.idl',
- 'nsIWorkerHolder.idl',
-]
-
-XPIDL_MODULE = 'dom_system_gonk'
-
-EXPORTS += [
- 'GeolocationUtil.h',
- 'GonkGPSGeolocationProvider.h',
- 'nsVolume.h',
- 'nsVolumeService.h',
- 'SystemProperty.h',
-]
-UNIFIED_SOURCES += [
- 'AudioChannelManager.cpp',
- 'AudioManager.cpp',
- 'AutoMounter.cpp',
- 'AutoMounterSetting.cpp',
- 'GeolocationUtil.cpp',
- 'GonkGPSGeolocationProvider.cpp',
- 'MozMtpDatabase.cpp',
- 'MozMtpServer.cpp',
- 'MozMtpStorage.cpp',
- 'NetIdManager.cpp',
- 'NetworkUtils.cpp',
- 'NetworkWorker.cpp',
- 'nsVolume.cpp',
- 'nsVolumeMountLock.cpp',
- 'nsVolumeService.cpp',
- 'nsVolumeStat.cpp',
- 'OpenFileFinder.cpp',
- 'SystemProperty.cpp',
- 'SystemWorkerManager.cpp',
- 'TimeZoneSettingObserver.cpp',
- 'Volume.cpp',
- 'VolumeCommand.cpp',
- 'VolumeManager.cpp',
- 'VolumeServiceIOThread.cpp',
- 'VolumeServiceTest.cpp',
-]
-
-if CONFIG['ANDROID_VERSION'] >= '17':
- LOCAL_INCLUDES += ['%' + '%s/frameworks/av/media/mtp' % CONFIG['ANDROID_SOURCE']]
-else:
- LOCAL_INCLUDES += ['%' + '%s/frameworks/base/media/mtp' % CONFIG['ANDROID_SOURCE']]
-
-if CONFIG['ENABLE_TESTS']:
- XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']
-
-EXTRA_COMPONENTS += [
- 'NetworkInterfaceListService.js',
- 'NetworkInterfaceListService.manifest',
- 'NetworkManager.js',
- 'NetworkManager.manifest',
- 'NetworkService.js',
- 'NetworkService.manifest',
- 'TetheringService.js',
- 'TetheringService.manifest',
-]
-EXTRA_JS_MODULES += [
- 'systemlibs.js',
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-DEFINES['HAVE_ANDROID_OS'] = True
-
-LOCAL_INCLUDES += [
- '/dom/base',
- '/dom/bluetooth/common',
- '/dom/geolocation',
- '/dom/wifi',
-]
-
-FINAL_LIBRARY = 'xul'
-
-FINAL_TARGET_FILES.modules.workers += [
- 'worker_buf.js',
-]
diff --git a/dom/system/gonk/mozstumbler/MozStumbler.cpp b/dom/system/gonk/mozstumbler/MozStumbler.cpp
deleted file mode 100644
index 61e09e705..000000000
--- a/dom/system/gonk/mozstumbler/MozStumbler.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MozStumbler.h"
-#include "nsDataHashtable.h"
-#include "nsGeoPosition.h"
-#include "nsNetCID.h"
-#include "nsPrintfCString.h"
-#include "StumblerLogging.h"
-#include "WriteStumbleOnThread.h"
-#include "../GeolocationUtil.h"
-
-#include "nsIInterfaceRequestor.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsIMobileConnectionInfo.h"
-#include "nsIMobileConnectionService.h"
-#include "nsIMobileCellInfo.h"
-#include "nsIMobileNetworkInfo.h"
-#include "nsINetworkInterface.h"
-#include "nsIRadioInterfaceLayer.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-
-NS_IMPL_ISUPPORTS(StumblerInfo, nsICellInfoListCallback, nsIWifiScanResultsReady)
-
-class RequestCellInfoEvent : public Runnable {
-public:
- RequestCellInfoEvent(StumblerInfo *callback)
- : mRequestCallback(callback)
- {}
-
- NS_IMETHOD Run() override {
- MOZ_ASSERT(NS_IsMainThread());
- // Get Cell Info
- nsCOMPtr<nsIMobileConnectionService> service =
- do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID);
-
- if (!service) {
- STUMBLER_ERR("Stumbler-can not get nsIMobileConnectionService \n");
- return NS_OK;
- }
- nsCOMPtr<nsIMobileConnection> connection;
- uint32_t numberOfRilServices = 1, cellInfoNum = 0;
-
- service->GetNumItems(&numberOfRilServices);
- for (uint32_t rilNum = 0; rilNum < numberOfRilServices; rilNum++) {
- service->GetItemByServiceId(rilNum /* Client Id */, getter_AddRefs(connection));
- if (!connection) {
- STUMBLER_ERR("Stumbler-can not get nsIMobileConnection by ServiceId %d \n", rilNum);
- } else {
- cellInfoNum++;
- connection->GetCellInfoList(mRequestCallback);
- }
- }
- mRequestCallback->SetCellInfoResponsesExpected(cellInfoNum);
-
- // Get Wifi AP Info
- nsCOMPtr<nsIInterfaceRequestor> ir = do_GetService("@mozilla.org/telephony/system-worker-manager;1");
- nsCOMPtr<nsIWifi> wifi = do_GetInterface(ir);
- if (!wifi) {
- mRequestCallback->SetWifiInfoResponseReceived();
- STUMBLER_ERR("Stumbler-can not get nsIWifi interface\n");
- return NS_OK;
- }
- wifi->GetWifiScanResults(mRequestCallback);
- return NS_OK;
- }
-private:
- RefPtr<StumblerInfo> mRequestCallback;
-};
-
-void
-MozStumble(nsGeoPosition* position)
-{
- if (WriteStumbleOnThread::IsFileWaitingForUpload()) {
- nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
- MOZ_ASSERT(target);
- // Knowing that file is waiting to upload, and no collection will take place,
- // just trigger the thread with an empty string.
- nsCOMPtr<nsIRunnable> event = new WriteStumbleOnThread(EmptyCString());
- target->Dispatch(event, NS_DISPATCH_NORMAL);
- return;
- }
-
- nsCOMPtr<nsIDOMGeoPositionCoords> coords;
- position->GetCoords(getter_AddRefs(coords));
- if (!coords) {
- return;
- }
-
- double latitude, longitude;
- coords->GetLatitude(&latitude);
- coords->GetLongitude(&longitude);
-
- const double kMinChangeInMeters = 30;
- static int64_t lastTime_ms = 0;
- static double sLastLat = 0;
- static double sLastLon = 0;
- double delta = -1.0;
- int64_t timediff = (PR_Now() / PR_USEC_PER_MSEC) - lastTime_ms;
-
- if (0 != sLastLon || 0 != sLastLat) {
- delta = CalculateDeltaInMeter(latitude, longitude, sLastLat, sLastLon);
- }
- STUMBLER_DBG("Stumbler-Location. [%f , %f] time_diff:%lld, delta : %f\n",
- longitude, latitude, timediff, delta);
-
- // Consecutive GPS locations must be 30 meters and 3 seconds apart
- if (lastTime_ms == 0 || ((timediff >= STUMBLE_INTERVAL_MS) && (delta > kMinChangeInMeters))){
- lastTime_ms = (PR_Now() / PR_USEC_PER_MSEC);
- sLastLat = latitude;
- sLastLon = longitude;
- RefPtr<StumblerInfo> requestCallback = new StumblerInfo(position);
- RefPtr<RequestCellInfoEvent> runnable = new RequestCellInfoEvent(requestCallback);
- NS_DispatchToMainThread(runnable);
- } else {
- STUMBLER_DBG("Stumbler-GPS locations less than 30 meters and 3 seconds. Ignore!\n");
- }
-}
-
-void
-StumblerInfo::SetWifiInfoResponseReceived()
-{
- mIsWifiInfoResponseReceived = true;
-
- if (mIsWifiInfoResponseReceived && mCellInfoResponsesReceived == mCellInfoResponsesExpected) {
- STUMBLER_DBG("Call DumpStumblerInfo from SetWifiInfoResponseReceived\n");
- DumpStumblerInfo();
- }
-}
-
-void
-StumblerInfo::SetCellInfoResponsesExpected(uint8_t count)
-{
- mCellInfoResponsesExpected = count;
- STUMBLER_DBG("SetCellInfoNum (%d)\n", count);
-
- if (mIsWifiInfoResponseReceived && mCellInfoResponsesReceived == mCellInfoResponsesExpected) {
- STUMBLER_DBG("Call DumpStumblerInfo from SetCellInfoResponsesExpected\n");
- DumpStumblerInfo();
- }
-}
-
-
-#define TEXT_LAT NS_LITERAL_CSTRING("latitude")
-#define TEXT_LON NS_LITERAL_CSTRING("longitude")
-#define TEXT_ACC NS_LITERAL_CSTRING("accuracy")
-#define TEXT_ALT NS_LITERAL_CSTRING("altitude")
-#define TEXT_ALTACC NS_LITERAL_CSTRING("altitudeAccuracy")
-#define TEXT_HEAD NS_LITERAL_CSTRING("heading")
-#define TEXT_SPD NS_LITERAL_CSTRING("speed")
-
-nsresult
-StumblerInfo::LocationInfoToString(nsACString& aLocDesc)
-{
- nsCOMPtr<nsIDOMGeoPositionCoords> coords;
- mPosition->GetCoords(getter_AddRefs(coords));
- if (!coords) {
- return NS_ERROR_FAILURE;
- }
-
- nsDataHashtable<nsCStringHashKey, double> info;
-
- double val;
- coords->GetLatitude(&val);
- info.Put(TEXT_LAT, val);
- coords->GetLongitude(&val);
- info.Put(TEXT_LON, val);
- coords->GetAccuracy(&val);
- info.Put(TEXT_ACC, val);
- coords->GetAltitude(&val);
- info.Put(TEXT_ALT, val);
- coords->GetAltitudeAccuracy(&val);
- info.Put(TEXT_ALTACC, val);
- coords->GetHeading(&val);
- info.Put(TEXT_HEAD, val);
- coords->GetSpeed(&val);
- info.Put(TEXT_SPD, val);
-
- for (auto it = info.Iter(); !it.Done(); it.Next()) {
- const nsACString& key = it.Key();
- val = it.UserData();
- if (!IsNaN(val)) {
- aLocDesc += nsPrintfCString("\"%s\":%f,", key.BeginReading(), val);
- }
- }
-
- aLocDesc += nsPrintfCString("\"timestamp\":%lld,", PR_Now() / PR_USEC_PER_MSEC).get();
- return NS_OK;
-}
-
-#define TEXT_RADIOTYPE NS_LITERAL_CSTRING("radioType")
-#define TEXT_MCC NS_LITERAL_CSTRING("mobileCountryCode")
-#define TEXT_MNC NS_LITERAL_CSTRING("mobileNetworkCode")
-#define TEXT_LAC NS_LITERAL_CSTRING("locationAreaCode")
-#define TEXT_CID NS_LITERAL_CSTRING("cellId")
-#define TEXT_PSC NS_LITERAL_CSTRING("psc")
-#define TEXT_STRENGTH_ASU NS_LITERAL_CSTRING("asu")
-#define TEXT_STRENGTH_DBM NS_LITERAL_CSTRING("signalStrength")
-#define TEXT_REGISTERED NS_LITERAL_CSTRING("serving")
-#define TEXT_TIMEING_ADVANCE NS_LITERAL_CSTRING("timingAdvance")
-
-template <class T> void
-ExtractCommonNonCDMACellInfoItems(nsCOMPtr<T>& cell, nsDataHashtable<nsCStringHashKey, int32_t>& info)
-{
- int32_t mcc, mnc, cid, sig;
-
- cell->GetMcc(&mcc);
- cell->GetMnc(&mnc);
- cell->GetCid(&cid);
- cell->GetSignalStrength(&sig);
-
- info.Put(TEXT_MCC, mcc);
- info.Put(TEXT_MNC, mnc);
- info.Put(TEXT_CID, cid);
- info.Put(TEXT_STRENGTH_ASU, sig);
-}
-
-void
-StumblerInfo::CellNetworkInfoToString(nsACString& aCellDesc)
-{
- aCellDesc += "\"cellTowers\": [";
-
- for (uint32_t idx = 0; idx < mCellInfo.Length() ; idx++) {
- const char* radioType = 0;
- int32_t type;
- mCellInfo[idx]->GetType(&type);
- bool registered;
- mCellInfo[idx]->GetRegistered(&registered);
- if (idx) {
- aCellDesc += ",{";
- } else {
- aCellDesc += "{";
- }
-
- STUMBLER_DBG("type=%d\n", type);
-
- nsDataHashtable<nsCStringHashKey, int32_t> info;
- info.Put(TEXT_REGISTERED, registered);
-
- if(type == nsICellInfo::CELL_INFO_TYPE_GSM) {
- radioType = "gsm";
- nsCOMPtr<nsIGsmCellInfo> gsmCellInfo = do_QueryInterface(mCellInfo[idx]);
- ExtractCommonNonCDMACellInfoItems(gsmCellInfo, info);
- int32_t lac;
- gsmCellInfo->GetLac(&lac);
- info.Put(TEXT_LAC, lac);
- } else if (type == nsICellInfo::CELL_INFO_TYPE_WCDMA) {
- radioType = "wcdma";
- nsCOMPtr<nsIWcdmaCellInfo> wcdmaCellInfo = do_QueryInterface(mCellInfo[idx]);
- ExtractCommonNonCDMACellInfoItems(wcdmaCellInfo, info);
- int32_t lac, psc;
- wcdmaCellInfo->GetLac(&lac);
- wcdmaCellInfo->GetPsc(&psc);
- info.Put(TEXT_LAC, lac);
- info.Put(TEXT_PSC, psc);
- } else if (type == nsICellInfo::CELL_INFO_TYPE_CDMA) {
- radioType = "cdma";
- nsCOMPtr<nsICdmaCellInfo> cdmaCellInfo = do_QueryInterface(mCellInfo[idx]);
- int32_t mnc, lac, cid, sig;
- cdmaCellInfo->GetSystemId(&mnc);
- cdmaCellInfo->GetNetworkId(&lac);
- cdmaCellInfo->GetBaseStationId(&cid);
- info.Put(TEXT_MNC, mnc);
- info.Put(TEXT_LAC, lac);
- info.Put(TEXT_CID, cid);
-
- cdmaCellInfo->GetEvdoDbm(&sig);
- if (sig < 0 || sig == nsICellInfo::UNKNOWN_VALUE) {
- cdmaCellInfo->GetCdmaDbm(&sig);
- }
- if (sig > -1 && sig != nsICellInfo::UNKNOWN_VALUE) {
- sig *= -1;
- info.Put(TEXT_STRENGTH_DBM, sig);
- }
- } else if (type == nsICellInfo::CELL_INFO_TYPE_LTE) {
- radioType = "lte";
- nsCOMPtr<nsILteCellInfo> lteCellInfo = do_QueryInterface(mCellInfo[idx]);
- ExtractCommonNonCDMACellInfoItems(lteCellInfo, info);
- int32_t lac, timingAdvance, pcid, rsrp;
- lteCellInfo->GetTac(&lac);
- lteCellInfo->GetTimingAdvance(&timingAdvance);
- lteCellInfo->GetPcid(&pcid);
- lteCellInfo->GetRsrp(&rsrp);
- info.Put(TEXT_LAC, lac);
- info.Put(TEXT_TIMEING_ADVANCE, timingAdvance);
- info.Put(TEXT_PSC, pcid);
- if (rsrp != nsICellInfo::UNKNOWN_VALUE) {
- info.Put(TEXT_STRENGTH_DBM, rsrp * -1);
- }
- }
-
- aCellDesc += nsPrintfCString("\"%s\":\"%s\"", TEXT_RADIOTYPE.get(), radioType);
- for (auto it = info.Iter(); !it.Done(); it.Next()) {
- const nsACString& key = it.Key();
- int32_t value = it.UserData();
- if (value != nsICellInfo::UNKNOWN_VALUE) {
- aCellDesc += nsPrintfCString(",\"%s\":%d", key.BeginReading(), value);
- }
- }
-
- aCellDesc += "}";
- }
- aCellDesc += "]";
-}
-
-void
-StumblerInfo::DumpStumblerInfo()
-{
- if (!mIsWifiInfoResponseReceived || mCellInfoResponsesReceived != mCellInfoResponsesExpected) {
- STUMBLER_DBG("CellInfoReceived=%d (Expected=%d), WifiInfoResponseReceived=%d\n",
- mCellInfoResponsesReceived, mCellInfoResponsesExpected, mIsWifiInfoResponseReceived);
- return;
- }
- mIsWifiInfoResponseReceived = false;
- mCellInfoResponsesReceived = 0;
-
- nsAutoCString desc;
- nsresult rv = LocationInfoToString(desc);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("LocationInfoToString failed, skip this dump");
- return;
- }
-
- CellNetworkInfoToString(desc);
- desc += mWifiDesc;
-
- STUMBLER_DBG("dispatch write event to thread\n");
- nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
- MOZ_ASSERT(target);
-
- nsCOMPtr<nsIRunnable> event = new WriteStumbleOnThread(desc);
- target->Dispatch(event, NS_DISPATCH_NORMAL);
-}
-
-NS_IMETHODIMP
-StumblerInfo::NotifyGetCellInfoList(uint32_t count, nsICellInfo** aCellInfos)
-{
- MOZ_ASSERT(NS_IsMainThread());
- STUMBLER_DBG("There are %d cellinfo in the result\n", count);
-
- for (uint32_t i = 0; i < count; i++) {
- mCellInfo.AppendElement(aCellInfos[i]);
- }
- mCellInfoResponsesReceived++;
- DumpStumblerInfo();
- return NS_OK;
-}
-
-NS_IMETHODIMP StumblerInfo::NotifyGetCellInfoListFailed(const nsAString& error)
-{
- MOZ_ASSERT(NS_IsMainThread());
- mCellInfoResponsesReceived++;
- STUMBLER_ERR("NotifyGetCellInfoListFailedm CellInfoReadyNum=%d, mCellInfoResponsesExpected=%d, mIsWifiInfoResponseReceived=%d",
- mCellInfoResponsesReceived, mCellInfoResponsesExpected, mIsWifiInfoResponseReceived);
- DumpStumblerInfo();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-StumblerInfo::Onready(uint32_t count, nsIWifiScanResult** results)
-{
- MOZ_ASSERT(NS_IsMainThread());
- STUMBLER_DBG("There are %d wifiAPinfo in the result\n",count);
-
- mWifiDesc += ",\"wifiAccessPoints\": [";
- bool firstItem = true;
- for (uint32_t i = 0 ; i < count ; i++) {
- nsString ssid;
- results[i]->GetSsid(ssid);
- if (ssid.IsEmpty()) {
- STUMBLER_DBG("no ssid, skip this AP\n");
- continue;
- }
-
- if (ssid.Length() >= 6) {
- if (StringEndsWith(ssid, NS_LITERAL_STRING("_nomap"))) {
- STUMBLER_DBG("end with _nomap. skip this AP(ssid :%s)\n", ssid.get());
- continue;
- }
- }
-
- if (firstItem) {
- mWifiDesc += "{";
- firstItem = false;
- } else {
- mWifiDesc += ",{";
- }
-
- // mac address
- nsString bssid;
- results[i]->GetBssid(bssid);
- // 00:00:00:00:00:00 --> 000000000000
- bssid.StripChars(":");
- mWifiDesc += "\"macAddress\":\"";
- mWifiDesc += NS_ConvertUTF16toUTF8(bssid);
-
- uint32_t signal;
- results[i]->GetSignalStrength(&signal);
- mWifiDesc += "\",\"signalStrength\":";
- mWifiDesc.AppendInt(signal);
-
- mWifiDesc += "}";
- }
- mWifiDesc += "]";
-
- mIsWifiInfoResponseReceived = true;
- DumpStumblerInfo();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-StumblerInfo::Onfailure()
-{
- MOZ_ASSERT(NS_IsMainThread());
- STUMBLER_ERR("GetWifiScanResults Onfailure\n");
- mIsWifiInfoResponseReceived = true;
- DumpStumblerInfo();
- return NS_OK;
-}
-
diff --git a/dom/system/gonk/mozstumbler/MozStumbler.h b/dom/system/gonk/mozstumbler/MozStumbler.h
deleted file mode 100644
index 41ee4e5e1..000000000
--- a/dom/system/gonk/mozstumbler/MozStumbler.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozstumbler_h__
-#define mozilla_system_mozstumbler_h__
-
-#include "nsIDOMEventTarget.h"
-#include "nsICellInfo.h"
-#include "nsIWifi.h"
-
-#define STUMBLE_INTERVAL_MS 3000
-
-class nsGeoPosition;
-
-void MozStumble(nsGeoPosition* position);
-
-class StumblerInfo final : public nsICellInfoListCallback,
- public nsIWifiScanResultsReady
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSICELLINFOLISTCALLBACK
- NS_DECL_NSIWIFISCANRESULTSREADY
-
- explicit StumblerInfo(nsGeoPosition* position)
- : mPosition(position), mCellInfoResponsesExpected(0), mCellInfoResponsesReceived(0), mIsWifiInfoResponseReceived(0)
- {}
- void SetWifiInfoResponseReceived();
- void SetCellInfoResponsesExpected(uint8_t count);
-
-private:
- ~StumblerInfo() {}
- void DumpStumblerInfo();
- nsresult LocationInfoToString(nsACString& aLocDesc);
- void CellNetworkInfoToString(nsACString& aCellDesc);
- nsTArray<RefPtr<nsICellInfo>> mCellInfo;
- nsCString mWifiDesc;
- RefPtr<nsGeoPosition> mPosition;
- int mCellInfoResponsesExpected;
- int mCellInfoResponsesReceived;
- bool mIsWifiInfoResponseReceived;
-};
-#endif // mozilla_system_mozstumbler_h__
-
diff --git a/dom/system/gonk/mozstumbler/StumblerLogging.cpp b/dom/system/gonk/mozstumbler/StumblerLogging.cpp
deleted file mode 100644
index acf23b3b1..000000000
--- a/dom/system/gonk/mozstumbler/StumblerLogging.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "StumblerLogging.h"
-
-mozilla::LogModule* GetLog()
-{
- static mozilla::LazyLogModule log("mozstumbler");
- return log;
-}
diff --git a/dom/system/gonk/mozstumbler/StumblerLogging.h b/dom/system/gonk/mozstumbler/StumblerLogging.h
deleted file mode 100644
index 038f44f8f..000000000
--- a/dom/system/gonk/mozstumbler/StumblerLogging.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef STUMBLERLOGGING_H
-#define STUMBLERLOGGING_H
-
-#include "mozilla/Logging.h"
-
-mozilla::LogModule* GetLog();
-
-#define STUMBLER_DBG(arg, ...) MOZ_LOG(GetLog(), mozilla::LogLevel::Debug, ("STUMBLER - %s: " arg, __func__, ##__VA_ARGS__))
-#define STUMBLER_LOG(arg, ...) MOZ_LOG(GetLog(), mozilla::LogLevel::Info, ("STUMBLER - %s: " arg, __func__, ##__VA_ARGS__))
-#define STUMBLER_ERR(arg, ...) MOZ_LOG(GetLog(), mozilla::LogLevel::Error, ("STUMBLER -%s: " arg, __func__, ##__VA_ARGS__))
-
-#endif
diff --git a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp b/dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp
deleted file mode 100644
index d97aa9712..000000000
--- a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "UploadStumbleRunnable.h"
-#include "StumblerLogging.h"
-#include "mozilla/dom/Event.h"
-#include "nsIInputStream.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsIURLFormatter.h"
-#include "nsIXMLHttpRequest.h"
-#include "nsNetUtil.h"
-#include "nsVariant.h"
-
-UploadStumbleRunnable::UploadStumbleRunnable(nsIInputStream* aUploadData)
-: mUploadInputStream(aUploadData)
-{
-}
-
-NS_IMETHODIMP
-UploadStumbleRunnable::Run()
-{
- MOZ_ASSERT(NS_IsMainThread());
- nsresult rv = Upload();
- if (NS_FAILED(rv)) {
- WriteStumbleOnThread::UploadEnded(false);
- }
- return NS_OK;
-}
-
-nsresult
-UploadStumbleRunnable::Upload()
-{
- nsresult rv;
- RefPtr<nsVariant> variant = new nsVariant();
-
- rv = variant->SetAsISupports(mUploadInputStream);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIXMLHttpRequest> xhr = do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIScriptSecurityManager> secman =
- do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIPrincipal> systemPrincipal;
- rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIURLFormatter> formatter =
- do_CreateInstance("@mozilla.org/toolkit/URLFormatterService;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- nsString url;
- rv = formatter->FormatURLPref(NS_LITERAL_STRING("geo.stumbler.url"), url);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = xhr->Open(NS_LITERAL_CSTRING("POST"), NS_ConvertUTF16toUTF8(url), false, EmptyString(), EmptyString());
- NS_ENSURE_SUCCESS(rv, rv);
-
- xhr->SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), NS_LITERAL_CSTRING("gzip"));
- xhr->SetMozBackgroundRequest(true);
- // 60s timeout
- xhr->SetTimeout(60 * 1000);
-
- nsCOMPtr<EventTarget> target(do_QueryInterface(xhr));
- RefPtr<nsIDOMEventListener> listener = new UploadEventListener(xhr);
-
- const char* const sEventStrings[] = {
- // nsIXMLHttpRequestEventTarget event types
- "abort",
- "error",
- "load",
- "timeout"
- };
-
- for (uint32_t index = 0; index < MOZ_ARRAY_LENGTH(sEventStrings); index++) {
- nsAutoString eventType = NS_ConvertASCIItoUTF16(sEventStrings[index]);
- rv = target->AddEventListener(eventType, listener, false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = xhr->Send(variant);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(UploadEventListener, nsIDOMEventListener)
-
-UploadEventListener::UploadEventListener(nsIXMLHttpRequest* aXHR)
-: mXHR(aXHR)
-{
-}
-
-NS_IMETHODIMP
-UploadEventListener::HandleEvent(nsIDOMEvent* aEvent)
-{
- nsString type;
- if (NS_FAILED(aEvent->GetType(type))) {
- STUMBLER_ERR("Failed to get event type");
- WriteStumbleOnThread::UploadEnded(false);
- return NS_ERROR_FAILURE;
- }
-
- if (type.EqualsLiteral("load")) {
- STUMBLER_DBG("Got load Event\n");
- } else if (type.EqualsLiteral("error") && mXHR) {
- STUMBLER_ERR("Upload Error");
- } else {
- STUMBLER_DBG("Receive %s Event", NS_ConvertUTF16toUTF8(type).get());
- }
-
- uint32_t statusCode = 0;
- bool doDelete = false;
- if (!mXHR) {
- return NS_OK;
- }
- nsresult rv = mXHR->GetStatus(&statusCode);
- if (NS_SUCCEEDED(rv)) {
- STUMBLER_DBG("statuscode %d \n", statusCode);
- }
-
- if (200 == statusCode || 400 == statusCode) {
- doDelete = true;
- }
-
- WriteStumbleOnThread::UploadEnded(doDelete);
- nsCOMPtr<EventTarget> target(do_QueryInterface(mXHR));
-
- const char* const sEventStrings[] = {
- // nsIXMLHttpRequestEventTarget event types
- "abort",
- "error",
- "load",
- "timeout"
- };
-
- for (uint32_t index = 0; index < MOZ_ARRAY_LENGTH(sEventStrings); index++) {
- nsAutoString eventType = NS_ConvertASCIItoUTF16(sEventStrings[index]);
- rv = target->RemoveEventListener(eventType, this, false);
- }
-
- mXHR = nullptr;
- return NS_OK;
-}
diff --git a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.h b/dom/system/gonk/mozstumbler/UploadStumbleRunnable.h
deleted file mode 100644
index 462665a86..000000000
--- a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#ifndef UPLOADSTUMBLERUNNABLE_H
-#define UPLOADSTUMBLERUNNABLE_H
-
-#include "nsIDOMEventListener.h"
-
-class nsIXMLHttpRequest;
-class nsIInputStream;
-
-/*
- This runnable is managed by WriteStumbleOnThread only, see that class
- for how this is scheduled.
- */
-class UploadStumbleRunnable final : public Runnable
-{
-public:
- explicit UploadStumbleRunnable(nsIInputStream* aUploadInputStream);
-
- NS_IMETHOD Run() override;
-private:
- virtual ~UploadStumbleRunnable() {}
- nsCOMPtr<nsIInputStream> mUploadInputStream;
- nsresult Upload();
-};
-
-
-class UploadEventListener : public nsIDOMEventListener
-{
-public:
- UploadEventListener(nsIXMLHttpRequest* aXHR);
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDOMEVENTLISTENER
-
-protected:
- virtual ~UploadEventListener() {}
- nsCOMPtr<nsIXMLHttpRequest> mXHR;
-};
-
-#endif
diff --git a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp b/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp
deleted file mode 100644
index e58e771c4..000000000
--- a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WriteStumbleOnThread.h"
-#include "StumblerLogging.h"
-#include "UploadStumbleRunnable.h"
-#include "nsDumpUtils.h"
-#include "nsGZFileWriter.h"
-#include "nsIFileStreams.h"
-#include "nsIInputStream.h"
-#include "nsPrintfCString.h"
-
-#define MAXFILESIZE_KB (15 * 1024)
-#define ONEDAY_IN_MSEC (24 * 60 * 60 * 1000)
-#define MAX_UPLOAD_ATTEMPTS 20
-
-mozilla::Atomic<bool> WriteStumbleOnThread::sIsFileWaitingForUpload(false);
-mozilla::Atomic<bool> WriteStumbleOnThread::sIsAlreadyRunning(false);
-WriteStumbleOnThread::UploadFreqGuard WriteStumbleOnThread::sUploadFreqGuard = {0};
-
-#define FILENAME_INPROGRESS NS_LITERAL_CSTRING("stumbles.json.gz")
-#define FILENAME_COMPLETED NS_LITERAL_CSTRING("stumbles.done.json.gz")
-#define OUTPUT_DIR NS_LITERAL_CSTRING("mozstumbler")
-
-class DeleteRunnable : public Runnable
-{
- public:
- DeleteRunnable() {}
-
- NS_IMETHOD
- Run() override
- {
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED,
- getter_AddRefs(tmpFile),
- OUTPUT_DIR,
- nsDumpUtils::CREATE);
- if (NS_SUCCEEDED(rv)) {
- tmpFile->Remove(true);
- }
- // critically, this sets this flag to false so writing can happen again
- WriteStumbleOnThread::sIsAlreadyRunning = false;
- WriteStumbleOnThread::sIsFileWaitingForUpload = false;
- return NS_OK;
- }
-
- private:
- ~DeleteRunnable() {}
-};
-
-bool
-WriteStumbleOnThread::IsFileWaitingForUpload()
-{
- return sIsFileWaitingForUpload;
-}
-
-void
-WriteStumbleOnThread::UploadEnded(bool deleteUploadFile)
-{
- if (!deleteUploadFile) {
- sIsAlreadyRunning = false;
- return;
- }
-
- nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
- MOZ_ASSERT(target);
- nsCOMPtr<nsIRunnable> event = new DeleteRunnable();
- target->Dispatch(event, NS_DISPATCH_NORMAL);
-}
-
-void
-WriteStumbleOnThread::WriteJSON(Partition aPart)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv;
- rv = nsDumpUtils::OpenTempFile(FILENAME_INPROGRESS, getter_AddRefs(tmpFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Open a file for stumble failed");
- return;
- }
-
- RefPtr<nsGZFileWriter> gzWriter = new nsGZFileWriter(nsGZFileWriter::Append);
- rv = gzWriter->Init(tmpFile);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("gzWriter init failed");
- return;
- }
-
- /*
- The json format is like below.
- {items:[
- {item},
- {item},
- {item}
- ]}
- */
-
- // Need to add "]}" after the last item
- if (aPart == Partition::End) {
- rv = gzWriter->Write("]}");
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("gzWriter Write failed");
- }
-
- rv = gzWriter->Finish();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream finish failed");
- }
-
- nsCOMPtr<nsIFile> targetFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(targetFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- nsAutoString targetFilename;
- rv = targetFile->GetLeafName(targetFilename);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Get Filename failed");
- return;
- }
- rv = targetFile->Remove(true);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Remove File failed");
- return;
- }
- // Rename tmpfile
- rv = tmpFile->MoveTo(/* directory */ nullptr, targetFilename);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Rename File failed");
- return;
- }
- return;
- }
-
- // Need to add "{items:[" before the first item
- if (aPart == Partition::Begining) {
- rv = gzWriter->Write("{\"items\":[{");
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream write begining failed");
- }
- } else if (aPart == Partition::Middle) {
- rv = gzWriter->Write(",{");
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream write middle failed");
- }
- }
- rv = gzWriter->Write(mDesc.get());
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream write mDesc failed");
- }
- // one item is ended with '}' (e.g. {item})
- rv = gzWriter->Write("}");
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream write end failed");
- }
-
- rv = gzWriter->Finish();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream finish failed");
- }
-
- // check if it is the end of this file
- int64_t fileSize = 0;
- rv = tmpFile->GetFileSize(&fileSize);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("GetFileSize failed");
- return;
- }
- if (fileSize >= MAXFILESIZE_KB) {
- WriteJSON(Partition::End);
- return;
- }
-}
-
-WriteStumbleOnThread::Partition
-WriteStumbleOnThread::GetWritePosition()
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_INPROGRESS, getter_AddRefs(tmpFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Open a file for stumble failed");
- return Partition::Unknown;
- }
-
- int64_t fileSize = 0;
- rv = tmpFile->GetFileSize(&fileSize);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("GetFileSize failed");
- return Partition::Unknown;
- }
-
- if (fileSize == 0) {
- return Partition::Begining;
- } else if (fileSize >= MAXFILESIZE_KB) {
- return Partition::End;
- } else {
- return Partition::Middle;
- }
-}
-
-NS_IMETHODIMP
-WriteStumbleOnThread::Run()
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- bool b = sIsAlreadyRunning.exchange(true);
- if (b) {
- return NS_OK;
- }
-
- UploadFileStatus status = GetUploadFileStatus();
-
- if (UploadFileStatus::NoFile != status) {
- if (UploadFileStatus::ExistsAndReadyToUpload == status) {
- sIsFileWaitingForUpload = true;
- Upload();
- return NS_OK;
- }
- } else {
- Partition partition = GetWritePosition();
- if (partition == Partition::Unknown) {
- STUMBLER_ERR("GetWritePosition failed, skip once");
- } else {
- WriteJSON(partition);
- }
- }
-
- sIsFileWaitingForUpload = false;
- sIsAlreadyRunning = false;
- return NS_OK;
-}
-
-
-/*
- If the upload file exists, then check if it is one day old.
- • if it is a day old -> ExistsAndReadyToUpload
- • if it is less than the current day old -> Exists
- • otherwise -> NoFile
-
- The Exists case means that the upload and the stumbling is rate limited
- per-day to the size of the one file.
- */
-WriteStumbleOnThread::UploadFileStatus
-WriteStumbleOnThread::GetUploadFileStatus()
-{
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(tmpFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- int64_t fileSize;
- rv = tmpFile->GetFileSize(&fileSize);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("GetFileSize failed");
- return UploadFileStatus::NoFile;
- }
- if (fileSize <= 0) {
- tmpFile->Remove(true);
- return UploadFileStatus::NoFile;
- }
-
- PRTime lastModifiedTime;
- tmpFile->GetLastModifiedTime(&lastModifiedTime);
- if ((PR_Now() / PR_USEC_PER_MSEC) - lastModifiedTime >= ONEDAY_IN_MSEC) {
- return UploadFileStatus::ExistsAndReadyToUpload;
- }
- return UploadFileStatus::Exists;
-}
-
-void
-WriteStumbleOnThread::Upload()
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- time_t seconds = time(0);
- int day = seconds / (60 * 60 * 24);
-
- if (sUploadFreqGuard.daySinceEpoch < day) {
- sUploadFreqGuard.daySinceEpoch = day;
- sUploadFreqGuard.attempts = 0;
- }
-
- sUploadFreqGuard.attempts++;
- if (sUploadFreqGuard.attempts > MAX_UPLOAD_ATTEMPTS) {
- STUMBLER_ERR("Too many upload attempts today");
- sIsAlreadyRunning = false;
- return;
- }
-
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(tmpFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- int64_t fileSize;
- rv = tmpFile->GetFileSize(&fileSize);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("GetFileSize failed");
- sIsAlreadyRunning = false;
- return;
- }
-
- if (fileSize <= 0) {
- sIsAlreadyRunning = false;
- return;
- }
-
- // prepare json into nsIInputStream
- nsCOMPtr<nsIInputStream> inStream;
- rv = NS_NewLocalFileInputStream(getter_AddRefs(inStream), tmpFile);
- if (NS_FAILED(rv)) {
- sIsAlreadyRunning = false;
- return;
- }
-
- RefPtr<nsIRunnable> uploader = new UploadStumbleRunnable(inStream);
- NS_DispatchToMainThread(uploader);
-}
diff --git a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.h b/dom/system/gonk/mozstumbler/WriteStumbleOnThread.h
deleted file mode 100644
index 104cf9bdd..000000000
--- a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef WriteStumbleOnThread_H
-#define WriteStumbleOnThread_H
-
-#include "mozilla/Atomics.h"
-
-class DeleteRunnable;
-
-/*
- This class is the entry point to stumbling, in that it
- receives the location+cell+wifi string and writes it
- to disk, or instead, it calls UploadStumbleRunnable
- to upload the data.
-
- Writes will happen until the file is a max size, then stop.
- Uploads will happen only when the file is one day old.
- The purpose of these decisions is to have very simple rate-limiting
- on the writes, as well as the uploads.
-
- There is only one file active; it is either being used for writing,
- or for uploading. If the file is ready for uploading, no further
- writes will take place until this file has been uploaded.
- This can mean writing might not take place for days until the uploaded
- file is processed. This is correct by-design.
-
- A notable limitation is that the upload is triggered by a location event,
- this is used as an arbitrary and simple trigger. In future, there are
- better events that can be used, such as detecting network activity.
-
- This thread is guarded so that only one instance is active (see the
- mozilla::Atomics used for this).
- */
-class WriteStumbleOnThread : public mozilla::Runnable
-{
-public:
- explicit WriteStumbleOnThread(const nsCString& aDesc)
- : mDesc(aDesc)
- {}
-
- NS_IMETHOD Run() override;
-
- static void UploadEnded(bool deleteUploadFile);
-
- // Used externally to determine if cell+wifi scans should happen
- // (returns false for that case).
- static bool IsFileWaitingForUpload();
-
-private:
- friend class DeleteRunnable;
-
- enum class Partition {
- Begining,
- Middle,
- End,
- Unknown
- };
-
- enum class UploadFileStatus {
- NoFile, Exists, ExistsAndReadyToUpload
- };
-
- ~WriteStumbleOnThread() {}
-
- Partition GetWritePosition();
- UploadFileStatus GetUploadFileStatus();
- void WriteJSON(Partition aPart);
- void Upload();
-
- nsCString mDesc;
-
- // Only run one instance of this
- static mozilla::Atomic<bool> sIsAlreadyRunning;
-
- static mozilla::Atomic<bool> sIsFileWaitingForUpload;
-
- // Limit the upload attempts per day. If the device is rebooted
- // this resets the allowed attempts, which is acceptable.
- struct UploadFreqGuard {
- int attempts;
- int daySinceEpoch;
- };
- static UploadFreqGuard sUploadFreqGuard;
-
-};
-
-#endif
diff --git a/dom/system/gonk/nsIAudioManager.idl b/dom/system/gonk/nsIAudioManager.idl
deleted file mode 100644
index c2eb62b21..000000000
--- a/dom/system/gonk/nsIAudioManager.idl
+++ /dev/null
@@ -1,58 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, builtinclass, uuid(df31c280-1ef1-11e5-867f-0800200c9a66)]
-interface nsIAudioManager : nsISupports
-{
- /**
- * Microphone muted?
- */
- attribute boolean microphoneMuted;
-
- /**
- * Set the phone's audio mode.
- */
- const long PHONE_STATE_INVALID = -2;
- const long PHONE_STATE_CURRENT = -1;
- const long PHONE_STATE_NORMAL = 0;
- const long PHONE_STATE_RINGTONE = 1;
- const long PHONE_STATE_IN_CALL = 2;
- const long PHONE_STATE_IN_COMMUNICATION = 3;
-
- attribute long phoneState;
-
- /**
- * Configure a particular device ("force") to be used for one of the uses
- * (communication, media playback, etc.)
- */
- const long FORCE_NONE = 0; // the default
- const long FORCE_SPEAKER = 1;
- const long FORCE_HEADPHONES = 2;
- const long FORCE_BT_SCO = 3;
- const long FORCE_BT_A2DP = 4;
- const long FORCE_WIRED_ACCESSORY = 5;
- const long FORCE_BT_CAR_DOCK = 6;
- const long FORCE_BT_DESK_DOCK = 7;
- const long FORCE_ANALOG_DOCK = 8;
- const long FORCE_DIGITAL_DOCK = 9;
- const long FORCE_NO_BT_A2DP = 10;
- const long USE_COMMUNICATION = 0;
- const long USE_MEDIA = 1;
- const long USE_RECORD = 2;
- const long USE_DOCK = 3;
-
- void setForceForUse(in long usage, in long force);
- long getForceForUse(in long usage);
-
- /**
- * These functions would be used when we enable the new volume control API
- * (mozAudioChannelManager). The range of volume index is from 0 to N.
- * More details on : https://gist.github.com/evanxd/41d8e2d91c5201a42bfa
- */
- void setAudioChannelVolume(in unsigned long channel, in unsigned long index);
- unsigned long getAudioChannelVolume(in unsigned long channel);
- unsigned long getMaxAudioChannelVolume(in unsigned long channel);
-};
diff --git a/dom/system/gonk/nsIDataCallInterfaceService.idl b/dom/system/gonk/nsIDataCallInterfaceService.idl
deleted file mode 100644
index c387879fa..000000000
--- a/dom/system/gonk/nsIDataCallInterfaceService.idl
+++ /dev/null
@@ -1,268 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(6b66446a-7000-438f-8e1b-b56b4cbf4fa9)]
-interface nsIDataCall : nsISupports
-{
- /**
- * Data call fail cause. One of the nsIDataCallInterface.DATACALL_FAIL_*
- * values.
- */
- readonly attribute long failCause;
-
- /**
- * If failCause != nsIDataCallInterface.DATACALL_FAIL_NONE, this field
- * indicates the suggested retry back-off timer. The unit is milliseconds.
- */
- readonly attribute long suggestedRetryTime;
-
- /**
- * Context ID, uniquely identifies this call.
- */
- readonly attribute long cid;
-
- /**
- * Data call network state. One of the nsIDataCallInterface.DATACALL_STATE_*
- * values.
- */
- readonly attribute long active;
-
- /**
- * Data call connection type. One of the
- * nsIDataCallInterface.DATACALL_PDP_TYPE_* values.
- */
- readonly attribute long pdpType;
-
- /**
- * The network interface name.
- */
- readonly attribute DOMString ifname;
-
- /**
- * A space-delimited list of addresses with optional "/" prefix length.
- */
- readonly attribute DOMString addresses;
-
- /**
- * A space-delimited list of DNS server addresses.
- */
- readonly attribute DOMString dnses;
-
- /**
- * A space-delimited list of default gateway addresses.
- */
- readonly attribute DOMString gateways;
-
- /**
- * A space-delimited list of Proxy Call State Control Function addresses for
- * IMS client.
- */
- readonly attribute DOMString pcscf;
-
- /**
- * MTU received from network, -1 if not set or invalid.
- */
- readonly attribute long mtu;
-};
-
-[scriptable, uuid(e119c54b-9354-4ad6-a1ee-18608bde9320)]
-interface nsIDataCallInterfaceListener : nsISupports
-{
- /**
- * Notify data call interface listeners about unsolicited data call state
- * changes.
- */
- void notifyDataCallListChanged(in uint32_t count,
- [array, size_is(count)] in nsIDataCall
- dataCalls);
-};
-
-[scriptable, uuid(db0b640a-3b3a-4f48-84dc-256e176876c2)]
-interface nsIDataCallCallback : nsISupports
-{
- /**
- * Called when setupDataCall() returns succesfully.
- */
- void notifySetupDataCallSuccess(in nsIDataCall dataCall);
-
- /**
- * Called when getDataCallList() returns succesfully.
- */
- void notifyGetDataCallListSuccess(in uint32_t count,
- [array, size_is(count)] in nsIDataCall
- dataCalls);
- /**
- * Called when request returns succesfully.
- */
- void notifySuccess();
-
- /**
- * Called when request returns error.
- */
- void notifyError(in AString errorMsg);
-};
-
-[scriptable, uuid(ec219021-8623-4b9f-aba5-4db58c60684f)]
-interface nsIDataCallInterface : nsISupports
-{
- /**
- * Data fail causes, defined in TS 24.008.
- */
- const long DATACALL_FAIL_NONE = 0;
- const long DATACALL_FAIL_OPERATOR_BARRED = 0x08;
- const long DATACALL_FAIL_INSUFFICIENT_RESOURCES = 0x1A;
- const long DATACALL_FAIL_MISSING_UKNOWN_APN = 0x1B;
- const long DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;
- const long DATACALL_FAIL_USER_AUTHENTICATION = 0x1D;
- const long DATACALL_FAIL_ACTIVATION_REJECT_GGSN = 0x1E;
- const long DATACALL_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
- const long DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20;
- const long DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;
- const long DATACALL_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22;
- const long DATACALL_FAIL_NSAPI_IN_USE = 0x23;
- const long DATACALL_FAIL_ONLY_IPV4_ALLOWED = 0x32;
- const long DATACALL_FAIL_ONLY_IPV6_ALLOWED = 0x33;
- const long DATACALL_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34;
- const long DATACALL_FAIL_PROTOCOL_ERRORS = 0x6F;
- /* Not mentioned in the specification */
- const long DATACALL_FAIL_VOICE_REGISTRATION_FAIL = -1;
- const long DATACALL_FAIL_DATA_REGISTRATION_FAIL = -2;
- const long DATACALL_FAIL_SIGNAL_LOST = -3;
- const long DATACALL_FAIL_PREF_RADIO_TECH_CHANGED = -4;
- const long DATACALL_FAIL_RADIO_POWER_OFF = -5;
- const long DATACALL_FAIL_TETHERED_CALL_ACTIVE = -6;
- const long DATACALL_FAIL_ERROR_UNSPECIFIED = 0xFFFF;
-
- /**
- * Data call network state.
- */
- const long DATACALL_STATE_INACTIVE = 0;
- const long DATACALL_STATE_ACTIVE_DOWN = 1;
- const long DATACALL_STATE_ACTIVE_UP = 2;
-
- /**
- * Data call authentication type. Must match the values in ril_consts
- * RIL_DATACALL_AUTH_TO_GECKO array.
- */
- const long DATACALL_AUTH_NONE = 0;
- const long DATACALL_AUTH_PAP = 1;
- const long DATACALL_AUTH_CHAP = 2;
- const long DATACALL_AUTH_PAP_OR_CHAP = 3;
-
- /**
- * Data call protocol type. Must match the values in ril_consts
- * RIL_DATACALL_PDP_TYPES array.
- */
- const long DATACALL_PDP_TYPE_IPV4 = 0;
- const long DATACALL_PDP_TYPE_IPV4V6 = 1;
- const long DATACALL_PDP_TYPE_IPV6 = 2;
-
- /**
- * Reason for deactivating data call.
- */
- const long DATACALL_DEACTIVATE_NO_REASON = 0;
- const long DATACALL_DEACTIVATE_RADIO_SHUTDOWN = 1;
-
- /**
- * Setup data call.
- *
- * @param apn
- * Apn to connect to.
- * @param username
- * Username for apn.
- * @param password
- * Password for apn.
- * @param authType
- * Authentication type. One of the DATACALL_AUTH_* values.
- * @param pdpType
- * Connection type. One of the DATACALL_PDP_TYPE_* values.
- * @param nsIDataCallCallback
- * Called when request is finished.
- *
- * If successful, the notifySetupDataCallSuccess() will be called with the
- * new nsIDataCall.
- *
- * Otherwise, the notifyError() will be called, and the error will be either
- * 'RadioNotAvailable', 'OpNotAllowedBeforeRegToNw',
- * 'OpNotAllowedDuringVoiceCall', 'RequestNotSupported' or 'GenericFailure'.
- */
- void setupDataCall(in AString apn, in AString username,
- in AString password, in long authType,
- in long pdpType,
- in nsIDataCallCallback callback);
-
- /**
- * Deactivate data call.
- *
- * @param cid
- * Context id.
- * @param reason
- * Disconnect Reason. One of the DATACALL_DEACTIVATE_* values.
- * @param nsIDataCallCallback
- * Called when request is finished.
- *
- * If successful, the notifySuccess() will be called.
- *
- * Otherwise, the notifyError() will be called, and the error will be either
- * 'RadioNotAvailable' or 'GenericFailure'.
- */
- void deactivateDataCall(in long cid,
- in long reason,
- in nsIDataCallCallback callback);
-
- /**
- * Get current data call list.
- *
- * @param nsIDataCallCallback
- * Called when request is finished.
- *
- * If successful, the notifyGetDataCallListSuccess() will be called with the
- * list of nsIDataCall(s).
- *
- * Otherwise, the notifyError() will be called, and the error will be either
- * 'RadioNotAvailable' or 'GenericFailure'.
- */
- void getDataCallList(in nsIDataCallCallback callback);
-
- /**
- * Set data registration state.
- *
- * @param attach
- * whether to attach data registration or not.
- * @param nsIDataCallCallback
- * Called when request is finished.
- *
- * If successful, the notifySuccess() will be called.
- *
- * Otherwise, the notifyError() will be called, and the error will be either
- * 'RadioNotAvailable', 'SubscriptionNotAvailable' or 'GenericFailure'.
- */
- void setDataRegistration(in boolean attach,
- in nsIDataCallCallback callback);
-
- /**
- * Register to receive unsolicited events from this nsIDataCallInterface.
- */
- void registerListener(in nsIDataCallInterfaceListener listener);
-
- /**
- * Unregister to stop receiving unsolicited events from this
- * nsIDataCallInterface.
- */
- void unregisterListener(in nsIDataCallInterfaceListener listener);
-};
-
-[scriptable, uuid(64700406-7429-4743-a6ae-f82e9877fd0d)]
-interface nsIDataCallInterfaceService : nsISupports
-{
- /**
- * Get the corresponding data call interface.
- *
- * @param clientId
- * clientId of the data call interface to get.
- */
- nsIDataCallInterface getDataCallInterface(in long clientId);
-}; \ No newline at end of file
diff --git a/dom/system/gonk/nsIDataCallManager.idl b/dom/system/gonk/nsIDataCallManager.idl
deleted file mode 100644
index de8477801..000000000
--- a/dom/system/gonk/nsIDataCallManager.idl
+++ /dev/null
@@ -1,81 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsINetworkInterface.idl"
-
-[scriptable, uuid(b8bcd6aa-5b06-4362-a68c-317878429e51)]
-interface nsIRilNetworkInfo : nsINetworkInfo
-{
- readonly attribute unsigned long serviceId;
- readonly attribute DOMString iccId;
-
- /* The following attributes are for MMS proxy settings. */
- readonly attribute DOMString mmsc; // Empty string if not set.
- readonly attribute DOMString mmsProxy; // Empty string if not set.
- readonly attribute long mmsPort; // -1 if not set.
-
- /**
- * Get the list of pcscf addresses, could be IPv4 or IPv6.
- *
- * @param count
- * The length of the list of pcscf addresses.
- *
- * @returns the list of pcscf addresses.
- */
- void getPcscf([optional] out unsigned long count,
- [array, size_is(count), retval] out wstring pcscf);
-};
-
-[scriptable, function, uuid(cb2f0f5b-67f4-4c14-93e8-01e66b630464)]
-interface nsIDeactivateDataCallsCallback : nsISupports
-{
- /**
- * Callback function used to notify when all data calls are disconnected.
- */
- void notifyDataCallsDisconnected();
-};
-
-[scriptable, uuid(e3feec20-36b4-47de-a7a5-e32a65f20186)]
-interface nsIDataCallHandler : nsISupports
-{
- /**
- * PDP APIs
- *
- * @param networkType
- * Mobile network type, that is,
- * nsINetworkInterface.NETWORK_TYPE_MOBILE or one of the
- * nsINetworkInterface.NETWORK_TYPE_MOBILE_* values.
- */
- void setupDataCallByType(in long networkType);
- void deactivateDataCallByType(in long networkType);
- long getDataCallStateByType(in long networkType);
-
- /**
- * Deactivate all data calls.
- *
- * @param callback
- * Callback to notify when all data calls are disconnected.
- */
- void deactivateDataCalls(in nsIDeactivateDataCallsCallback callback);
-
- /**
- * Called to reconsider data call state.
- */
- void updateRILNetworkInterface();
-};
-
-[scriptable, uuid(2c46e37d-88dc-4d25-bb37-e1c0d3e9cb5f)]
-interface nsIDataCallManager : nsISupports
-{
- readonly attribute long dataDefaultServiceId;
-
- /**
- * Get the corresponding data call handler.
- *
- * @param clientId
- * clientId of the data call handler to get.
- */
- nsIDataCallHandler getDataCallHandler(in unsigned long clientId);
-}; \ No newline at end of file
diff --git a/dom/system/gonk/nsIGonkDataCallInterfaceService.idl b/dom/system/gonk/nsIGonkDataCallInterfaceService.idl
deleted file mode 100644
index 240ca6bab..000000000
--- a/dom/system/gonk/nsIGonkDataCallInterfaceService.idl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDataCallInterfaceService.idl"
-
-[scriptable, uuid(f008d00c-e2b8-49b2-8f88-19111577938e)]
-interface nsIGonkDataCallInterfaceService : nsIDataCallInterfaceService
-{
- /**
- * Called by RadioInterface or lower layer to notify about data call list
- * changes.
- */
- void notifyDataCallListChanged(in unsigned long clientId,
- in uint32_t count,
- [array, size_is(count)] in nsIDataCall
- dataCalls);
-}; \ No newline at end of file
diff --git a/dom/system/gonk/nsINetworkInterface.idl b/dom/system/gonk/nsINetworkInterface.idl
deleted file mode 100644
index bd40e751a..000000000
--- a/dom/system/gonk/nsINetworkInterface.idl
+++ /dev/null
@@ -1,108 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(4816a559-5620-4cb5-8433-ff0b25e6622f)]
-interface nsINetworkInfo : nsISupports
-{
- const long NETWORK_STATE_UNKNOWN = -1;
- const long NETWORK_STATE_CONNECTING = 0;
- const long NETWORK_STATE_CONNECTED = 1;
- const long NETWORK_STATE_DISCONNECTING = 2;
- const long NETWORK_STATE_DISCONNECTED = 3;
- const long NETWORK_STATE_ENABLED = 4;
- const long NETWORK_STATE_DISABLED = 5;
-
- /**
- * Current network state, one of the NETWORK_STATE_* constants.
- *
- * When this changes, network interface implementations notify with
- * updateNetworkInterface() API.
- */
- readonly attribute long state;
-
- const long NETWORK_TYPE_UNKNOWN = -1;
- const long NETWORK_TYPE_WIFI = 0;
- const long NETWORK_TYPE_MOBILE = 1;
- const long NETWORK_TYPE_MOBILE_MMS = 2;
- const long NETWORK_TYPE_MOBILE_SUPL = 3;
- const long NETWORK_TYPE_WIFI_P2P = 4;
- const long NETWORK_TYPE_MOBILE_IMS = 5;
- const long NETWORK_TYPE_MOBILE_DUN = 6;
- const long NETWORK_TYPE_MOBILE_FOTA = 7;
- const long NETWORK_TYPE_ETHERNET = 8;
-
- /**
- * Network type. One of the NETWORK_TYPE_* constants.
- */
- readonly attribute long type;
-
- /**
- * Interface name of the network interface this network info belongs to.
- */
- readonly attribute DOMString name;
-
- /**
- * Get the list of ip addresses and prefix lengths, ip address could be IPv4
- * or IPv6, typically 1 IPv4 or 1 IPv6 or one of each.
- *
- * @param ips
- * The list of ip addresses retrieved.
- * @param prefixLengths
- * The list of prefix lengths retrieved.
- *
- * @returns the length of the lists.
- */
- void getAddresses([array, size_is(count)] out wstring ips,
- [array, size_is(count)] out unsigned long prefixLengths,
- [retval] out unsigned long count);
-
- /**
- * Get the list of gateways, could be IPv4 or IPv6, typically 1 IPv4 or 1
- * IPv6 or one of each.
- *
- * @param count
- * The length of the list of gateways
- *
- * @returns the list of gateways.
- */
- void getGateways([optional] out unsigned long count,
- [array, size_is(count), retval] out wstring gateways);
-
- /**
- * Get the list of dnses, could be IPv4 or IPv6.
- *
- * @param count
- * The length of the list of dnses.
- *
- * @returns the list of dnses.
- */
- void getDnses([optional] out unsigned long count,
- [array, size_is(count), retval] out wstring dnses);
-};
-
-[scriptable, uuid(8b1345fa-b34c-41b3-8d21-09f961bf8887)]
-interface nsINetworkInterface : nsISupports
-{
- /**
- * The network information about this network interface.
- */
- readonly attribute nsINetworkInfo info;
-
- /**
- * The host name of the http proxy server.
- */
- readonly attribute DOMString httpProxyHost;
-
- /*
- * The port number of the http proxy server.
- */
- readonly attribute long httpProxyPort;
-
- /*
- * The Maximun Transmit Unit for this network interface, -1 if not set.
- */
- readonly attribute long mtu;
-};
diff --git a/dom/system/gonk/nsINetworkInterfaceListService.idl b/dom/system/gonk/nsINetworkInterfaceListService.idl
deleted file mode 100644
index 0c224842e..000000000
--- a/dom/system/gonk/nsINetworkInterfaceListService.idl
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsINetworkInfo;
-
-[scriptable, uuid(55779d32-1e28-4f43-af87-09d04bc3cce9)]
-interface nsINetworkInterfaceList : nsISupports
-{
- /**
- * Number of the network interfaces that is available.
- */
- long getNumberOfInterface();
-
- /**
- * Get the i-th interface info info from the list.
- * @param interfaceIndex index of interface, from 0 to number of interface - 1.
- */
- nsINetworkInfo getInterfaceInfo(in long interfaceIndex);
-};
-
-[scriptable, uuid(21d7fc8b-28c4-4a4f-a15e-1f9defbc2cec)]
-interface nsINetworkInterfaceListService : nsISupports
-{
- const long LIST_NOT_INCLUDE_MMS_INTERFACES = (1 << 0);
- const long LIST_NOT_INCLUDE_SUPL_INTERFACES = (1 << 1);
- const long LIST_NOT_INCLUDE_IMS_INTERFACES = (1 << 2);
- const long LIST_NOT_INCLUDE_DUN_INTERFACES = (1 << 3);
- const long LIST_NOT_INCLUDE_FOTA_INTERFACES = (1 << 4);
-
- /**
- * Obtain a list of network interfaces that satisfy the specified condition.
- * @param condition flags that specify the interfaces to be returned. This
- * can be OR combination of LIST_* flags, or zero to make all available
- * interfaces returned.
- */
- nsINetworkInterfaceList getDataInterfaceList(in long condition);
-};
diff --git a/dom/system/gonk/nsINetworkManager.idl b/dom/system/gonk/nsINetworkManager.idl
deleted file mode 100644
index 0da123796..000000000
--- a/dom/system/gonk/nsINetworkManager.idl
+++ /dev/null
@@ -1,135 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsINetworkInfo;
-interface nsINetworkInterface;
-
-/**
- * Manage network interfaces.
- */
-[scriptable, uuid(1ba9346b-53b5-4660-9dc6-58f0b258d0a6)]
-interface nsINetworkManager : nsISupports
-{
- /**
- * Register the given network interface with the network manager.
- *
- * Consumers will be notified with the 'network-interface-registered'
- * observer notification.
- *
- * Throws if there's already an interface registered with the same network id.
- *
- * @param network
- * Network interface to register.
- */
- void registerNetworkInterface(in nsINetworkInterface network);
-
- /**
- * Update the routes and DNSes according the state of the given network.
- *
- * Consumers will be notified with the 'network-connection-state-changed'
- * observer notification.
- *
- * Throws an exception if the specified network interface object isn't
- * registered.
- *
- * @param network
- * Network interface to update.
- */
- void updateNetworkInterface(in nsINetworkInterface network);
-
- /**
- * Unregister the given network interface from the network manager.
- *
- * Consumers will be notified with the 'network-interface-unregistered'
- * observer notification.
- *
- * Throws an exception if the specified network interface object isn't
- * registered.
- *
- * @param network
- * Network interface to unregister.
- */
- void unregisterNetworkInterface(in nsINetworkInterface network);
-
- /**
- * Object containing all known network information, keyed by their
- * network id. Network id is composed of a sub-id + '-' + network
- * type. For mobile network types, sub-id is 'ril' + service id; for
- * non-mobile network types, sub-id is always 'device'.
- */
- readonly attribute jsval allNetworkInfo;
-
- /**
- * Priority list of network types. An array of
- * nsINetworkInterface::NETWORK_TYPE_* constants.
- *
- * The piror position of the type indicates the higher priority. The priority
- * is used to determine route when there are multiple connected networks.
- */
- attribute jsval networkTypePriorityList;
-
- /**
- * The preferred network type. One of the
- * nsINetworkInterface::NETWORK_TYPE_* constants.
- *
- * This attribute is used for setting default route to favor
- * interfaces with given type. This can be overriden by calling
- * overrideDefaultRoute().
- */
- attribute long preferredNetworkType;
-
- /**
- * The network information of the network interface handling all network
- * traffic.
- *
- * When this changes, the 'network-active-changed' observer
- * notification is dispatched.
- */
- readonly attribute nsINetworkInfo activeNetworkInfo;
-
- /**
- * Override the default behaviour for preferredNetworkType and route
- * all network traffic through the the specified interface.
- *
- * Consumers can observe changes to the active network by subscribing to
- * the 'network-active-changed' observer notification.
- *
- * @param network
- * Network to route all network traffic to. If this is null,
- * a previous override is canceled.
- */
- long overrideActive(in nsINetworkInterface network);
-
- /**
- * Add host route to the specified network into routing table.
- *
- * @param network
- * The network information for the host to be routed to.
- * @param host
- * The host to be added.
- * The host will be resolved in advance if it's not an ip-address.
- *
- * @return a Promise
- * resolved if added; rejected, otherwise.
- */
- jsval addHostRoute(in nsINetworkInfo network,
- in DOMString host);
-
- /**
- * Remove host route to the specified network from routing table.
- *
- * @param network
- * The network information for the routing to be removed from.
- * @param host
- * The host routed to the network.
- * The host will be resolved in advance if it's not an ip-address.
- *
- * @return a Promise
- * resolved if removed; rejected, otherwise.
- */
- jsval removeHostRoute(in nsINetworkInfo network,
- in DOMString host);
-};
diff --git a/dom/system/gonk/nsINetworkService.idl b/dom/system/gonk/nsINetworkService.idl
deleted file mode 100644
index 50a468494..000000000
--- a/dom/system/gonk/nsINetworkService.idl
+++ /dev/null
@@ -1,619 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, function, uuid(91824160-fb25-11e1-a21f-0800200c9a66)]
-interface nsIWifiTetheringCallback : nsISupports
-{
- /**
- * Callback function used to report status to WifiManager.
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void wifiTetheringEnabledChange(in jsval error);
-};
-
-[scriptable, function, uuid(9c128e68-5e4b-4626-bb88-84ec54cce5d8)]
-interface nsINetworkStatsCallback : nsISupports
-{
- void networkStatsAvailable(in boolean success,
- in unsigned long rxBytes,
- in unsigned long txBytes,
- in unsigned long long timestamp);
-};
-
-[scriptable, function, uuid(0706bfa2-ac2d-11e2-9a8d-7b6d988d4767)]
-interface nsINetworkUsageAlarmCallback : nsISupports
-{
- void networkUsageAlarmResult(in jsval error);
-};
-
-[scriptable, function, uuid(9ede8720-f8bc-11e2-b778-0800200c9a66)]
-interface nsIWifiOperationModeCallback : nsISupports
-{
- /**
- * Callback function used to report result to WifiManager.
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void wifiOperationModeResult(in jsval error);
-};
-
-[scriptable, function, uuid(097878b0-19fc-11e3-8ffd-0800200c9a66)]
-interface nsISetDhcpServerCallback : nsISupports
-{
- /**
- * Callback function used to report the DHCP server set result
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void dhcpServerResult(in jsval error);
-};
-
-[scriptable, function, uuid(32407c50-46c7-11e3-8f96-0800200c9a66)]
-interface nsIUsbTetheringCallback : nsISupports
-{
- /**
- * Callback function used to report status of enabling usb tethering.
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void usbTetheringEnabledChange(in jsval error);
-};
-
-[scriptable, function, uuid(055fd560-46ad-11e3-8f96-0800200c9a66)]
-interface nsIEnableUsbRndisCallback : nsISupports
-{
- /**
- * Callback function used to report the status of enabling/disabling usb rndis.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- * @param enable
- * Boolean to indicate if we are enabling or disabling usb rndis.
- */
- void enableUsbRndisResult(in boolean success, in boolean enable);
-};
-
-[scriptable, function, uuid(4f08cc30-46ad-11e3-8f96-0800200c9a66)]
-interface nsIUpdateUpStreamCallback : nsISupports
-{
- /**
- * Callback function used to report the result of updating upstream.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- * @param externalIfname
- * The external interface name.
- */
- void updateUpStreamResult(in boolean success, in DOMString externalIfname);
-};
-
-[scriptable, function, uuid(eedca6c0-1310-11e4-9191-0800200c9a66)]
-interface nsISetDnsCallback : nsISupports
-{
- /**
- * Callback function used to report the result of setting DNS server.
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void setDnsResult(in jsval error);
-};
-
-[scriptable, function, uuid(5d0e1a60-1187-11e4-9191-0800200c9a66)]
-interface nsINativeCommandCallback : nsISupports
-{
- /**
- * Callback function used to report the result of a network native command.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- */
- void nativeCommandResult(in boolean success);
-};
-
-[scriptable, function, uuid(694abb80-1187-11e4-9191-0800200c9a66)]
-interface nsIDhcpRequestCallback : nsISupports
-{
- /**
- * Callback function used to report the result of DHCP client request.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- *
- * @param dhcpInfo
- * An object to represent the successful DHCP request:
- *
- * - gateway_str: string
- * - dns1_str: string
- * - dns2_str: string
- * - mask_str: string
- * - server_str: string
- * - vendor_str: string
- * - lease: long
- * - mask: long
- * - ipaddr: long
- * - gateway: long
- * - dns1: long
- * - dns2: long
- * - server: long
- */
- void dhcpRequestResult(in boolean success, in jsval dhcpInfo);
-};
-
-[scriptable, function, uuid(88e3ee22-f1b3-4fa0-8a5d-793fb827c42c)]
-interface nsIGetInterfacesCallback : nsISupports
-{
- /**
- * Callback function used to return the list of existing network interfaces.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- * @param interfaceList
- * An array of interface name.
- */
- void getInterfacesResult(in boolean success, in jsval interfaceList);
-};
-
-[scriptable, function, uuid(064e02a3-d2c0-42c5-a293-1efa84056100)]
-interface nsIGetInterfaceConfigCallback : nsISupports
-{
- /**
- * Callback function used to return the network config of a given interface.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- * @param result
- * .ip: Ip address.
- * .prefix: mask length.
- * .link: network link properties.
- * .mac: mac address.
- */
- void getInterfaceConfigResult(in boolean success, in jsval result);
-};
-
-[scriptable, function, uuid(b370f360-6ba8-4517-a4f9-31e8f004ee91)]
-interface nsISetInterfaceConfigCallback : nsISupports
-{
- /**
- * Callback function used to set network config for a specified interface.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- */
- void setInterfaceConfigResult(in boolean success);
-};
-
-/**
- * Provide network services.
- */
-[scriptable, uuid(e16fe98f-9f63-48fe-82ba-8d1a1b7c6a57)]
-interface nsINetworkService : nsISupports
-{
- const long MODIFY_ROUTE_ADD = 0;
- const long MODIFY_ROUTE_REMOVE = 1;
-
- /**
- * Enable or disable Wifi Tethering
- *
- * @param enabled
- * Boolean that indicates whether tethering should be enabled (true) or disabled (false).
- * @param config
- * The Wifi Tethering configuration from settings db.
- * @param callback
- * Callback function used to report status to WifiManager.
- */
- void setWifiTethering(in boolean enabled,
- in jsval config,
- in nsIWifiTetheringCallback callback);
-
- /**
- * Enable or disable DHCP server
- *
- * @param enabled
- * Boolean that indicates enabling or disabling DHCP server.
- *
- * @param config
- * Config used to enable the DHCP server. It contains
- * .startIp start of the ip lease range (string)
- * .endIp end of the ip lease range (string)
- * .serverIp ip of the DHCP server (string)
- * .maskLength the length of the subnet mask
- * .ifname the interface name
- *
- * As for disabling the DHCP server, put this value |null|.
- *
- * @param callback
- * Callback function used to report status.
- */
- void setDhcpServer(in boolean enabled,
- in jsval config,
- in nsISetDhcpServerCallback callback);
-
-
- /**
- * Retrieve network interface stats.
- *
- * @param networkName
- * Select the Network interface to request estats.
- *
- * @param callback
- * Callback to notify result and provide stats, connectionType
- * and the date when stats are retrieved
- */
- void getNetworkInterfaceStats(in DOMString networkName, in nsINetworkStatsCallback callback);
-
- /**
- * Set Alarm of usage per interface
- *
- * @param networkName
- * Select the Network interface to set an alarm.
- *
- * @param threshold
- * Amount of data that will trigger the alarm.
- *
- * @param callback
- * Callback to notify the result.
- *
- * @return false if there is no interface registered for the networkType param.
- */
- boolean setNetworkInterfaceAlarm(in DOMString networkName,
- in long long threshold,
- in nsINetworkUsageAlarmCallback callback);
-
- /**
- * Reload Wifi firmware to specific operation mode.
- *
- * @param interfaceName
- * Wifi Network interface name.
- *
- * @param mode
- * AP - Access pointer mode.
- * P2P - Peer to peer connection mode.
- * STA - Station mode.
- *
- * @param callback
- * Callback to notify Wifi firmware reload result.
- */
- void setWifiOperationMode(in DOMString interfaceName,
- in DOMString mode,
- in nsIWifiOperationModeCallback callback);
-
- /**
- * Set USB tethering.
- *
- * @param enabled
- * Boolean to indicate we are going to enable or disable usb tethering.
- * @param config
- * The usb tethering configuration.
- * @param callback
- * Callback function used to report the result enabling/disabling usb tethering.
- */
- void setUSBTethering(in boolean enabled,
- in jsval config,
- in nsIUsbTetheringCallback callback);
-
- /**
- * Reset routing table.
- *
- * @param interfaceName
- * The name of the network interface we want to remove from the routing
- * table.
- *
- * @param callback
- * Callback to notify the result of resetting routing table.
- */
- void resetRoutingTable(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Set DNS.
- *
- * @param interfaceName
- * The network interface name of the DNS we want to set.
- * @param dnsesCount
- * Number of elements in dnses.
- * @param dnses
- * Dnses to set.
- * @param gatewaysCount
- * Number of elements in gateways.
- * @param gateways
- * Gateways for the dnses, the most suitable, usually the one with the
- * same address family, will be selected for each dns.
- *
- * @param callback
- * Callback to notify the result of setting DNS server.
- */
- void setDNS(in DOMString interfaceName,
- in unsigned long dnsesCount,
- [array, size_is(dnsesCount)] in wstring dnses,
- in unsigned long gatewaysCount,
- [array, size_is(gatewaysCount)] in wstring gateways,
- in nsISetDnsCallback callback);
-
- /**
- * Set default route.
- *
- * @param interfaceName
- * The network interface name of the default route we want to set.
- * @param count
- * Number of elements in gateways.
- * @param gateways
- * Default gateways for setting default route.
- *
- * @param callback
- * Callback to notify the result of setting default route.
- */
- void setDefaultRoute(in DOMString interfaceName,
- in unsigned long count,
- [array, size_is(count)] in wstring gateways,
- in nsINativeCommandCallback callback);
-
- /**
- * Remove default route.
- *
- * @param interfaceName
- * The network interface name of the default route we want to remove.
- * @param count
- * Number of elements in gateways.
- * @param gatways
- * Default gateways for removing default route.
- *
- * @param callback
- * Callback to notify the result of removing default route.
- */
- void removeDefaultRoute(in DOMString interfaceName,
- in unsigned long count,
- [array, size_is(count)] in wstring gateways,
- in nsINativeCommandCallback callback);
-
- /**
- * Modify route.
- *
- * @param action
- * nsINetworkService.MODIFY_ROUTE_ADD to add route and
- * nsINetworkService.MODIFY_ROUTE_REMOVE to remove.
- * @param interfaceName
- * Network interface name for the output of the host route.
- * @param host
- * Host ip we want to remove route for.
- * @param prefixLength
- * The prefix length of the route we'd like to modify.
- * @param [optional] gateway
- * Gateway ip for the output of the host route.
- *
- * @return A deferred promise that resolves on success or rejects with a
- * specified reason otherwise.
- */
- jsval modifyRoute(in long action,
- in DOMString interfaceName,
- in DOMString host,
- in long prefixLength,
- [optional] in DOMString gateway);
-
- /**
- * Add route to secondary routing table.
- *
- * @param interfaceName
- * The network interface for this route.
- * @param route
- * The route info should have the following fields:
- * .ip: destination ip address
- * .prefix: destination prefix
- * .gateway: gateway ip address
- */
- void addSecondaryRoute(in DOMString interfaceName, in jsval route,
- in nsINativeCommandCallback callback);
-
- /**
- * Remove route from secondary routing table.
- *
- * @param interfaceName
- * The network interface for the route we want to remove.
- * @param route
- * The route info should have the following fields:
- * .ip: destination ip address
- * .prefix: destination prefix
- * .gateway: gateway ip address
- */
- void removeSecondaryRoute(in DOMString interfaceName, in jsval route,
- in nsINativeCommandCallback callback);
-
- /**
- * Enable or disable usb rndis.
- *
- * @param enable
- * Boolean to indicate we want enable or disable usb rndis.
- * @param callback
- * Callback function to report the result.
- */
- void enableUsbRndis(in boolean enable,
- in nsIEnableUsbRndisCallback callback);
-
- /**
- * Update upstream.
- *
- * @param previous
- * The previous internal and external interface.
- * @param current
- * The current internal and external interface.
- * @param callback
- * Callback function to report the result.
- */
- void updateUpStream(in jsval previous,
- in jsval current,
- in nsIUpdateUpStreamCallback callback);
-
- /*
- * Obtain interfaces list.
- *
- * @param callback
- * Callback function to return the result.
- */
- void getInterfaces(in nsIGetInterfacesCallback callback);
-
- /**
- * Get config of a network interface.
- *
- * @param ifname
- * Target interface.
- * @param callback
- * Callback function to report the result.
- */
- void getInterfaceConfig(in DOMString ifname, in nsIGetInterfaceConfigCallback callback);
-
- /**
- * Set config for a network interface.
- *
- * @param config
- * .ifname: Target interface.
- * .ip: Ip address.
- * .prefix: mask length.
- * .link: network link properties.
- * @param callback
- * Callback function to report the result.
- */
- void setInterfaceConfig(in jsval config, in nsISetInterfaceConfigCallback callback);
-
- /**
- * Configure a network interface.
- *
- * @param config
- * An object containing the detail that we want to configure the interface:
- *
- * - ifname: string
- * - ipaddr: long
- * - mask: long
- * - gateway: long
- * - dns1: long
- * - dns2: long
- *
- * @param callback
- * Callback to notify the result of configurating network interface.
- */
- void configureInterface(in jsval config,
- in nsINativeCommandCallback callback);
-
- /**
- * Issue a DHCP client request.
- *
- * @param networkInterface
- * The network interface which we wnat to do the DHCP request on.
- *
- * @param callback
- * Callback to notify the result of the DHCP request.
- */
- void dhcpRequest(in DOMString interfaceName,
- in nsIDhcpRequestCallback callback);
-
- /**
- * Stop Dhcp daemon.
- *
- * @param ifname
- * Target interface.
- *
- * @param callback
- * Callback to notify the result of stopping dhcp request.
- */
- void stopDhcp(in DOMString ifname,
- in nsINativeCommandCallback callback);
-
- /**
- * Enable a network interface.
- *
- * @param networkInterface
- * The network interface name which we want to enable.
- *
- * @param callback
- * Callback to notify the result of disabling network interface.
- */
- void enableInterface(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Disable a network interface.
- *
- * @param networkInterface
- * The network interface name which we want to disable.
- *
- * @param callback
- * Callback to notify the result of disabling network interface.
- */
- void disableInterface(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Reset all connections on a specified network interface.
- *
- * @param interfaceName
- * The network interface name which we want to reset.
- *
- * @param callback
- * Callback to notify the result of resetting connections.
- */
- void resetConnections(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Create network (required to call prior to any networking operation).
- *
- * @param interfaceName
- * The network interface name which we want to create network for.
- *
- * @param callback
- * Callback to notify the result of creating network.
- */
- void createNetwork(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Destroy network.
- *
- * @param interfaceName
- * The network interface name of the network we want to destroy.
- *
- * @param callback
- * Callback to notify the result of destroying network.
- */
- void destroyNetwork(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Query the netId associated with given network interface name.
- *
- * @param interfaceName
- * The network interface name which we want to query.
- *
- * @return A deferred promise that resolves with a string to indicate.
- * the queried netId on success and rejects if the interface name
- * is invalid.
- *
- */
- jsval getNetId(in DOMString interfaceName);
-
- /**
- * Set maximum transmission unit on a network interface.
- *
- * @param interfaceName
- * The name of the network interface that we want to set mtu.
- * @param mtu
- * Size of maximum tranmission unit.
- *
- * @param callback
- * Callback to notify the result of setting mtu.
- */
- void setMtu(in DOMString interfaceName, in long mtu,
- in nsINativeCommandCallback callback);
-};
diff --git a/dom/system/gonk/nsINetworkWorker.idl b/dom/system/gonk/nsINetworkWorker.idl
deleted file mode 100644
index 8fe19be69..000000000
--- a/dom/system/gonk/nsINetworkWorker.idl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(98e31d3b-6cad-4cab-b4b3-4afff566ea65)]
-interface nsINetworkEventListener : nsISupports {
- void onEvent(in jsval result);
-};
-
-[scriptable, uuid(f9d9c694-0aac-4f9a-98ac-7788f954239a)]
-interface nsINetworkWorker : nsISupports {
- void start(in nsINetworkEventListener listener);
- void shutdown();
- [implicit_jscontext]
- void postMessage(in jsval options);
-};
diff --git a/dom/system/gonk/nsIRadioInterfaceLayer.idl b/dom/system/gonk/nsIRadioInterfaceLayer.idl
deleted file mode 100644
index 168fe3894..000000000
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ /dev/null
@@ -1,53 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIIccInfo;
-interface nsIMobileConnectionInfo;
-interface nsIMobileMessageCallback;
-
-[scriptable, function, uuid(3bc96351-53b0-47a1-a888-c74c64b60f25)]
-interface nsIRilSendWorkerMessageCallback : nsISupports
-{
- boolean handleResponse(in jsval response);
-};
-
-[scriptable, uuid(1a3ef88a-e4d1-11e4-8512-176220f2b32b)]
-interface nsIRadioInterface : nsISupports
-{
- /**
- * PDP APIs
- *
- * @param networkType
- * Mobile network type, that is, nsINetworkInterface.NETWORK_TYPE_MOBILE
- * or one of the nsINetworkInterface.NETWORK_TYPE_MOBILE_* values.
- */
- void setupDataCallByType(in long networkType);
- void deactivateDataCallByType(in long networkType);
- long getDataCallStateByType(in long networkType);
-
- void updateRILNetworkInterface();
-
- void sendWorkerMessage(in DOMString type,
- [optional] in jsval message,
- [optional] in nsIRilSendWorkerMessageCallback callback);
-};
-
-%{C++
-#define NS_RADIOINTERFACELAYER_CID \
- { 0x2d831c8d, 0x6017, 0x435b, \
- { 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } }
-#define NS_RADIOINTERFACELAYER_CONTRACTID "@mozilla.org/ril;1"
-%}
-
-[scriptable, uuid(09730e0d-75bb-4f21-8540-062a2eadc8ff)]
-interface nsIRadioInterfaceLayer : nsISupports
-{
- readonly attribute unsigned long numRadioInterfaces;
-
- nsIRadioInterface getRadioInterface(in unsigned long clientId);
-
- void setMicrophoneMuted(in boolean muted);
-};
diff --git a/dom/system/gonk/nsISystemWorkerManager.idl b/dom/system/gonk/nsISystemWorkerManager.idl
deleted file mode 100644
index a77e253e4..000000000
--- a/dom/system/gonk/nsISystemWorkerManager.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-/**
- * Information about networks that is exposed to network manager API consumers.
- */
-[scriptable, builtinclass, uuid(4984b669-0ee0-4809-ae96-3358a325a6b0)]
-interface nsISystemWorkerManager : nsISupports
-{
- [implicit_jscontext]
- void registerRilWorker(in unsigned long aClientId,
- in jsval aWorker);
-};
diff --git a/dom/system/gonk/nsITetheringService.idl b/dom/system/gonk/nsITetheringService.idl
deleted file mode 100644
index 530ab0069..000000000
--- a/dom/system/gonk/nsITetheringService.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsINetworkInterface;
-interface nsIWifiTetheringCallback;
-
-[scriptable, uuid(779de2d3-6d29-4ee6-b069-6251839f757a)]
-interface nsITetheringService : nsISupports
-{
- const long TETHERING_STATE_INACTIVE = 0;
- const long TETHERING_STATE_WIFI = 1;
- const long TETHERING_STATE_USB = 2;
-
- /**
- * Current tethering state. One of the TETHERING_STATE_* constants.
- */
- readonly attribute long state;
-
- /**
- * Enable or disable Wifi Tethering.
- *
- * @param enabled
- * Boolean that indicates whether tethering should be enabled (true) or
- * disabled (false).
- * @param interfaceName
- * The Wifi network interface name for internal interface.
- * @param config
- * The Wifi Tethering configuration from settings db.
- * @param callback
- * Callback function used to report status to WifiManager.
- */
- void setWifiTethering(in boolean enabled,
- in DOMString interfaceName,
- in jsval config,
- in nsIWifiTetheringCallback callback);
-}; \ No newline at end of file
diff --git a/dom/system/gonk/nsIVolume.idl b/dom/system/gonk/nsIVolume.idl
deleted file mode 100644
index 60785f0a4..000000000
--- a/dom/system/gonk/nsIVolume.idl
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsIVolumeStat.idl"
-
-[scriptable, uuid(EE752CB8-8FD7-11E4-A602-70221D5D46B0)]
-interface nsIVolume : nsISupports
-{
- // These MUST match the states from android's system/vold/Volume.h header
- // Note: Changes made to the STATE_xxx names should also be reflected in the
- // NS_VolumeStateStr function found in Volume.cpp
- const long STATE_INIT = -1;
- const long STATE_NOMEDIA = 0;
- const long STATE_IDLE = 1;
- const long STATE_PENDING = 2;
- const long STATE_CHECKING = 3;
- const long STATE_MOUNTED = 4;
- const long STATE_UNMOUNTING = 5;
- const long STATE_FORMATTING = 6;
- const long STATE_SHARED = 7;
- const long STATE_SHAREDMNT = 8;
- const long STATE_CHECKMNT = 100;
- const long STATE_MOUNT_FAIL = 101;
-
- // The name of the volume. Often there is only one volume, called sdcard.
- // But some phones support multiple volumes.
- readonly attribute DOMString name;
-
- // The mount point is the path on the system where the volume is mounted
- // and is only valid when state == STATE_MOUNTED.
- readonly attribute DOMString mountPoint;
-
- // Reflects the current state of the volume, using STATE_xxx constants
- // from above.
- readonly attribute long state;
-
- // mountGeneration is a unique number which is used distinguish between
- // periods of time that a volume is in the mounted state. Each time a
- // volume transitions to the mounted state, the mountGeneration will
- // be different from the last time it transitioned to the mounted state.
- readonly attribute long mountGeneration;
-
- // While a volume is mounted, it can be locked, preventing it from being
- // shared with the PC. To lock a volume, acquire an MozWakeLock
- // using the name of this attribute. Note that mountLockName changes
- // every time the mountGeneration changes, so you'll need to reacquire
- // the wakelock every time the volume becomes mounted.
- readonly attribute DOMString mountLockName;
-
- // Determines if a mountlock is currently being held against this volume.
- readonly attribute boolean isMountLocked;
-
- // Determines if media is actually present or not. Note, that when an sdcard
- // is ejected, it may go through several tranistory states before finally
- // arriving at STATE_NOMEDIA. So isMediaPresent may be false even when the
- // current state isn't STATE_NOMEDIA.
- readonly attribute boolean isMediaPresent;
-
- // Determines if the volume is currently being shared. This covers off
- // more than just state == STATE_SHARED. isSharing will return true from the
- // time that the volume leaves the mounted state, until it gets back to
- // mounted, nomedia, or formatting states. This attribute is to allow
- // device storage to suppress unwanted 'unavailable' status when
- // transitioning from mounted to sharing and back again.
- readonly attribute boolean isSharing;
-
- // Determines if the volume is currently formatting. This sets true once
- // mFormatRequest == true and mState == STATE_MOUNTED, and sets false
- // once the volume has been formatted and mounted again.
- readonly attribute boolean isFormatting;
-
- readonly attribute boolean isUnmounting;
-
- nsIVolumeStat getStats();
-
- // Formats the volume in IO thread, if the volume is ready to be formatted.
- // Automounter will unmount it, format it and then mount it again.
- void format();
-
- // Mounts the volume in IO thread, if the volume is already unmounted.
- // Automounter will mount it. Otherwise Automounter will skip this.
- void mount();
-
- // Unmounts the volume in IO thread, if the volume is already mounted.
- // Automounter will unmount it. Otherwise Automounter will skip this.
- void unmount();
-
- // Whether this is a fake volume.
- readonly attribute boolean isFake;
-
- // Whether this is a removable volume
- readonly attribute boolean isRemovable;
-
- // Whether this is a hot-swappable volume
- readonly attribute boolean isHotSwappable;
-
-};
-
-%{C++
-// For use with the ObserverService
-#define NS_VOLUME_STATE_CHANGED "volume-state-changed"
-#define NS_VOLUME_REMOVED "volume-removed"
-
-namespace mozilla {
-namespace system {
-
-// Convert a state into a loggable/printable string.
-const char* NS_VolumeStateStr(int32_t aState);
-
-} // system
-} // mozilla
-%}
diff --git a/dom/system/gonk/nsIVolumeMountLock.idl b/dom/system/gonk/nsIVolumeMountLock.idl
deleted file mode 100644
index 0a9a1a5c2..000000000
--- a/dom/system/gonk/nsIVolumeMountLock.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(44449f34-5ca1-4aff-bce6-22c79263de24)]
-interface nsIVolumeMountLock : nsISupports
-{
- void unlock();
-};
-
diff --git a/dom/system/gonk/nsIVolumeService.idl b/dom/system/gonk/nsIVolumeService.idl
deleted file mode 100644
index d3752e201..000000000
--- a/dom/system/gonk/nsIVolumeService.idl
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsIVolume.idl"
-#include "nsIVolumeMountLock.idl"
-
-interface nsIArray;
-
-[scriptable, uuid(cfbf9880-cba5-11e4-8830-0800200c9a66)]
-interface nsIVolumeService : nsISupports
-{
- nsIVolume getVolumeByName(in DOMString volName);
- nsIVolume getVolumeByPath(in DOMString path);
- nsIVolume createOrGetVolumeByPath(in DOMString path);
-
- nsIVolumeMountLock createMountLock(in DOMString volName);
-
- nsIArray getVolumeNames();
-
- void Dump(in DOMString label);
-
- /* for test case only to simulate sdcard insertion/removal */
- void createFakeVolume(in DOMString name, in DOMString path);
- void SetFakeVolumeState(in DOMString name, in long state);
-
- /* for test case only to test removal of storage area */
- void removeFakeVolume(in DOMString name);
-};
-
-%{C++
-#define NS_VOLUMESERVICE_CID \
- {0x7c179fb7, 0x67a0, 0x43a3, {0x93, 0x37, 0x29, 0x4e, 0x03, 0x60, 0xb8, 0x58}}
-#define NS_VOLUMESERVICE_CONTRACTID "@mozilla.org/telephony/volume-service;1"
-%}
diff --git a/dom/system/gonk/nsIVolumeStat.idl b/dom/system/gonk/nsIVolumeStat.idl
deleted file mode 100644
index 1d725689d..000000000
--- a/dom/system/gonk/nsIVolumeStat.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(b4c050d0-c57a-11e1-9b21-0800200c9a66)]
-interface nsIVolumeStat : nsISupports
-{
- readonly attribute long long totalBytes;
- readonly attribute long long freeBytes;
-};
diff --git a/dom/system/gonk/nsIWorkerHolder.idl b/dom/system/gonk/nsIWorkerHolder.idl
deleted file mode 100644
index e5cc82c9e..000000000
--- a/dom/system/gonk/nsIWorkerHolder.idl
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(c04f3102-1ce8-4d57-9c27-8aece9c2740a)]
-interface nsIWorkerHolder : nsISupports
-{
- readonly attribute jsval worker;
-};
diff --git a/dom/system/gonk/nsVolume.cpp b/dom/system/gonk/nsVolume.cpp
deleted file mode 100644
index 77a1628e4..000000000
--- a/dom/system/gonk/nsVolume.cpp
+++ /dev/null
@@ -1,467 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsVolume.h"
-
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "nsIPowerManagerService.h"
-#include "nsISupportsUtils.h"
-#include "nsIVolume.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "nsVolumeStat.h"
-#include "nsXULAppAPI.h"
-#include "Volume.h"
-#include "AutoMounter.h"
-#include "VolumeManager.h"
-
-#undef VOLUME_MANAGER_LOG_TAG
-#define VOLUME_MANAGER_LOG_TAG "nsVolume"
-#include "VolumeManagerLog.h"
-
-namespace mozilla {
-namespace system {
-
-const char *
-NS_VolumeStateStr(int32_t aState)
-{
- switch (aState) {
- case nsIVolume::STATE_INIT: return "Init";
- case nsIVolume::STATE_NOMEDIA: return "NoMedia";
- case nsIVolume::STATE_IDLE: return "Idle";
- case nsIVolume::STATE_PENDING: return "Pending";
- case nsIVolume::STATE_CHECKING: return "Checking";
- case nsIVolume::STATE_MOUNTED: return "Mounted";
- case nsIVolume::STATE_UNMOUNTING: return "Unmounting";
- case nsIVolume::STATE_FORMATTING: return "Formatting";
- case nsIVolume::STATE_SHARED: return "Shared";
- case nsIVolume::STATE_SHAREDMNT: return "Shared-Mounted";
- case nsIVolume::STATE_CHECKMNT: return "Check-Mounted";
- case nsIVolume::STATE_MOUNT_FAIL: return "Mount-Fail";
- }
- return "???";
-}
-
-// While nsVolumes can only be used on the main thread, in the
-// UpdateVolumeRunnable constructor (which is called from IOThread) we
-// allocate an nsVolume which is then passed to MainThread. Since we
-// have a situation where we allocate on one thread and free on another
-// we use a thread safe AddRef implementation.
-NS_IMPL_ISUPPORTS(nsVolume, nsIVolume)
-
-nsVolume::nsVolume(const Volume* aVolume)
- : mName(NS_ConvertUTF8toUTF16(aVolume->Name())),
- mMountPoint(NS_ConvertUTF8toUTF16(aVolume->MountPoint())),
- mState(aVolume->State()),
- mMountGeneration(aVolume->MountGeneration()),
- mMountLocked(aVolume->IsMountLocked()),
- mIsFake(!aVolume->CanBeShared()),
- mIsMediaPresent(aVolume->MediaPresent()),
- mIsSharing(aVolume->IsSharing()),
- mIsFormatting(aVolume->IsFormatting()),
- mIsUnmounting(aVolume->IsUnmounting()),
- mIsRemovable(aVolume->IsRemovable()),
- mIsHotSwappable(aVolume->IsHotSwappable())
-{
-}
-
-nsVolume::nsVolume(const nsVolume* aVolume)
- : mName(aVolume->mName),
- mMountPoint(aVolume->mMountPoint),
- mState(aVolume->mState),
- mMountGeneration(aVolume->mMountGeneration),
- mMountLocked(aVolume->mMountLocked),
- mIsFake(aVolume->mIsFake),
- mIsMediaPresent(aVolume->mIsMediaPresent),
- mIsSharing(aVolume->mIsSharing),
- mIsFormatting(aVolume->mIsFormatting),
- mIsUnmounting(aVolume->mIsUnmounting),
- mIsRemovable(aVolume->mIsRemovable),
- mIsHotSwappable(aVolume->mIsHotSwappable)
-{
-}
-
-void nsVolume::Dump(const char* aLabel) const
-{
- LOG("%s: Volume: %s is %s and %s @ %s gen %d locked %d",
- aLabel,
- NameStr().get(),
- StateStr(),
- IsMediaPresent() ? "inserted" : "missing",
- MountPointStr().get(),
- MountGeneration(),
- (int)IsMountLocked());
- LOG("%s: IsSharing %s IsFormating %s IsUnmounting %s",
- aLabel,
- (IsSharing() ? "y" : "n"),
- (IsFormatting() ? "y" : "n"),
- (IsUnmounting() ? "y" : "n"));
-}
-
-bool nsVolume::Equals(nsIVolume* aVolume)
-{
- nsString volName;
- aVolume->GetName(volName);
- if (!mName.Equals(volName)) {
- return false;
- }
-
- nsString volMountPoint;
- aVolume->GetMountPoint(volMountPoint);
- if (!mMountPoint.Equals(volMountPoint)) {
- return false;
- }
-
- int32_t volState;
- aVolume->GetState(&volState);
- if (mState != volState){
- return false;
- }
-
- int32_t volMountGeneration;
- aVolume->GetMountGeneration(&volMountGeneration);
- if (mMountGeneration != volMountGeneration) {
- return false;
- }
-
- bool volIsMountLocked;
- aVolume->GetIsMountLocked(&volIsMountLocked);
- if (mMountLocked != volIsMountLocked) {
- return false;
- }
-
- bool isFake;
- aVolume->GetIsFake(&isFake);
- if (mIsFake != isFake) {
- return false;
- }
-
- bool isSharing;
- aVolume->GetIsSharing(&isSharing);
- if (mIsSharing != isSharing) {
- return false;
- }
-
- bool isFormatting;
- aVolume->GetIsFormatting(&isFormatting);
- if (mIsFormatting != isFormatting) {
- return false;
- }
-
- bool isUnmounting;
- aVolume->GetIsUnmounting(&isUnmounting);
- if (mIsUnmounting != isUnmounting) {
- return false;
- }
-
- bool isRemovable;
- aVolume->GetIsRemovable(&isRemovable);
- if (mIsRemovable != isRemovable) {
- return false;
- }
-
- bool isHotSwappable;
- aVolume->GetIsHotSwappable(&isHotSwappable);
- if (mIsHotSwappable != isHotSwappable) {
- return false;
- }
-
- return true;
-}
-
-NS_IMETHODIMP nsVolume::GetIsMediaPresent(bool* aIsMediaPresent)
-{
- *aIsMediaPresent = mIsMediaPresent;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsMountLocked(bool* aIsMountLocked)
-{
- *aIsMountLocked = mMountLocked;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsSharing(bool* aIsSharing)
-{
- *aIsSharing = mIsSharing;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsFormatting(bool* aIsFormatting)
-{
- *aIsFormatting = mIsFormatting;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsUnmounting(bool* aIsUnmounting)
-{
- *aIsUnmounting = mIsUnmounting;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetName(nsAString& aName)
-{
- aName = mName;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetMountGeneration(int32_t* aMountGeneration)
-{
- *aMountGeneration = mMountGeneration;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetMountLockName(nsAString& aMountLockName)
-{
- aMountLockName = NS_LITERAL_STRING("volume-") + Name();
- aMountLockName.AppendPrintf("-%d", mMountGeneration);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetMountPoint(nsAString& aMountPoint)
-{
- aMountPoint = mMountPoint;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetState(int32_t* aState)
-{
- *aState = mState;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetStats(nsIVolumeStat **aResult)
-{
- if (mState != STATE_MOUNTED) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- NS_IF_ADDREF(*aResult = new nsVolumeStat(mMountPoint));
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsFake(bool *aIsFake)
-{
- *aIsFake = mIsFake;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsRemovable(bool *aIsRemovable)
-{
- *aIsRemovable = mIsRemovable;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsHotSwappable(bool *aIsHotSwappable)
-{
- *aIsHotSwappable = mIsHotSwappable;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::Format()
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(FormatVolumeIOThread, NameStr()));
-
- return NS_OK;
-}
-
-/* static */
-void nsVolume::FormatVolumeIOThread(const nsCString& aVolume)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
-
- AutoMounterFormatVolume(aVolume);
-}
-
-NS_IMETHODIMP nsVolume::Mount()
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(MountVolumeIOThread, NameStr()));
-
- return NS_OK;
-}
-
-/* static */
-void nsVolume::MountVolumeIOThread(const nsCString& aVolume)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
-
- AutoMounterMountVolume(aVolume);
-}
-
-NS_IMETHODIMP nsVolume::Unmount()
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(UnmountVolumeIOThread, NameStr()));
-
- return NS_OK;
-}
-
-/* static */
-void nsVolume::UnmountVolumeIOThread(const nsCString& aVolume)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
-
- AutoMounterUnmountVolume(aVolume);
-}
-
-void
-nsVolume::LogState() const
-{
- if (mState == nsIVolume::STATE_MOUNTED) {
- LOG("nsVolume: %s state %s @ '%s' gen %d locked %d fake %d "
- "media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
- NameStr().get(), StateStr(), MountPointStr().get(),
- MountGeneration(), (int)IsMountLocked(), (int)IsFake(),
- (int)IsMediaPresent(), (int)IsSharing(),
- (int)IsFormatting(), (int)IsUnmounting(),
- (int)IsRemovable(), (int)IsHotSwappable());
- return;
- }
-
- LOG("nsVolume: %s state %s", NameStr().get(), StateStr());
-}
-
-void nsVolume::UpdateMountLock(nsVolume* aOldVolume)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- bool oldMountLocked = aOldVolume ? aOldVolume->mMountLocked : false;
- if (mState != nsIVolume::STATE_MOUNTED) {
- // Since we're not in the mounted state, we need to
- // forgot whatever mount generation we may have had.
- mMountGeneration = -1;
- mMountLocked = oldMountLocked;
- return;
- }
-
- int32_t oldMountGeneration = aOldVolume ? aOldVolume->mMountGeneration : -1;
- if (mMountGeneration == oldMountGeneration) {
- // No change in mount generation, nothing else to do
- mMountLocked = oldMountLocked;
- return;
- }
-
- if (!XRE_IsParentProcess()) {
- // Child processes just track the state, not maintain it.
- return;
- }
-
- // Notify the Volume on IOThread whether the volume is locked or not.
- nsCOMPtr<nsIPowerManagerService> pmService =
- do_GetService(POWERMANAGERSERVICE_CONTRACTID);
- if (!pmService) {
- return;
- }
- nsString mountLockName;
- GetMountLockName(mountLockName);
- nsString mountLockState;
- pmService->GetWakeLockState(mountLockName, mountLockState);
- UpdateMountLock(mountLockState);
-}
-
-void
-nsVolume::UpdateMountLock(const nsAString& aMountLockState)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
-
- // There are 3 states, unlocked, locked-background, and locked-foreground
- // I figured it was easier to use negtive logic and compare for unlocked.
- UpdateMountLock(!aMountLockState.EqualsLiteral("unlocked"));
-}
-
-void
-nsVolume::UpdateMountLock(bool aMountLocked)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
-
- if (aMountLocked == mMountLocked) {
- return;
- }
- // The locked/unlocked state changed. Tell IOThread about it.
- mMountLocked = aMountLocked;
- LogState();
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(Volume::UpdateMountLock,
- NS_LossyConvertUTF16toASCII(Name()),
- MountGeneration(), aMountLocked));
-}
-
-void
-nsVolume::SetIsFake(bool aIsFake)
-{
- mIsFake = aIsFake;
- if (mIsFake) {
- // The media is always present for fake volumes.
- mIsMediaPresent = true;
- MOZ_ASSERT(!mIsSharing);
- }
-}
-
-void
-nsVolume::SetIsRemovable(bool aIsRemovable)
-{
- mIsRemovable = aIsRemovable;
- if (!mIsRemovable) {
- mIsHotSwappable = false;
- }
-}
-
-void
-nsVolume::SetIsHotSwappable(bool aIsHotSwappable)
-{
- mIsHotSwappable = aIsHotSwappable;
- if (mIsHotSwappable) {
- mIsRemovable = true;
- }
-}
-
-void
-nsVolume::SetState(int32_t aState)
-{
- static int32_t sMountGeneration = 0;
-
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(IsFake());
-
- if (aState == mState) {
- return;
- }
-
- if (aState == nsIVolume::STATE_MOUNTED) {
- mMountGeneration = ++sMountGeneration;
- }
-
- mState = aState;
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/nsVolume.h b/dom/system/gonk/nsVolume.h
deleted file mode 100644
index 88be425f6..000000000
--- a/dom/system/gonk/nsVolume.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_nsvolume_h__
-#define mozilla_system_nsvolume_h__
-
-#include "nsCOMPtr.h"
-#include "nsIVolume.h"
-#include "nsString.h"
-#include "nsTArray.h"
-
-namespace mozilla {
-namespace system {
-
-class Volume;
-
-class nsVolume : public nsIVolume
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIVOLUME
-
- // This constructor is used by the UpdateVolumeRunnable constructor
- nsVolume(const Volume* aVolume);
-
- // This constructor is used by nsVolumeService::SetFakeVolumeState
- nsVolume(const nsVolume* aVolume);
-
- // This constructor is used by ContentChild::RecvFileSystemUpdate which is
- // used to update the volume cache maintained in the child process.
- nsVolume(const nsAString& aName, const nsAString& aMountPoint,
- const int32_t& aState, const int32_t& aMountGeneration,
- const bool& aIsMediaPresent, const bool& aIsSharing,
- const bool& aIsFormatting, const bool& aIsFake,
- const bool& aIsUnmounting, const bool& aIsRemovable,
- const bool& aIsHotSwappable)
- : mName(aName),
- mMountPoint(aMountPoint),
- mState(aState),
- mMountGeneration(aMountGeneration),
- mMountLocked(false),
- mIsFake(aIsFake),
- mIsMediaPresent(aIsMediaPresent),
- mIsSharing(aIsSharing),
- mIsFormatting(aIsFormatting),
- mIsUnmounting(aIsUnmounting),
- mIsRemovable(aIsRemovable),
- mIsHotSwappable(aIsHotSwappable)
- {
- }
-
- bool Equals(nsIVolume* aVolume);
- void UpdateMountLock(nsVolume* aOldVolume);
-
- void LogState() const;
-
- const nsString& Name() const { return mName; }
- nsCString NameStr() const { return NS_LossyConvertUTF16toASCII(mName); }
-
- void Dump(const char* aLabel) const;
-
- int32_t MountGeneration() const { return mMountGeneration; }
- bool IsMountLocked() const { return mMountLocked; }
-
- const nsString& MountPoint() const { return mMountPoint; }
- nsCString MountPointStr() const { return NS_LossyConvertUTF16toASCII(mMountPoint); }
-
- int32_t State() const { return mState; }
- const char* StateStr() const { return NS_VolumeStateStr(mState); }
-
- bool IsFake() const { return mIsFake; }
- bool IsMediaPresent() const { return mIsMediaPresent; }
- bool IsSharing() const { return mIsSharing; }
- bool IsFormatting() const { return mIsFormatting; }
- bool IsUnmounting() const { return mIsUnmounting; }
- bool IsRemovable() const { return mIsRemovable; }
- bool IsHotSwappable() const { return mIsHotSwappable; }
-
- typedef nsTArray<RefPtr<nsVolume> > Array;
-
-private:
- virtual ~nsVolume() {} // MozExternalRefCountType complains if this is non-virtual
-
- friend class nsVolumeService; // Calls the following XxxMountLock functions
- void UpdateMountLock(const nsAString& aMountLockState);
- void UpdateMountLock(bool aMountLocked);
-
- void SetIsFake(bool aIsFake);
- void SetIsRemovable(bool aIsRemovable);
- void SetIsHotSwappable(bool aIsHotSwappble);
- void SetState(int32_t aState);
- static void FormatVolumeIOThread(const nsCString& aVolume);
- static void MountVolumeIOThread(const nsCString& aVolume);
- static void UnmountVolumeIOThread(const nsCString& aVolume);
-
- nsString mName;
- nsString mMountPoint;
- int32_t mState;
- int32_t mMountGeneration;
- bool mMountLocked;
- bool mIsFake;
- bool mIsMediaPresent;
- bool mIsSharing;
- bool mIsFormatting;
- bool mIsUnmounting;
- bool mIsRemovable;
- bool mIsHotSwappable;
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_nsvolume_h__
diff --git a/dom/system/gonk/nsVolumeMountLock.cpp b/dom/system/gonk/nsVolumeMountLock.cpp
deleted file mode 100644
index 288c0f689..000000000
--- a/dom/system/gonk/nsVolumeMountLock.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsVolumeMountLock.h"
-
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/Services.h"
-
-#include "nsIObserverService.h"
-#include "nsIPowerManagerService.h"
-#include "nsIVolume.h"
-#include "nsIVolumeService.h"
-#include "nsString.h"
-#include "nsXULAppAPI.h"
-
-#undef VOLUME_MANAGER_LOG_TAG
-#define VOLUME_MANAGER_LOG_TAG "nsVolumeMountLock"
-#include "VolumeManagerLog.h"
-#include "nsServiceManagerUtils.h"
-#include "mozilla/dom/power/PowerManagerService.h"
-
-using namespace mozilla::dom;
-using namespace mozilla::services;
-
-namespace mozilla {
-namespace system {
-
-NS_IMPL_ISUPPORTS(nsVolumeMountLock, nsIVolumeMountLock,
- nsIObserver, nsISupportsWeakReference)
-
-// static
-already_AddRefed<nsVolumeMountLock>
-nsVolumeMountLock::Create(const nsAString& aVolumeName)
-{
- DBG("nsVolumeMountLock::Create called");
-
- RefPtr<nsVolumeMountLock> mountLock = new nsVolumeMountLock(aVolumeName);
- nsresult rv = mountLock->Init();
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- return mountLock.forget();
-}
-
-nsVolumeMountLock::nsVolumeMountLock(const nsAString& aVolumeName)
- : mVolumeName(aVolumeName),
- mVolumeGeneration(-1),
- mUnlocked(false)
-{
-}
-
-//virtual
-nsVolumeMountLock::~nsVolumeMountLock()
-{
- Unlock();
-}
-
-nsresult nsVolumeMountLock::Init()
-{
- LOG("nsVolumeMountLock created for '%s'",
- NS_LossyConvertUTF16toASCII(mVolumeName).get());
-
- // Add ourselves as an Observer. It's important that we use a weak
- // reference here. If we used a strong reference, then that reference
- // would prevent this object from being destructed.
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, true /*weak*/);
-
- // Get the initial mountGeneration and grab a lock.
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
- NS_ENSURE_TRUE(vs, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIVolume> vol;
- nsresult rv = vs->GetVolumeByName(mVolumeName, getter_AddRefs(vol));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rv = vol->GetMountGeneration(&mVolumeGeneration);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return Lock(vol);
-}
-
-NS_IMETHODIMP nsVolumeMountLock::Unlock()
-{
- LOG("nsVolumeMountLock released for '%s'",
- NS_LossyConvertUTF16toASCII(mVolumeName).get());
-
- mUnlocked = true;
- mWakeLock = nullptr;
-
- // While we don't really need to remove weak observers, we do so anyways
- // since it will reduce the number of times Observe gets called.
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolumeMountLock::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
-{
- if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
- return NS_OK;
- }
- if (mUnlocked) {
- // We're not locked anymore, so we don't need to look at the notifications.
- return NS_OK;
- }
-
- nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
- if (!vol) {
- return NS_OK;
- }
- nsString volName;
- vol->GetName(volName);
- if (!volName.Equals(mVolumeName)) {
- return NS_OK;
- }
- int32_t state;
- nsresult rv = vol->GetState(&state);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (state != nsIVolume::STATE_MOUNTED) {
- mWakeLock = nullptr;
- mVolumeGeneration = -1;
- return NS_OK;
- }
-
- int32_t mountGeneration;
- rv = vol->GetMountGeneration(&mountGeneration);
- NS_ENSURE_SUCCESS(rv, rv);
-
- DBG("nsVolumeMountLock::Observe mountGeneration = %d mVolumeGeneration = %d",
- mountGeneration, mVolumeGeneration);
-
- if (mVolumeGeneration == mountGeneration) {
- return NS_OK;
- }
-
- // The generation changed, which means that any wakelock we may have
- // been holding is now invalid. Grab a new wakelock for the new generation
- // number.
-
- mWakeLock = nullptr;
- mVolumeGeneration = mountGeneration;
-
- return Lock(vol);
-}
-
-nsresult
-nsVolumeMountLock::Lock(nsIVolume* aVolume)
-{
- RefPtr<power::PowerManagerService> pmService =
- power::PowerManagerService::GetInstance();
- NS_ENSURE_TRUE(pmService, NS_ERROR_FAILURE);
-
- nsString mountLockName;
- aVolume->GetMountLockName(mountLockName);
-
- ErrorResult err;
- mWakeLock = pmService->NewWakeLock(mountLockName, nullptr, err);
- if (err.Failed()) {
- return err.StealNSResult();
- }
-
- LOG("nsVolumeMountLock acquired for '%s' gen %d",
- NS_LossyConvertUTF16toASCII(mVolumeName).get(), mVolumeGeneration);
- return NS_OK;
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/nsVolumeMountLock.h b/dom/system/gonk/nsVolumeMountLock.h
deleted file mode 100644
index caf5b2ad5..000000000
--- a/dom/system/gonk/nsVolumeMountLock.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_nsvolumemountlock_h__
-#define mozilla_system_nsvolumemountlock_h__
-
-#include "nsIVolumeMountLock.h"
-
-#include "mozilla/dom/WakeLock.h"
-#include "nsIObserver.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nsWeakReference.h"
-
-class nsIVolume;
-
-namespace mozilla {
-namespace system {
-
-/* The VolumeMountLock is designed so that it can be used in the Child or
- * Parent process. While the VolumeMountLock object exists, then the
- * VolumeManager/AutoMounter will prevent a mounted volume from being
- * shared with the PC.
- */
-
-class nsVolumeMountLock final : public nsIVolumeMountLock,
- public nsIObserver,
- public nsSupportsWeakReference
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- NS_DECL_NSIVOLUMEMOUNTLOCK
-
- static already_AddRefed<nsVolumeMountLock> Create(const nsAString& volumeName);
-
- const nsString& VolumeName() const { return mVolumeName; }
-
-private:
- nsVolumeMountLock(const nsAString& aVolumeName);
- ~nsVolumeMountLock();
-
- nsresult Init();
- nsresult Lock(nsIVolume* aVolume);
-
- RefPtr<dom::WakeLock> mWakeLock;
- nsString mVolumeName;
- int32_t mVolumeGeneration;
- bool mUnlocked;
-};
-
-} // namespace system
-} // namespace mozilla
-
-#endif // mozilla_system_nsvolumemountlock_h__
diff --git a/dom/system/gonk/nsVolumeService.cpp b/dom/system/gonk/nsVolumeService.cpp
deleted file mode 100644
index 48d95c26a..000000000
--- a/dom/system/gonk/nsVolumeService.cpp
+++ /dev/null
@@ -1,553 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsVolumeService.h"
-
-#include "Volume.h"
-#include "VolumeManager.h"
-#include "VolumeServiceIOThread.h"
-
-#include "nsCOMPtr.h"
-#include "nsDependentSubstring.h"
-#include "nsIDOMWakeLockListener.h"
-#include "nsIMutableArray.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsIPowerManagerService.h"
-#include "nsISupportsPrimitives.h"
-#include "nsISupportsUtils.h"
-#include "nsIVolume.h"
-#include "nsIVolumeService.h"
-#include "nsLocalFile.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nsThreadUtils.h"
-#include "nsVolumeMountLock.h"
-#include "nsXULAppAPI.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/Services.h"
-#include "base/task.h"
-
-#undef VOLUME_MANAGER_LOG_TAG
-#define VOLUME_MANAGER_LOG_TAG "nsVolumeService"
-#include "VolumeManagerLog.h"
-
-#include <stdlib.h>
-
-using namespace mozilla::dom;
-using namespace mozilla::services;
-
-namespace mozilla {
-namespace system {
-
-NS_IMPL_ISUPPORTS(nsVolumeService,
- nsIVolumeService,
- nsIDOMMozWakeLockListener)
-
-StaticRefPtr<nsVolumeService> nsVolumeService::sSingleton;
-
-// static
-already_AddRefed<nsVolumeService>
-nsVolumeService::GetSingleton()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!sSingleton) {
- sSingleton = new nsVolumeService();
- }
- RefPtr<nsVolumeService> volumeService = sSingleton.get();
- return volumeService.forget();
-}
-
-// static
-void
-nsVolumeService::Shutdown()
-{
- if (!sSingleton) {
- return;
- }
- if (!XRE_IsParentProcess()) {
- sSingleton = nullptr;
- return;
- }
-
- nsCOMPtr<nsIPowerManagerService> pmService =
- do_GetService(POWERMANAGERSERVICE_CONTRACTID);
- if (pmService) {
- pmService->RemoveWakeLockListener(sSingleton.get());
- }
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(ShutdownVolumeServiceIOThread));
-
- sSingleton = nullptr;
-}
-
-nsVolumeService::nsVolumeService()
- : mArrayMonitor("nsVolumeServiceArray"),
- mGotVolumesFromParent(false)
-{
- sSingleton = this;
-
- if (!XRE_IsParentProcess()) {
- // VolumeServiceIOThread and the WakeLock listener should only run in the
- // parent, so we return early.
- return;
- }
-
- // Startup the IOThread side of things. The actual volume changes
- // are captured by the IOThread and forwarded to main thread.
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(InitVolumeServiceIOThread, this));
-
- nsCOMPtr<nsIPowerManagerService> pmService =
- do_GetService(POWERMANAGERSERVICE_CONTRACTID);
- if (!pmService) {
- return;
- }
- pmService->AddWakeLockListener(this);
-}
-
-nsVolumeService::~nsVolumeService()
-{
-}
-
-// Callback for nsIDOMMozWakeLockListener
-NS_IMETHODIMP
-nsVolumeService::Callback(const nsAString& aTopic, const nsAString& aState)
-{
- CheckMountLock(aTopic, aState);
- return NS_OK;
-}
-
-void nsVolumeService::DumpNoLock(const char* aLabel)
-{
- mArrayMonitor.AssertCurrentThreadOwns();
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
-
- if (numVolumes == 0) {
- LOG("%s: No Volumes!", aLabel);
- return;
- }
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- vol->Dump(aLabel);
- }
-}
-
-NS_IMETHODIMP
-nsVolumeService::Dump(const nsAString& aLabel)
-{
- MonitorAutoLock autoLock(mArrayMonitor);
- DumpNoLock(NS_LossyConvertUTF16toASCII(aLabel).get());
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult)
-{
- MonitorAutoLock autoLock(mArrayMonitor);
-
- RefPtr<nsVolume> vol = FindVolumeByName(aVolName);
- if (!vol) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- vol.forget(aResult);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult)
-{
- NS_ConvertUTF16toUTF8 utf8Path(aPath);
- char realPathBuf[PATH_MAX];
-
- while (realpath(utf8Path.get(), realPathBuf) < 0) {
- if (errno != ENOENT) {
- ERR("GetVolumeByPath: realpath on '%s' failed: %d", utf8Path.get(), errno);
- return NSRESULT_FOR_ERRNO();
- }
- // The pathname we were passed doesn't exist, so we try stripping off trailing
- // components until we get a successful call to realpath, or until we run out
- // of components (if we finally get to /something then we also stop).
- int32_t slashIndex = utf8Path.RFindChar('/');
- if ((slashIndex == kNotFound) || (slashIndex == 0)) {
- errno = ENOENT;
- ERR("GetVolumeByPath: realpath on '%s' failed.", utf8Path.get());
- return NSRESULT_FOR_ERRNO();
- }
- utf8Path.Assign(Substring(utf8Path, 0, slashIndex));
- }
-
- // The volume mount point is always a directory. Something like /mnt/sdcard
- // Once we have a full qualified pathname with symlinks removed (which is
- // what realpath does), we basically check if aPath starts with the mount
- // point, but we don't want to have /mnt/sdcard match /mnt/sdcardfoo but we
- // do want it to match /mnt/sdcard/foo
- // So we add a trailing slash to the mount point and the pathname passed in
- // prior to doing the comparison.
-
- strlcat(realPathBuf, "/", sizeof(realPathBuf));
-
- MonitorAutoLock autoLock(mArrayMonitor);
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- NS_ConvertUTF16toUTF8 volMountPointSlash(vol->MountPoint());
- volMountPointSlash.Append('/');
- nsDependentCSubstring testStr(realPathBuf, volMountPointSlash.Length());
- if (volMountPointSlash.Equals(testStr)) {
- vol.forget(aResult);
- return NS_OK;
- }
- }
- return NS_ERROR_FILE_NOT_FOUND;
-}
-
-NS_IMETHODIMP
-nsVolumeService::CreateOrGetVolumeByPath(const nsAString& aPath, nsIVolume** aResult)
-{
- nsresult rv = GetVolumeByPath(aPath, aResult);
- if (rv == NS_OK) {
- return NS_OK;
- }
-
- // In order to support queries by the updater, we will fabricate a volume
- // from the pathname, so that the caller can determine the volume size.
- nsCOMPtr<nsIVolume> vol = new nsVolume(NS_LITERAL_STRING("fake"),
- aPath, nsIVolume::STATE_MOUNTED,
- -1 /* generation */,
- true /* isMediaPresent*/,
- false /* isSharing */,
- false /* isFormatting */,
- true /* isFake */,
- false /* isUnmounting */,
- false /* isRemovable */,
- false /* isHotSwappable*/);
- vol.forget(aResult);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsVolumeService::GetVolumeNames(nsIArray** aVolNames)
-{
- NS_ENSURE_ARG_POINTER(aVolNames);
- MonitorAutoLock autoLock(mArrayMonitor);
-
- *aVolNames = nullptr;
-
- nsresult rv;
- nsCOMPtr<nsIMutableArray> volNames =
- do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- nsCOMPtr<nsISupportsString> isupportsString =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = isupportsString->SetData(vol->Name());
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = volNames->AppendElement(isupportsString, false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- volNames.forget(aVolNames);
- return NS_OK;
-}
-
-void
-nsVolumeService::GetVolumesForIPC(nsTArray<VolumeInfo>* aResult)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
-
- MonitorAutoLock autoLock(mArrayMonitor);
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- VolumeInfo* volInfo = aResult->AppendElement();
-
- volInfo->name() = vol->mName;
- volInfo->mountPoint() = vol->mMountPoint;
- volInfo->volState() = vol->mState;
- volInfo->mountGeneration() = vol->mMountGeneration;
- volInfo->isMediaPresent() = vol->mIsMediaPresent;
- volInfo->isSharing() = vol->mIsSharing;
- volInfo->isFormatting() = vol->mIsFormatting;
- volInfo->isFake() = vol->mIsFake;
- volInfo->isUnmounting() = vol->mIsUnmounting;
- volInfo->isRemovable() = vol->mIsRemovable;
- volInfo->isHotSwappable() = vol->mIsHotSwappable;
- }
-}
-
-void
-nsVolumeService::RecvVolumesFromParent(const nsTArray<VolumeInfo>& aVolumes)
-{
- if (XRE_IsParentProcess()) {
- // We are the parent. Therefore our volumes are already correct.
- return;
- }
- if (mGotVolumesFromParent) {
- // We've already done this, no need to do it again.
- return;
- }
-
- for (uint32_t i = 0; i < aVolumes.Length(); i++) {
- const VolumeInfo& volInfo(aVolumes[i]);
- RefPtr<nsVolume> vol = new nsVolume(volInfo.name(),
- volInfo.mountPoint(),
- volInfo.volState(),
- volInfo.mountGeneration(),
- volInfo.isMediaPresent(),
- volInfo.isSharing(),
- volInfo.isFormatting(),
- volInfo.isFake(),
- volInfo.isUnmounting(),
- volInfo.isRemovable(),
- volInfo.isHotSwappable());
- UpdateVolume(vol, false);
- }
-}
-
-NS_IMETHODIMP
-nsVolumeService::CreateMountLock(const nsAString& aVolumeName, nsIVolumeMountLock **aResult)
-{
- nsCOMPtr<nsIVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName);
- if (!mountLock) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- mountLock.forget(aResult);
- return NS_OK;
-}
-
-void
-nsVolumeService::CheckMountLock(const nsAString& aMountLockName,
- const nsAString& aMountLockState)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
-
- RefPtr<nsVolume> vol = FindVolumeByMountLockName(aMountLockName);
- if (vol) {
- vol->UpdateMountLock(aMountLockState);
- }
-}
-
-already_AddRefed<nsVolume>
-nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName)
-{
- MonitorAutoLock autoLock(mArrayMonitor);
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- nsString mountLockName;
- vol->GetMountLockName(mountLockName);
- if (mountLockName.Equals(aMountLockName)) {
- return vol.forget();
- }
- }
- return nullptr;
-}
-
-already_AddRefed<nsVolume>
-nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index_type* aIndex)
-{
- mArrayMonitor.AssertCurrentThreadOwns();
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- if (vol->Name().Equals(aName)) {
- if (aIndex) {
- *aIndex = volIndex;
- }
- return vol.forget();
- }
- }
- return nullptr;
-}
-
-void
-nsVolumeService::UpdateVolume(nsVolume* aVolume, bool aNotifyObservers)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- {
- MonitorAutoLock autoLock(mArrayMonitor);
- nsVolume::Array::index_type volIndex;
- RefPtr<nsVolume> vol = FindVolumeByName(aVolume->Name(), &volIndex);
- if (!vol) {
- mVolumeArray.AppendElement(aVolume);
- } else if (vol->Equals(aVolume) || (!vol->IsFake() && aVolume->IsFake())) {
- // Ignore if nothing changed or if a fake tries to override a real volume.
- return;
- } else {
- mVolumeArray.ReplaceElementAt(volIndex, aVolume);
- }
- aVolume->UpdateMountLock(vol);
- }
-
- if (!aNotifyObservers) {
- return;
- }
-
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- if (!obs) {
- return;
- }
- NS_ConvertUTF8toUTF16 stateStr(aVolume->StateStr());
- obs->NotifyObservers(aVolume, NS_VOLUME_STATE_CHANGED, stateStr.get());
-}
-
-NS_IMETHODIMP
-nsVolumeService::CreateFakeVolume(const nsAString& name, const nsAString& path)
-{
- if (XRE_IsParentProcess()) {
- RefPtr<nsVolume> vol = new nsVolume(name, path, nsIVolume::STATE_INIT,
- -1 /* mountGeneration */,
- true /* isMediaPresent */,
- false /* isSharing */,
- false /* isFormatting */,
- true /* isFake */,
- false /* isUnmounting */,
- false /* isRemovable */,
- false /* isHotSwappable */);
- vol->SetState(nsIVolume::STATE_MOUNTED);
- vol->LogState();
- UpdateVolume(vol.get());
- return NS_OK;
- }
-
- ContentChild::GetSingleton()->SendCreateFakeVolume(nsString(name), nsString(path));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
-{
- if (XRE_IsParentProcess()) {
- RefPtr<nsVolume> vol;
- {
- MonitorAutoLock autoLock(mArrayMonitor);
- vol = FindVolumeByName(name);
- }
- if (!vol || !vol->IsFake()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- // Clone the existing volume so we can replace it
- RefPtr<nsVolume> volume = new nsVolume(vol);
- volume->SetState(state);
- volume->LogState();
- UpdateVolume(volume.get());
- return NS_OK;
- }
-
- ContentChild::GetSingleton()->SendSetFakeVolumeState(nsString(name), state);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsVolumeService::RemoveFakeVolume(const nsAString& name)
-{
- if (XRE_IsParentProcess()) {
- SetFakeVolumeState(name, nsIVolume::STATE_NOMEDIA);
- RemoveVolumeByName(name);
- return NS_OK;
- }
-
- ContentChild::GetSingleton()->SendRemoveFakeVolume(nsString(name));
- return NS_OK;
-}
-
-void
-nsVolumeService::RemoveVolumeByName(const nsAString& aName)
-{
- {
- MonitorAutoLock autoLock(mArrayMonitor);
- nsVolume::Array::index_type volIndex;
- RefPtr<nsVolume> vol = FindVolumeByName(aName, &volIndex);
- if (!vol) {
- return;
- }
- mVolumeArray.RemoveElementAt(volIndex);
- }
-
- if (XRE_IsParentProcess()) {
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- if (!obs) {
- return;
- }
- obs->NotifyObservers(nullptr, NS_VOLUME_REMOVED, nsString(aName).get());
- }
-}
-
-/***************************************************************************
-* The UpdateVolumeRunnable creates an nsVolume and updates the main thread
-* data structure while running on the main thread.
-*/
-class UpdateVolumeRunnable : public Runnable
-{
-public:
- UpdateVolumeRunnable(nsVolumeService* aVolumeService, const Volume* aVolume)
- : mVolumeService(aVolumeService),
- mVolume(new nsVolume(aVolume))
- {
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- DBG("UpdateVolumeRunnable::Run '%s' state %s gen %d locked %d "
- "media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
- mVolume->NameStr().get(), mVolume->StateStr(),
- mVolume->MountGeneration(), (int)mVolume->IsMountLocked(),
- (int)mVolume->IsMediaPresent(), mVolume->IsSharing(),
- mVolume->IsFormatting(), mVolume->IsUnmounting(),
- (int)mVolume->IsRemovable(), (int)mVolume->IsHotSwappable());
-
- mVolumeService->UpdateVolume(mVolume);
- mVolumeService = nullptr;
- mVolume = nullptr;
- return NS_OK;
- }
-
-private:
- RefPtr<nsVolumeService> mVolumeService;
- RefPtr<nsVolume> mVolume;
-};
-
-void
-nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
-{
- DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d "
- "media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
- aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
- aVolume->MountGeneration(), (int)aVolume->IsMountLocked(),
- (int)aVolume->MediaPresent(), (int)aVolume->IsSharing(),
- (int)aVolume->IsFormatting(), (int)aVolume->IsUnmounting(),
- (int)aVolume->IsRemovable(), (int)aVolume->IsHotSwappable());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/nsVolumeService.h b/dom/system/gonk/nsVolumeService.h
deleted file mode 100644
index 9bddc0b8f..000000000
--- a/dom/system/gonk/nsVolumeService.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_nsvolumeservice_h__
-#define mozilla_system_nsvolumeservice_h__
-
-#include "mozilla/Monitor.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/StaticPtr.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMWakeLockListener.h"
-#include "nsIVolume.h"
-#include "nsIVolumeService.h"
-#include "nsVolume.h"
-
-namespace mozilla {
-
-namespace dom {
-class VolumeInfo;
-} // dom
-
-namespace system {
-
-class Volume;
-
-/***************************************************************************
-* The nsVolumeData class encapsulates the data that is updated/maintained
-* on the main thread in order to support the nsIVolume and nsIVolumeService
-* classes.
-*/
-
-class nsVolumeService final : public nsIVolumeService,
- public nsIDOMMozWakeLockListener
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIVOLUMESERVICE
- NS_DECL_NSIDOMMOZWAKELOCKLISTENER
-
- nsVolumeService();
-
- static already_AddRefed<nsVolumeService> GetSingleton();
- //static nsVolumeService* GetSingleton();
- static void Shutdown();
-
- void DumpNoLock(const char* aLabel);
-
- // To use this function, you have to create a new volume and pass it in.
- void UpdateVolume(nsVolume* aVolume, bool aNotifyObservers = true);
- void UpdateVolumeIOThread(const Volume* aVolume);
-
- void RecvVolumesFromParent(const nsTArray<dom::VolumeInfo>& aVolumes);
- void GetVolumesForIPC(nsTArray<dom::VolumeInfo>* aResult);
-
- void RemoveVolumeByName(const nsAString& aName);
-
-private:
- ~nsVolumeService();
-
- void CheckMountLock(const nsAString& aMountLockName,
- const nsAString& aMountLockState);
- already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
-
- already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName,
- nsVolume::Array::index_type* aIndex = nullptr);
-
- Monitor mArrayMonitor;
- nsVolume::Array mVolumeArray;
-
- static StaticRefPtr<nsVolumeService> sSingleton;
- bool mGotVolumesFromParent;
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_nsvolumeservice_h__
diff --git a/dom/system/gonk/nsVolumeStat.cpp b/dom/system/gonk/nsVolumeStat.cpp
deleted file mode 100644
index 11976237f..000000000
--- a/dom/system/gonk/nsVolumeStat.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsVolumeStat.h"
-#include "nsString.h"
-
-namespace mozilla {
-namespace system {
-
-NS_IMPL_ISUPPORTS(nsVolumeStat, nsIVolumeStat)
-
-nsVolumeStat::nsVolumeStat(const nsAString& aPath)
-{
- if (statfs(NS_ConvertUTF16toUTF8(aPath).get(), &mStat) != 0) {
- memset(&mStat, 0, sizeof(mStat));
- }
-}
-
-NS_IMETHODIMP nsVolumeStat::GetTotalBytes(int64_t* aTotalBytes)
-{
- *aTotalBytes = mStat.f_blocks * mStat.f_bsize;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolumeStat::GetFreeBytes(int64_t* aFreeBytes)
-{
- *aFreeBytes = mStat.f_bfree * mStat.f_bsize;
- return NS_OK;
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/nsVolumeStat.h b/dom/system/gonk/nsVolumeStat.h
deleted file mode 100644
index 2ca03ed46..000000000
--- a/dom/system/gonk/nsVolumeStat.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_nsvolumestat_h__
-#define mozilla_system_nsvolumestat_h__
-
-#include "nsIVolumeStat.h"
-#include "nsString.h"
-#include <sys/statfs.h>
-
-namespace mozilla {
-namespace system {
-
-class nsVolumeStat final : public nsIVolumeStat
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIVOLUMESTAT
-
- nsVolumeStat(const nsAString& aPath);
-
-protected:
- ~nsVolumeStat() {}
-
-private:
- struct statfs mStat;
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_nsvolumestat_h__
diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js
deleted file mode 100644
index af5b9d8e1..000000000
--- a/dom/system/gonk/ril_consts.js
+++ /dev/null
@@ -1,3338 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// Set to true to debug all RIL layers
-this.DEBUG_ALL = false;
-
-// Set individually to debug specific layers
-this.DEBUG_WORKER = false || DEBUG_ALL;
-this.DEBUG_CONTENT_HELPER = false || DEBUG_ALL;
-this.DEBUG_RIL = false || DEBUG_ALL;
-
-this.REQUEST_GET_SIM_STATUS = 1;
-this.REQUEST_ENTER_SIM_PIN = 2;
-this.REQUEST_ENTER_SIM_PUK = 3;
-this.REQUEST_ENTER_SIM_PIN2 = 4;
-this.REQUEST_ENTER_SIM_PUK2 = 5;
-this.REQUEST_CHANGE_SIM_PIN = 6;
-this.REQUEST_CHANGE_SIM_PIN2 = 7;
-this.REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE = 8;
-this.REQUEST_GET_CURRENT_CALLS = 9;
-this.REQUEST_DIAL = 10;
-this.REQUEST_GET_IMSI = 11;
-this.REQUEST_HANGUP = 12;
-this.REQUEST_HANGUP_WAITING_OR_BACKGROUND = 13;
-this.REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND = 14;
-this.REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE = 15;
-this.REQUEST_CONFERENCE = 16;
-this.REQUEST_UDUB = 17;
-this.REQUEST_LAST_CALL_FAIL_CAUSE = 18;
-this.REQUEST_SIGNAL_STRENGTH = 19;
-this.REQUEST_VOICE_REGISTRATION_STATE = 20;
-this.REQUEST_DATA_REGISTRATION_STATE = 21;
-this.REQUEST_OPERATOR = 22;
-this.REQUEST_RADIO_POWER = 23;
-this.REQUEST_DTMF = 24;
-this.REQUEST_SEND_SMS = 25;
-this.REQUEST_SEND_SMS_EXPECT_MORE = 26;
-this.REQUEST_SETUP_DATA_CALL = 27;
-this.REQUEST_SIM_IO = 28;
-this.REQUEST_SEND_USSD = 29;
-this.REQUEST_CANCEL_USSD = 30;
-this.REQUEST_GET_CLIR = 31;
-this.REQUEST_SET_CLIR = 32;
-this.REQUEST_QUERY_CALL_FORWARD_STATUS = 33;
-this.REQUEST_SET_CALL_FORWARD = 34;
-this.REQUEST_QUERY_CALL_WAITING = 35;
-this.REQUEST_SET_CALL_WAITING = 36;
-this.REQUEST_SMS_ACKNOWLEDGE = 37;
-this.REQUEST_GET_IMEI = 38;
-this.REQUEST_GET_IMEISV = 39;
-this.REQUEST_ANSWER = 40;
-this.REQUEST_DEACTIVATE_DATA_CALL = 41;
-this.REQUEST_QUERY_FACILITY_LOCK = 42;
-this.REQUEST_SET_FACILITY_LOCK = 43;
-this.REQUEST_CHANGE_BARRING_PASSWORD = 44;
-this.REQUEST_QUERY_NETWORK_SELECTION_MODE = 45;
-this.REQUEST_SET_NETWORK_SELECTION_AUTOMATIC = 46;
-this.REQUEST_SET_NETWORK_SELECTION_MANUAL = 47;
-this.REQUEST_QUERY_AVAILABLE_NETWORKS = 48;
-this.REQUEST_DTMF_START = 49;
-this.REQUEST_DTMF_STOP = 50;
-this.REQUEST_BASEBAND_VERSION = 51;
-this.REQUEST_SEPARATE_CONNECTION = 52;
-this.REQUEST_SET_MUTE = 53;
-this.REQUEST_GET_MUTE = 54;
-this.REQUEST_QUERY_CLIP = 55;
-this.REQUEST_LAST_DATA_CALL_FAIL_CAUSE = 56;
-this.REQUEST_DATA_CALL_LIST = 57;
-this.REQUEST_RESET_RADIO = 58;
-this.REQUEST_OEM_HOOK_RAW = 59;
-this.REQUEST_OEM_HOOK_STRINGS = 60;
-this.REQUEST_SCREEN_STATE = 61;
-this.REQUEST_SET_SUPP_SVC_NOTIFICATION = 62;
-this.REQUEST_WRITE_SMS_TO_SIM = 63;
-this.REQUEST_DELETE_SMS_ON_SIM = 64;
-this.REQUEST_SET_BAND_MODE = 65;
-this.REQUEST_QUERY_AVAILABLE_BAND_MODE = 66;
-this.REQUEST_STK_GET_PROFILE = 67;
-this.REQUEST_STK_SET_PROFILE = 68;
-this.REQUEST_STK_SEND_ENVELOPE_COMMAND = 69;
-this.REQUEST_STK_SEND_TERMINAL_RESPONSE = 70;
-this.REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM = 71;
-this.REQUEST_EXPLICIT_CALL_TRANSFER = 72;
-this.REQUEST_SET_PREFERRED_NETWORK_TYPE = 73;
-this.REQUEST_GET_PREFERRED_NETWORK_TYPE = 74;
-this.REQUEST_GET_NEIGHBORING_CELL_IDS = 75;
-this.REQUEST_SET_LOCATION_UPDATES = 76;
-this.REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE = 77;
-this.REQUEST_CDMA_SET_ROAMING_PREFERENCE = 78;
-this.REQUEST_CDMA_QUERY_ROAMING_PREFERENCE = 79;
-this.REQUEST_SET_TTY_MODE = 80;
-this.REQUEST_QUERY_TTY_MODE = 81;
-this.REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE = 82;
-this.REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE = 83;
-this.REQUEST_CDMA_FLASH = 84;
-this.REQUEST_CDMA_BURST_DTMF = 85;
-this.REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY = 86;
-this.REQUEST_CDMA_SEND_SMS = 87;
-this.REQUEST_CDMA_SMS_ACKNOWLEDGE = 88;
-this.REQUEST_GSM_GET_BROADCAST_SMS_CONFIG = 89;
-this.REQUEST_GSM_SET_BROADCAST_SMS_CONFIG = 90;
-this.REQUEST_GSM_SMS_BROADCAST_ACTIVATION = 91;
-this.REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG = 92;
-this.REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG = 93;
-this.REQUEST_CDMA_SMS_BROADCAST_ACTIVATION = 94;
-this.REQUEST_CDMA_SUBSCRIPTION = 95;
-this.REQUEST_CDMA_WRITE_SMS_TO_RUIM = 96;
-this.REQUEST_CDMA_DELETE_SMS_ON_RUIM = 97;
-this.REQUEST_DEVICE_IDENTITY = 98;
-this.REQUEST_EXIT_EMERGENCY_CALLBACK_MODE = 99;
-this.REQUEST_GET_SMSC_ADDRESS = 100;
-this.REQUEST_SET_SMSC_ADDRESS = 101;
-this.REQUEST_REPORT_SMS_MEMORY_STATUS = 102;
-this.REQUEST_REPORT_STK_SERVICE_IS_RUNNING = 103;
-this.REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE = 104;
-this.REQUEST_ISIM_AUTHENTICATION = 105;
-this.REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU = 106;
-this.REQUEST_STK_SEND_ENVELOPE_WITH_STATUS = 107;
-this.REQUEST_VOICE_RADIO_TECH = 108;
-this.REQUEST_GET_CELL_INFO_LIST = 109;
-this.REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE = 110;
-this.REQUEST_SET_INITIAL_ATTACH_APN = 111;
-this.REQUEST_IMS_REGISTRATION_STATE = 112;
-this.REQUEST_IMS_SEND_SMS = 113;
-this.REQUEST_SIM_TRANSMIT_APDU_BASIC = 114;
-this.REQUEST_SIM_OPEN_CHANNEL = 115;
-this.REQUEST_SIM_CLOSE_CHANNEL = 116;
-this.REQUEST_SIM_TRANSMIT_APDU_CHANNEL = 117;
-this.REQUEST_NV_READ_ITEM = 118;
-this.REQUEST_NV_WRITE_ITEM = 119;
-this.REQUEST_NV_WRITE_CDMA_PRL = 120;
-this.REQUEST_NV_RESET_CONFIG = 121;
-this.REQUEST_SET_UICC_SUBSCRIPTION = 122;
-this.REQUEST_ALLOW_DATA = 123;
-this.REQUEST_GET_HARDWARE_CONFIG = 124;
-this.REQUEST_SIM_AUTHENTICATION = 125;
-this.REQUEST_GET_DC_RT_INFO = 126;
-this.REQUEST_SET_DC_RT_INFO_RATE = 127;
-this.REQUEST_SET_DATA_PROFILE = 128;
-this.REQUEST_SHUTDOWN = 129;
-
-// CAF specific parcel type. It should be synced with latest version. But CAF
-// doesn't have l version for b2g yet, so we set REQUEST_SET_DATA_SUBSCRIPTION
-// to a value that won't get conflict with known AOSP parcel.
-this.REQUEST_SET_DATA_SUBSCRIPTION = 130;
-
-// Mozilla specific parcel type.
-this.REQUEST_GET_UNLOCK_RETRY_COUNT = 150;
-
-// Fugu specific parcel types.
-this.RIL_REQUEST_GPRS_ATTACH = 5018;
-this.RIL_REQUEST_GPRS_DETACH = 5019;
-
-// Galaxy S2 specific parcel type.
-this.REQUEST_DIAL_EMERGENCY_CALL = 10016;
-
-this.RESPONSE_TYPE_SOLICITED = 0;
-this.RESPONSE_TYPE_UNSOLICITED = 1;
-
-this.UNSOLICITED_RESPONSE_BASE = 1000;
-this.UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED = 1000;
-this.UNSOLICITED_RESPONSE_CALL_STATE_CHANGED = 1001;
-this.UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED = 1002;
-this.UNSOLICITED_RESPONSE_NEW_SMS = 1003;
-this.UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT = 1004;
-this.UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM = 1005;
-this.UNSOLICITED_ON_USSD = 1006;
-this.UNSOLICITED_ON_USSD_REQUEST = 1007;
-this.UNSOLICITED_NITZ_TIME_RECEIVED = 1008;
-this.UNSOLICITED_SIGNAL_STRENGTH = 1009;
-this.UNSOLICITED_DATA_CALL_LIST_CHANGED = 1010;
-this.UNSOLICITED_SUPP_SVC_NOTIFICATION = 1011;
-this.UNSOLICITED_STK_SESSION_END = 1012;
-this.UNSOLICITED_STK_PROACTIVE_COMMAND = 1013;
-this.UNSOLICITED_STK_EVENT_NOTIFY = 1014;
-this.UNSOLICITED_STK_CALL_SETUP = 1015;
-this.UNSOLICITED_SIM_SMS_STORAGE_FULL = 1016;
-this.UNSOLICITED_SIM_REFRESH = 1017;
-this.UNSOLICITED_CALL_RING = 1018;
-this.UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED = 1019;
-this.UNSOLICITED_RESPONSE_CDMA_NEW_SMS = 1020;
-this.UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS = 1021;
-this.UNSOLICITED_CDMA_RUIM_SMS_STORAGE_FULL = 1022;
-this.UNSOLICITED_RESTRICTED_STATE_CHANGED = 1023;
-this.UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE = 1024;
-this.UNSOLICITED_CDMA_CALL_WAITING = 1025;
-this.UNSOLICITED_CDMA_OTA_PROVISION_STATUS = 1026;
-this.UNSOLICITED_CDMA_INFO_REC = 1027;
-this.UNSOLICITED_OEM_HOOK_RAW = 1028;
-this.UNSOLICITED_RINGBACK_TONE = 1029;
-this.UNSOLICITED_RESEND_INCALL_MUTE = 1030;
-this.UNSOLICITED_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1031;
-this.UNSOLICITED_CDMA_PRL_CHANGED = 1032;
-this.UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE = 1033;
-this.UNSOLICITED_RIL_CONNECTED = 1034;
-this.UNSOLICITED_VOICE_RADIO_TECH_CHANGED = 1035;
-this.UNSOLICITED_CELL_INFO_LIST = 1036;
-this.UNSOLICITED_RESPONSE_IMS_NETWORK_STATE_CHANGED = 1037;
-this.UNSOLICITED_UICC_SUBSCRIPTION_STATUS_CHANGED = 1038;
-this.UNSOLICITED_SRVCC_STATE_NOTIFY = 1039;
-this.UNSOLICITED_HARDWARE_CONFIG_CHANGED = 1040;
-this.UNSOLICITED_DC_RT_INFO_CHANGED = 1041;
-
-this.ERROR_SUCCESS = 0;
-this.ERROR_RADIO_NOT_AVAILABLE = 1;
-this.ERROR_GENERIC_FAILURE = 2;
-this.ERROR_PASSWORD_INCORRECT = 3;
-this.ERROR_SIM_PIN2 = 4;
-this.ERROR_SIM_PUK2 = 5;
-this.ERROR_REQUEST_NOT_SUPPORTED = 6;
-this.ERROR_CANCELLED = 7;
-this.ERROR_OP_NOT_ALLOWED_DURING_VOICE_CALL = 8;
-this.ERROR_OP_NOT_ALLOWED_BEFORE_REG_TO_NW = 9;
-this.ERROR_SMS_SEND_FAIL_RETRY = 10;
-this.ERROR_SIM_ABSENT = 11;
-this.ERROR_SUBSCRIPTION_NOT_AVAILABLE = 12;
-this.ERROR_MODE_NOT_SUPPORTED = 13;
-this.ERROR_FDN_CHECK_FAILURE = 14;
-this.ERROR_ILLEGAL_SIM_OR_ME = 15;
-this.ERROR_MISSING_RESOURCE = 16;
-this.ERROR_NO_SUCH_ELEMENT = 17;
-
-this.GECKO_ERROR_RADIO_NOT_AVAILABLE = "RadioNotAvailable";
-this.GECKO_ERROR_GENERIC_FAILURE = "GenericFailure";
-this.GECKO_ERROR_PASSWORD_INCORRECT = "IncorrectPassword";
-this.GECKO_ERROR_SIM_PIN2 = "SimPin2";
-this.GECKO_ERROR_SIM_PUK2 = "SimPuk2";
-this.GECKO_ERROR_REQUEST_NOT_SUPPORTED = "RequestNotSupported";
-this.GECKO_ERROR_CANCELLED = "Cancelled";
-this.GECKO_ERROR_OP_NOT_ALLOWED_DURING_VOICE_CALL = "OpNotAllowedDuringVoiceCall";
-this.GECKO_ERROR_OP_NOT_ALLOWED_BEFORE_REG_TO_NW = "OpNotAllowedBeforeRegToNw";
-this.GECKO_ERROR_SMS_SEND_FAIL_RETRY = "SmsSendFailRetry";
-this.GECKO_ERROR_SIM_ABSENT = "SimAbsent";
-this.GECKO_ERROR_SUBSCRIPTION_NOT_AVAILABLE = "SubscriptionNotAvailable";
-this.GECKO_ERROR_MODE_NOT_SUPPORTED = "ModeNotSupported";
-this.GECKO_ERROR_FDN_CHECK_FAILURE = "FdnCheckFailure";
-this.GECKO_ERROR_ILLEGAL_SIM_OR_ME = "IllegalSIMorME";
-this.GECKO_ERROR_MISSING_RESOURCE = "MissingResource";
-this.GECKO_ERROR_NO_SUCH_ELEMENT = "NoSuchElement";
-this.GECKO_ERROR_INVALID_PARAMETER = "InvalidParameter";
-this.GECKO_ERROR_UNSPECIFIED_ERROR = "UnspecifiedError";
-
-this.RIL_ERROR_TO_GECKO_ERROR = {};
-RIL_ERROR_TO_GECKO_ERROR[ERROR_RADIO_NOT_AVAILABLE] = GECKO_ERROR_RADIO_NOT_AVAILABLE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_GENERIC_FAILURE] = GECKO_ERROR_GENERIC_FAILURE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_PASSWORD_INCORRECT] = GECKO_ERROR_PASSWORD_INCORRECT;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SIM_PIN2] = GECKO_ERROR_SIM_PIN2;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SIM_PUK2] = GECKO_ERROR_SIM_PUK2;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_REQUEST_NOT_SUPPORTED] = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_CANCELLED] = GECKO_ERROR_CANCELLED;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_OP_NOT_ALLOWED_DURING_VOICE_CALL] = GECKO_ERROR_OP_NOT_ALLOWED_DURING_VOICE_CALL;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_OP_NOT_ALLOWED_BEFORE_REG_TO_NW] = GECKO_ERROR_OP_NOT_ALLOWED_BEFORE_REG_TO_NW;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SMS_SEND_FAIL_RETRY] = GECKO_ERROR_SMS_SEND_FAIL_RETRY;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SIM_ABSENT] = GECKO_ERROR_SIM_ABSENT;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SUBSCRIPTION_NOT_AVAILABLE] = GECKO_ERROR_SUBSCRIPTION_NOT_AVAILABLE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_MODE_NOT_SUPPORTED] = GECKO_ERROR_MODE_NOT_SUPPORTED;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_FDN_CHECK_FAILURE] = GECKO_ERROR_FDN_CHECK_FAILURE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_ILLEGAL_SIM_OR_ME] = GECKO_ERROR_ILLEGAL_SIM_OR_ME;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_MISSING_RESOURCE] = GECKO_ERROR_MISSING_RESOURCE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_NO_SUCH_ELEMENT] = GECKO_ERROR_NO_SUCH_ELEMENT;
-
-// 3GPP 23.040 clause 9.2.3.6 TP-Message-Reference(TP-MR):
-// The number of times the MS automatically repeats the SMS-SUBMIT shall be in
-// the range 1 to 3 but the precise number is an implementation matter.
-this.SMS_RETRY_MAX = 3;
-
-this.RADIO_STATE_OFF = 0;
-this.RADIO_STATE_UNAVAILABLE = 1;
-this.RADIO_STATE_ON = 10; // since RIL v7
-
-this.CARD_STATE_ABSENT = 0;
-this.CARD_STATE_PRESENT = 1;
-this.CARD_STATE_ERROR = 2;
-
-this.CARD_PERSOSUBSTATE_UNKNOWN = 0;
-this.CARD_PERSOSUBSTATE_IN_PROGRESS = 1;
-this.CARD_PERSOSUBSTATE_READY = 2;
-this.CARD_PERSOSUBSTATE_SIM_NETWORK = 3;
-this.CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET = 4;
-this.CARD_PERSOSUBSTATE_SIM_CORPORATE = 5;
-this.CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER = 6;
-this.CARD_PERSOSUBSTATE_SIM_SIM = 7;
-this.CARD_PERSOSUBSTATE_SIM_NETWORK_PUK = 8;
-this.CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK = 9;
-this.CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK = 10;
-this.CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK = 11;
-this.CARD_PERSOSUBSTATE_SIM_SIM_PUK = 12;
-this.CARD_PERSOSUBSTATE_RUIM_NETWORK1 = 13;
-this.CARD_PERSOSUBSTATE_RUIM_NETWORK2 = 14;
-this.CARD_PERSOSUBSTATE_RUIM_HRPD = 15;
-this.CARD_PERSOSUBSTATE_RUIM_CORPORATE = 16;
-this.CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER = 17;
-this.CARD_PERSOSUBSTATE_RUIM_RUIM = 18;
-this.CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK = 19;
-this.CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK = 20;
-this.CARD_PERSOSUBSTATE_RUIM_HRPD_PUK = 21;
-this.CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK = 22;
-this.CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK = 23;
-this.CARD_PERSOSUBSTATE_RUIM_RUIM_PUK = 24;
-
-this.CARD_APPSTATE_ILLEGAL = -1;
-this.CARD_APPSTATE_UNKNOWN = 0;
-this.CARD_APPSTATE_DETECTED = 1;
-this.CARD_APPSTATE_PIN = 2; // If PIN1 or UPin is required.
-this.CARD_APPSTATE_PUK = 3; // If PUK1 or Puk for UPin is required.
-this.CARD_APPSTATE_SUBSCRIPTION_PERSO = 4; // perso_substate should be looked
- // at when app_state is assigned
- // to this value.
-this.CARD_APPSTATE_READY = 5;
-
-this.CARD_PINSTATE_UNKNOWN = 0;
-this.CARD_PINSTATE_ENABLED_NOT_VERIFIED = 1;
-this.CARD_PINSTATE_ENABLED_VERIFIED = 2;
-this.CARD_PINSTATE_DISABLED = 3;
-this.CARD_PINSTATE_ENABLED_BLOCKED = 4;
-this.CARD_PINSTATE_ENABLED_PERM_BLOCKED = 5;
-
-this.CARD_APPTYPE_UNKNOWN = 0;
-this.CARD_APPTYPE_SIM = 1;
-this.CARD_APPTYPE_USIM = 2;
-this.CARD_APPTYPE_RUIM = 3;
-this.CARD_APPTYPE_CSIM = 4;
-this.CARD_APPTYPE_ISIM = 5;
-
-this.CARD_MAX_APPS = 8;
-
-this.GECKO_CARD_TYPE = [
- null,
- "sim",
- "usim",
- "ruim",
- "csim",
- "isim"
-];
-
-
-// Used for QUERY_AVAILABLE_NETWORKS status.
-this.QAN_STATE_UNKNOWN = "unknown";
-this.QAN_STATE_AVAILABLE = "available";
-this.QAN_STATE_CURRENT = "current";
-this.QAN_STATE_FORBIDDEN = "forbidden";
-
-// Must be in sync with MobileNetworkState of MozMobileNetworkInfo.webidl
-this.GECKO_QAN_STATE_UNKNOWN = null;
-this.GECKO_QAN_STATE_AVAILABLE = "available";
-this.GECKO_QAN_STATE_CONNECTED = "connected";
-this.GECKO_QAN_STATE_FORBIDDEN = "forbidden";
-
-this.RIL_QAN_STATE_TO_GECKO_STATE = {};
-this.RIL_QAN_STATE_TO_GECKO_STATE[this.QAN_STATE_UNKNOWN] = this.GECKO_QAN_STATE_UNKNOWN;
-this.RIL_QAN_STATE_TO_GECKO_STATE[this.QAN_STATE_AVAILABLE] = this.GECKO_QAN_STATE_AVAILABLE;
-this.RIL_QAN_STATE_TO_GECKO_STATE[this.QAN_STATE_CURRENT] = this.GECKO_QAN_STATE_CONNECTED;
-this.RIL_QAN_STATE_TO_GECKO_STATE[this.QAN_STATE_FORBIDDEN] = this.GECKO_QAN_STATE_FORBIDDEN;
-
-this.NETWORK_SELECTION_MODE_AUTOMATIC = 0;
-this.NETWORK_SELECTION_MODE_MANUAL = 1;
-
-this.NETWORK_INFO_VOICE_REGISTRATION_STATE = "voiceRegistrationState";
-this.NETWORK_INFO_DATA_REGISTRATION_STATE = "dataRegistrationState";
-this.NETWORK_INFO_OPERATOR = "operator";
-this.NETWORK_INFO_NETWORK_SELECTION_MODE = "networkSelectionMode";
-this.NETWORK_INFO_SIGNAL = "signal";
-this.NETWORK_INFO_MESSAGE_TYPES = [
- NETWORK_INFO_VOICE_REGISTRATION_STATE,
- NETWORK_INFO_DATA_REGISTRATION_STATE,
- NETWORK_INFO_OPERATOR,
- NETWORK_INFO_NETWORK_SELECTION_MODE,
- NETWORK_INFO_SIGNAL
-];
-
-this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM = "wcdma/gsm";
-this.GECKO_PREFERRED_NETWORK_TYPE_GSM_ONLY = "gsm";
-this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_ONLY = "wcdma";
-this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_AUTO = "wcdma/gsm-auto";
-this.GECKO_PREFERRED_NETWORK_TYPE_CDMA_EVDO = "cdma/evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_CDMA_ONLY = "cdma";
-this.GECKO_PREFERRED_NETWORK_TYPE_EVDO_ONLY = "evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO = "wcdma/gsm/cdma/evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_CDMA_EVDO = "lte/cdma/evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM = "lte/wcdma/gsm";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA = "lte/wcdma";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM_CDMA_EVDO = "lte/wcdma/gsm/cdma/evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_ONLY = "lte";
-this.RIL_PREFERRED_NETWORK_TYPE_TO_GECKO = [
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM,
- GECKO_PREFERRED_NETWORK_TYPE_GSM_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_AUTO,
- GECKO_PREFERRED_NETWORK_TYPE_CDMA_EVDO,
- GECKO_PREFERRED_NETWORK_TYPE_CDMA_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_EVDO_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_CDMA_EVDO,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM_CDMA_EVDO,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA
-];
-
-this.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT = "gsm,wcdma";
-// Index-item pair must be in sync with nsIMobileConnection.MOBILE_NETWORK_TYPE_*
-this.GECKO_SUPPORTED_NETWORK_TYPES = [
- "gsm",
- "wcdma",
- "cdma",
- "evdo",
- "lte"
-];
-
-// Network registration states. See TS 27.007 7.2
-this.NETWORK_CREG_STATE_NOT_SEARCHING = 0;
-this.NETWORK_CREG_STATE_REGISTERED_HOME = 1;
-this.NETWORK_CREG_STATE_SEARCHING = 2;
-this.NETWORK_CREG_STATE_DENIED = 3;
-this.NETWORK_CREG_STATE_UNKNOWN = 4;
-this.NETWORK_CREG_STATE_REGISTERED_ROAMING = 5;
-this.NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS = 10;
-this.NETWORK_CREG_STATE_SEARCHING_EMERGENCY_CALLS = 12;
-this.NETWORK_CREG_STATE_DENIED_EMERGENCY_CALLS = 13;
-this.NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS = 14;
-
-this.NETWORK_CREG_TECH_UNKNOWN = 0;
-this.NETWORK_CREG_TECH_GPRS = 1;
-this.NETWORK_CREG_TECH_EDGE = 2;
-this.NETWORK_CREG_TECH_UMTS = 3;
-this.NETWORK_CREG_TECH_IS95A = 4;
-this.NETWORK_CREG_TECH_IS95B = 5;
-this.NETWORK_CREG_TECH_1XRTT = 6;
-this.NETWORK_CREG_TECH_EVDO0 = 7;
-this.NETWORK_CREG_TECH_EVDOA = 8;
-this.NETWORK_CREG_TECH_HSDPA = 9;
-this.NETWORK_CREG_TECH_HSUPA = 10;
-this.NETWORK_CREG_TECH_HSPA = 11;
-this.NETWORK_CREG_TECH_EVDOB = 12;
-this.NETWORK_CREG_TECH_EHRPD = 13;
-this.NETWORK_CREG_TECH_LTE = 14;
-this.NETWORK_CREG_TECH_HSPAP = 15;
-this.NETWORK_CREG_TECH_GSM = 16;
-this.NETWORK_CREG_TECH_DCHSPAP_1 = 18; // Some devices reports as 18
-this.NETWORK_CREG_TECH_DCHSPAP_2 = 19; // Some others report it as 19
-
-this.CELL_INFO_TYPE_GSM = 1;
-this.CELL_INFO_TYPE_CDMA = 2;
-this.CELL_INFO_TYPE_LTE = 3;
-this.CELL_INFO_TYPE_WCDMA = 4;
-
-this.CALL_STATE_UNKNOWN = -1;
-this.CALL_STATE_ACTIVE = 0;
-this.CALL_STATE_HOLDING = 1;
-this.CALL_STATE_DIALING = 2;
-this.CALL_STATE_ALERTING = 3;
-this.CALL_STATE_INCOMING = 4;
-this.CALL_STATE_WAITING = 5;
-
-this.TOA_INTERNATIONAL = 0x91;
-this.TOA_UNKNOWN = 0x81;
-
-this.CALL_PRESENTATION_ALLOWED = 0;
-this.CALL_PRESENTATION_RESTRICTED = 1;
-this.CALL_PRESENTATION_UNKNOWN = 2;
-this.CALL_PRESENTATION_PAYPHONE = 3;
-
-// Call forwarding actions, see TS 27.007 7.11 "mode"
-this.CALL_FORWARD_ACTION_QUERY_STATUS = 2;
-
-// ICC commands, see TS 27.007 +CRSM commands
-this.ICC_COMMAND_SEEK = 0xa2;
-this.ICC_COMMAND_READ_BINARY = 0xb0;
-this.ICC_COMMAND_READ_RECORD = 0xb2;
-this.ICC_COMMAND_GET_RESPONSE = 0xc0;
-this.ICC_COMMAND_UPDATE_BINARY = 0xd6;
-this.ICC_COMMAND_UPDATE_RECORD = 0xdc;
-
-// ICC constants, GSM SIM file ids from TS 51.011
-this.ICC_EF_ICCID = 0x2fe2;
-this.ICC_EF_IMG = 0x4f20;
-this.ICC_EF_PBR = 0x4f30;
-this.ICC_EF_PLMNsel = 0x6f30; // PLMN for SIM
-this.ICC_EF_SST = 0x6f38;
-this.ICC_EF_UST = 0x6f38; // For USIM
-this.ICC_EF_ADN = 0x6f3a;
-this.ICC_EF_FDN = 0x6f3b;
-this.ICC_EF_SMS = 0x6f3c;
-this.ICC_EF_GID1 = 0x6f3e;
-this.ICC_EF_MSISDN = 0x6f40;
-this.ICC_EF_CBMI = 0x6f45;
-this.ICC_EF_SPN = 0x6f46;
-this.ICC_EF_CBMID = 0x6f48;
-this.ICC_EF_SDN = 0x6f49;
-this.ICC_EF_EXT1 = 0x6f4a;
-this.ICC_EF_EXT2 = 0x6f4b;
-this.ICC_EF_EXT3 = 0x6f4c;
-this.ICC_EF_CBMIR = 0x6f50;
-this.ICC_EF_AD = 0x6fad;
-this.ICC_EF_PHASE = 0x6fae;
-this.ICC_EF_PNN = 0x6fc5;
-this.ICC_EF_OPL = 0x6fc6;
-this.ICC_EF_MBDN = 0x6fc7;
-this.ICC_EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN]
-this.ICC_EF_MBI = 0x6fc9;
-this.ICC_EF_MWIS = 0x6fca;
-this.ICC_EF_CFIS = 0x6fcb;
-this.ICC_EF_SPDI = 0x6fcd;
-
-// CPHS files to be supported
-this.ICC_EF_CPHS_INFO = 0x6f16; // CPHS Information
-this.ICC_EF_CPHS_MBN = 0x6f17; // Mailbox Numbers
-
-// CSIM files
-this.ICC_EF_CSIM_IMSI_M = 0x6f22;
-this.ICC_EF_CSIM_CDMAHOME = 0x6f28;
-this.ICC_EF_CSIM_CST = 0x6f32; // CDMA Service table
-this.ICC_EF_CSIM_SPN = 0x6f41;
-
-this.ICC_PHASE_1 = 0x00;
-this.ICC_PHASE_2 = 0x02;
-this.ICC_PHASE_2_PROFILE_DOWNLOAD_REQUIRED = 0x03;
-
-// Types of files TS 11.11 9.3
-this.TYPE_RFU = 0;
-this.TYPE_MF = 1;
-this.TYPE_DF = 2;
-this.TYPE_EF = 4;
-
-this.RESPONSE_DATA_FILE_SIZE = 2;
-this.RESPONSE_DATA_FILE_ID_1 = 4;
-this.RESPONSE_DATA_FILE_ID_2 = 5;
-this.RESPONSE_DATA_FILE_TYPE = 6;
-this.RESPONSE_DATA_RFU_3 = 7;
-this.RESPONSE_DATA_ACCESS_CONDITION_1 = 8;
-this.RESPONSE_DATA_ACCESS_CONDITION_2 = 9;
-this.RESPONSE_DATA_ACCESS_CONDITION_3 = 10;
-this.RESPONSE_DATA_FILE_STATUS = 11;
-this.RESPONSE_DATA_LENGTH = 12;
-this.RESPONSE_DATA_STRUCTURE = 13;
-this.RESPONSE_DATA_RECORD_LENGTH = 14;
-
-// Structure of files TS 11.11 9.3
-this.EF_STRUCTURE_TRANSPARENT = 0;
-this.EF_STRUCTURE_LINEAR_FIXED = 1;
-this.EF_STRUCTURE_CYCLIC = 3;
-
-// TS 102.221 11.1.1.4.3 Table 11.5: File descriptor byte.
-this.UICC_EF_STRUCTURE = {};
-this.UICC_EF_STRUCTURE[this.EF_STRUCTURE_TRANSPARENT]= 1;
-this.UICC_EF_STRUCTURE[this.EF_STRUCTURE_LINEAR_FIXED]= 2;
-this.UICC_EF_STRUCTURE[this.EF_STRUCTURE_CYCLIC]= 6;
-
-// Status code of EFsms
-// see 3GPP TS 51.011 clause 10.5.3
-this.EFSMS_STATUS_FREE = 0x00;
-this.EFSMS_STATUS_READ = 0x01;
-this.EFSMS_STATUS_TO_BE_READ = 0x03;
-this.EFSMS_STATUS_TO_BE_SENT = 0x07;
-
-// Total size of ADN footer(the size of Alpha identifier excluded).
-// See TS 151.011 clause 10.5.1 EF_ADN.
-this.ADN_FOOTER_SIZE_BYTES = 14;
-// Maximum size of BCD numbers in ADN.
-// See TS 151.011 clause 10.5.1 EF_ADN, 'Length of BCD number/SSC contents'.
-this.ADN_MAX_BCD_NUMBER_BYTES = 11;
-// Maximum digits of the Dialling Number in ADN.
-// See TS 151.011 clause 10.5.1 EF_ADN, 'Dialling Number'.
-this.ADN_MAX_NUMBER_DIGITS = 20;
-// Maximum size of BCD numbers in EXT.
-// See TS 151.011 clause 10.5.10 EF_EXT1, 'Extension data'.
-this.EXT_MAX_BCD_NUMBER_BYTES = 10;
-// Maximum digits of the Dialling Number in EXT.
-// See TS 151.011 clause 10.5.10 EF_EXT1, 'Extension data'.
-this.EXT_MAX_NUMBER_DIGITS = 20;
-
-// READ_RECORD mode, TS 102.221
-this.READ_RECORD_ABSOLUTE_MODE = 4;
-
-// TS 102.221 Table 11.2, return FCP template
-this.GET_RESPONSE_FCP_TEMPLATE = 4;
-
-// GET_RESPONSE mandatory response size for EF, see TS 51.011 clause 9,
-// 'Response data in case of an EF.'
-this.GET_RESPONSE_EF_SIZE_BYTES = 15;
-
-// EF path
-this.EF_PATH_MF_SIM = "3f00";
-this.EF_PATH_DF_PHONEBOOK = "5f3a";
-this.EF_PATH_GRAPHICS = "5f50";
-this.EF_PATH_DF_TELECOM = "7f10";
-this.EF_PATH_DF_GSM = "7f20";
-this.EF_PATH_DF_CDMA = "7f25";
-this.EF_PATH_ADF_USIM = "7fff";
-
-// Status code of sw1 for ICC I/O,
-// see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
-this.ICC_STATUS_NORMAL_ENDING = 0x90;
-this.ICC_STATUS_NORMAL_ENDING_WITH_EXTRA = 0x91;
-this.ICC_STATUS_SAT_BUSY = 0x93;
-this.ICC_STATUS_WITH_SIM_DATA = 0x9e;
-this.ICC_STATUS_WITH_RESPONSE_DATA = 0x9f;
-this.ICC_STATUS_ERROR_WRONG_LENGTH = 0x67;
-this.ICC_STATUS_ERROR_COMMAND_NOT_ALLOWED = 0x69;
-this.ICC_STATUS_ERROR_WRONG_PARAMETERS = 0x6a;
-
-// ICC call barring facility.
-// TS 27.007, clause 7.4, +CLCK
-this.ICC_CB_FACILITY_SIM = "SC";
-this.ICC_CB_FACILITY_FDN = "FD";
-this.ICC_CB_FACILITY_BAOC = "AO";
-this.ICC_CB_FACILITY_BAOIC = "OI";
-this.ICC_CB_FACILITY_BAOICxH = "OX";
-this.ICC_CB_FACILITY_BAIC = "AI";
-this.ICC_CB_FACILITY_BAICr = "IR";
-this.ICC_CB_FACILITY_BA_ALL = "AB";
-this.ICC_CB_FACILITY_BA_MO = "AG";
-this.ICC_CB_FACILITY_BA_MT = "AC";
-
-// ICC service class
-// TS 27.007, clause 7.4, +CLCK
-this.ICC_SERVICE_CLASS_NONE = 0; // no user input
-this.ICC_SERVICE_CLASS_VOICE = (1 << 0);
-this.ICC_SERVICE_CLASS_DATA = (1 << 1);
-this.ICC_SERVICE_CLASS_FAX = (1 << 2);
-this.ICC_SERVICE_CLASS_SMS = (1 << 3);
-this.ICC_SERVICE_CLASS_DATA_SYNC = (1 << 4);
-this.ICC_SERVICE_CLASS_DATA_ASYNC = (1 << 5);
-this.ICC_SERVICE_CLASS_PACKET = (1 << 6);
-this.ICC_SERVICE_CLASS_PAD = (1 << 7);
-this.ICC_SERVICE_CLASS_MAX = (1 << 7); // Max ICC_SERVICE_CLASS value
-
-// ICC lock-selection codes
-// TS 27.007, clause 8.65, +CPINR
-this.ICC_SEL_CODE_SIM_PIN = "SIM PIN";
-this.ICC_SEL_CODE_SIM_PUK = "SIM PUK";
-this.ICC_SEL_CODE_PH_SIM_PIN = "PH-SIM PIN";
-this.ICC_SEL_CODE_PH_FSIM_PIN = "PH-FSIM PIN";
-this.ICC_SEL_CODE_PH_FSIM_PUK = "PH-FSIM PUK";
-this.ICC_SEL_CODE_SIM_PIN2 = "SIM PIN2";
-this.ICC_SEL_CODE_SIM_PUK2 = "SIM PUK2";
-this.ICC_SEL_CODE_PH_NET_PIN = "PH-NET PIN";
-this.ICC_SEL_CODE_PH_NET_PUK = "PH-NET PUK";
-this.ICC_SEL_CODE_PH_NETSUB_PIN = "PH-NETSUB PIN";
-this.ICC_SEL_CODE_PH_NETSUB_PUK = "PH-NETSUB PUK";
-this.ICC_SEL_CODE_PH_SP_PIN = "PH-SP PIN";
-this.ICC_SEL_CODE_PH_SP_PUK = "PH-SP PUK";
-this.ICC_SEL_CODE_PH_CORP_PIN = "PH-CORP PIN";
-this.ICC_SEL_CODE_PH_CORP_PUK = "PH-CORP PUK";
-// TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM @
-// ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_PCK.
-
-this.ICC_USIM_TYPE1_TAG = 0xa8;
-this.ICC_USIM_TYPE2_TAG = 0xa9;
-this.ICC_USIM_TYPE3_TAG = 0xaa;
-this.ICC_USIM_EFADN_TAG = 0xc0;
-this.ICC_USIM_EFIAP_TAG = 0xc1;
-this.ICC_USIM_EFEXT1_TAG = 0xc2;
-this.ICC_USIM_EFSNE_TAG = 0xc3;
-this.ICC_USIM_EFANR_TAG = 0xc4;
-this.ICC_USIM_EFPBC_TAG = 0xc5;
-this.ICC_USIM_EFGRP_TAG = 0xc6;
-this.ICC_USIM_EFAAS_TAG = 0xc7;
-this.ICC_USIM_EFGSD_TAG = 0xc8;
-this.ICC_USIM_EFUID_TAG = 0xc9;
-this.ICC_USIM_EFEMAIL_TAG = 0xca;
-this.ICC_USIM_EFCCP1_TAG = 0xcb;
-
-// ICC image coding scheme
-// TS 31.102, sub-clause 4.6.1.1
-this.ICC_IMG_CODING_SCHEME_BASIC = 0x11;
-this.ICC_IMG_CODING_SCHEME_COLOR = 0x21;
-this.ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY = 0x22;
-
-// Must be in sync with enum IccImageCodingScheme in MozStkCommandEvent.webidl.
-this.GECKO_IMG_CODING_SCHEME_BASIC = "basic";
-this.GECKO_IMG_CODING_SCHEME_COLOR = "color";
-this.GECKO_IMG_CODING_SCHEME_COLOR_TRANSPARENCY = "color-transparency";
-
-this.ICC_IMG_CODING_SCHEME_TO_GECKO = {};
-ICC_IMG_CODING_SCHEME_TO_GECKO[ICC_IMG_CODING_SCHEME_BASIC] = GECKO_IMG_CODING_SCHEME_BASIC;
-ICC_IMG_CODING_SCHEME_TO_GECKO[ICC_IMG_CODING_SCHEME_COLOR] = GECKO_IMG_CODING_SCHEME_COLOR;
-ICC_IMG_CODING_SCHEME_TO_GECKO[ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY] = GECKO_IMG_CODING_SCHEME_COLOR_TRANSPARENCY;
-
-// ICC image header size per coding scheme
-// TS 31.102, Annex B
-this.ICC_IMG_HEADER_SIZE_BASIC = 2;
-this.ICC_IMG_HEADER_SIZE_COLOR = 6;
-
-this.ICC_CLUT_ENTRY_SIZE = 3;
-
-this.USIM_PBR_ANR = "anr";
-this.USIM_PBR_ANR0 = "anr0";
-this.USIM_PBR_EMAIL = "email";
-
-// Current supported fields. Adding more fields to read will increasing I/O
-// time dramatically, do check the performance is acceptable when you add
-// more fields.
-this.USIM_PBR_FIELDS = [USIM_PBR_EMAIL, USIM_PBR_ANR0];
-
-this.USIM_TAG_NAME = {};
-this.USIM_TAG_NAME[ICC_USIM_EFADN_TAG] = "adn";
-this.USIM_TAG_NAME[ICC_USIM_EFIAP_TAG] ="iap";
-this.USIM_TAG_NAME[ICC_USIM_EFEXT1_TAG] = "ext1";
-this.USIM_TAG_NAME[ICC_USIM_EFSNE_TAG] = "sne";
-this.USIM_TAG_NAME[ICC_USIM_EFANR_TAG] = "anr";
-this.USIM_TAG_NAME[ICC_USIM_EFPBC_TAG] = "pbc";
-this.USIM_TAG_NAME[ICC_USIM_EFGRP_TAG] = "grp";
-this.USIM_TAG_NAME[ICC_USIM_EFAAS_TAG] = "aas";
-this.USIM_TAG_NAME[ICC_USIM_EFGSD_TAG] = "gsd";
-this.USIM_TAG_NAME[ICC_USIM_EFUID_TAG] = "uid";
-this.USIM_TAG_NAME[ICC_USIM_EFEMAIL_TAG] = "email";
-this.USIM_TAG_NAME[ICC_USIM_EFCCP1_TAG] = "ccp1";
-
-// Error message for ICC contact.
-this.CONTACT_ERR_REQUEST_NOT_SUPPORTED = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
-this.CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED = "ContactTypeNotSupported";
-this.CONTACT_ERR_FIELD_NOT_SUPPORTED = "FieldNotSupported";
-this.CONTACT_ERR_NO_FREE_RECORD_FOUND = "NoFreeRecordFound";
-this.CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK = "CannotAccessPhoneBook";
-
-// CDMA IMSI_M's byte const.
-// 3GPP2 C.S0065 Sec. 5.2.2
-this.CSIM_IMSI_M_MIN2_BYTE = 1;
-this.CSIM_IMSI_M_MIN1_BYTE = 3;
-this.CSIM_IMSI_M_MNC_BYTE = 6;
-this.CSIM_IMSI_M_PROGRAMMED_BYTE = 7;
-this.CSIM_IMSI_M_MCC_BYTE = 8;
-
-/**
- * Tags for Ber Tlv.
- * See 3GPP TS 101 220 clause 7.2 - Assigned TLV tag values.
- */
-this.BER_UNKNOWN_TAG = 0x00;
-this.BER_FCP_TEMPLATE_TAG = 0x62;
-this.BER_FCP_FILE_SIZE_DATA_TAG = 0x80;
-this.BER_FCP_FILE_SIZE_TOTAL_TAG = 0x81;
-this.BER_FCP_FILE_DESCRIPTOR_TAG = 0x82;
-this.BER_FCP_FILE_IDENTIFIER_TAG = 0x83;
-this.BER_FCP_DF_NAME_TAG = 0x84; // AID.
-this.BER_FCP_PROPRIETARY_PRIMITIVE_TAG = 0x85;
-this.BER_FCP_SFI_SUPPORT_TAG = 0x88;
-this.BER_FCP_LIFE_CYCLE_STATUS_TAG = 0x8a;
-this.BER_FCP_SA_REFERENCE_FORMAT_TAG = 0x8b; // Security Attribute - Reference Format.
-this.BER_FCP_SA_COMPACT_FORMAT_TAG = 0x8c; // Security Attribute - Compact Format.
-this.BER_FCP_SAT_EXPANDED_FORMAT_TAG = 0xab; // Security Attribute Template - Expanded Format.
-this.BER_FCP_PROPRIETARY_TEMPLATE_TAG = 0xa5;
-this.BER_FCP_PIN_STATUS_DATA_OBJECTS_TAG = 0xc6;
-this.BER_PROACTIVE_COMMAND_TAG = 0xd0;
-this.BER_SMS_PP_DOWNLOAD_TAG = 0xd1;
-this.BER_MENU_SELECTION_TAG = 0xd3;
-this.BER_EVENT_DOWNLOAD_TAG = 0xd6;
-this.BER_TIMER_EXPIRATION_TAG = 0xd7;
-
-// Flags in Comprehension TLV.
-this.COMPREHENSIONTLV_FLAG_CR = 0x80; // Comprehension required.
-
-// Tags for Comprehension TLV.
-this.COMPREHENSIONTLV_TAG_COMMAND_DETAILS = 0x01;
-this.COMPREHENSIONTLV_TAG_DEVICE_ID = 0x02;
-this.COMPREHENSIONTLV_TAG_RESULT = 0x03;
-this.COMPREHENSIONTLV_TAG_DURATION = 0x04;
-this.COMPREHENSIONTLV_TAG_ALPHA_ID = 0x05;
-this.COMPREHENSIONTLV_TAG_ADDRESS = 0x06;
-this.COMPREHENSIONTLV_TAG_SUBADDRESS = 0x08;
-this.COMPREHENSIONTLV_TAG_SMS_TPDU = 0x0b;
-this.COMPREHENSIONTLV_TAG_TEXT_STRING = 0x0d;
-this.COMPREHENSIONTLV_TAG_TONE = 0x0e;
-this.COMPREHENSIONTLV_TAG_ITEM = 0x0f;
-this.COMPREHENSIONTLV_TAG_ITEM_ID = 0x10;
-this.COMPREHENSIONTLV_TAG_RESPONSE_LENGTH = 0x11;
-this.COMPREHENSIONTLV_TAG_FILE_LIST = 0x12;
-this.COMPREHENSIONTLV_TAG_LOCATION_INFO = 0x13;
-this.COMPREHENSIONTLV_TAG_IMEI = 0x14;
-this.COMPREHENSIONTLV_TAG_HELP_REQUEST = 0x15;
-this.COMPREHENSIONTLV_TAG_NMR = 0x16;
-this.COMPREHENSIONTLV_TAG_DEFAULT_TEXT = 0x17;
-this.COMPREHENSIONTLV_TAG_NEXT_ACTION_IND = 0x18;
-this.COMPREHENSIONTLV_TAG_CAUSE = 0x1a;
-this.COMPREHENSIONTLV_TAG_LOCATION_STATUS = 0x1b;
-this.COMPREHENSIONTLV_TAG_TRANSACTION_ID = 0x1c;
-this.COMPREHENSIONTLV_TAG_EVENT_LIST = 0x19;
-this.COMPREHENSIONTLV_TAG_ICON_ID = 0x1e;
-this.COMPREHENSIONTLV_TAG_ICON_ID_LIST = 0x1f;
-this.COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER = 0x24;
-this.COMPREHENSIONTLV_TAG_TIMER_VALUE = 0x25;
-this.COMPREHENSIONTLV_TAG_DATE_TIME_ZONE = 0x26;
-this.COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE = 0x2b;
-this.COMPREHENSIONTLV_TAG_LANGUAGE = 0x2d;
-this.COMPREHENSIONTLV_TAG_URL = 0x31;
-this.COMPREHENSIONTLV_TAG_BROWSER_TERMINATION_CAUSE = 0x34;
-this.COMPREHENSIONTLV_TAG_ACCESS_TECH = 0x3f;
-this.COMPREHENSIONTLV_TAG_SERVICE_RECORD = 0x41;
-this.COMPREHENSIONTLV_TAG_IMEISV = 0x62;
-this.COMPREHENSIONTLV_TAG_BATTERY_STATE = 0x63;
-this.COMPREHENSIONTLV_TAG_NETWORK_SEARCH_MODE = 0x65;
-this.COMPREHENSIONTLV_TAG_MEID = 0x6d;
-this.COMPREHENSIONTLV_TAG_BROADCAST_NETWORK_INFO = 0x7a;
-
-// Tags for Service Provider Display Information TLV
-this.SPDI_TAG_SPDI = 0xa3;
-this.SPDI_TAG_PLMN_LIST = 0x80;
-
-// MM INFORMATION message content IEIs
-// See 3GPP TS 24.008 table 9.2.18
-this.PNN_IEI_FULL_NETWORK_NAME = 0x43;
-this.PNN_IEI_SHORT_NETWORK_NAME = 0x45;
-
-// Device identifiers, see TS 11.14, clause 12.7
-this.STK_DEVICE_ID_KEYPAD = 0x01;
-this.STK_DEVICE_ID_DISPLAY = 0x02;
-this.STK_DEVICE_ID_EARPIECE = 0x03;
-this.STK_DEVICE_ID_SIM = 0x81;
-this.STK_DEVICE_ID_ME = 0x82;
-this.STK_DEVICE_ID_NETWORK = 0x83;
-
-// STK Proactive commands.
-this.STK_CMD_REFRESH = 0x01;
-this.STK_CMD_MORE_TIME = 0x02;
-this.STK_CMD_POLL_INTERVAL = 0x03;
-this.STK_CMD_POLL_OFF = 0x04;
-this.STK_CMD_SET_UP_EVENT_LIST = 0x05;
-this.STK_CMD_SET_UP_CALL = 0x10;
-this.STK_CMD_SEND_SS = 0x11;
-this.STK_CMD_SEND_USSD = 0x12;
-this.STK_CMD_SEND_SMS = 0x13;
-this.STK_CMD_SEND_DTMF = 0x14;
-this.STK_CMD_LAUNCH_BROWSER = 0x15;
-this.STK_CMD_PLAY_TONE = 0x20;
-this.STK_CMD_DISPLAY_TEXT = 0x21;
-this.STK_CMD_GET_INKEY = 0x22;
-this.STK_CMD_GET_INPUT = 0x23;
-this.STK_CMD_SELECT_ITEM = 0x24;
-this.STK_CMD_SET_UP_MENU = 0x25;
-this.STK_CMD_PROVIDE_LOCAL_INFO = 0x26;
-this.STK_CMD_TIMER_MANAGEMENT = 0x27;
-this.STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
-this.STK_CMD_OPEN_CHANNEL = 0x40;
-this.STK_CMD_CLOSE_CHANNEL = 0x41;
-this.STK_CMD_RECEIVE_DATA = 0x42;
-this.STK_CMD_SEND_DATA = 0x43;
-
-// STK Result code.
-// TS 11.14, clause 12.12
-
-// Results '0X' and '1X' indicate that the command has been performed.
-
-// Command performed successfully.
-this.STK_RESULT_OK = 0x00;
-
-// Command performed with partial comprehension.
-this.STK_RESULT_PRFRMD_WITH_PARTIAL_COMPREHENSION = 0x01;
-
-// Command performed, with missing information.
-this.STK_RESULT_PRFRMD_WITH_MISSING_INFO = 0x02;
-
-// REFRESH performed with additional EFs read.
-this.STK_RESULT_PRFRMD_WITH_ADDITIONAL_EFS_READ = 0x03;
-
-// Command performed successfully, but requested icon could not be
-// displayed.
-this.STK_RESULT_PRFRMD_ICON_NOT_DISPLAYED = 0x04;
-
-// Command performed, but modified by call control by NAA.
-this.STK_RESULT_PRFRMD_MODIFIED_BY_NAA = 0x05;
-
-// Command performed successfully, limited service.
-this.STK_RESULT_PRFRMD_LIMITED_SERVICE = 0x06;
-
-// Command performed with modification.
-this.STK_RESULT_PRFRMD_WITH_MODIFICATION = 0x07;
-
-// REFRESH performed but indicated NAA was not active.
-this.STK_RESULT_PRFRMD_NAA_NOT_ACTIVE = 0x08;
-
-// Command performed successfully; tone not played.
-this.STK_RESULT_PRFRMD_TONE_NOT_PLAYED = 0x09;
-
-// Proactive UICC session terminated by the user.
-this.STK_RESULT_UICC_SESSION_TERM_BY_USER = 0x10;
-
-// Backward move in the proactive UICC session requested by the user.
-this.STK_RESULT_BACKWARD_MOVE_BY_USER = 0x11;
-
-// No response from user.
-this.STK_RESULT_NO_RESPONSE_FROM_USER = 0x12;
-
-// Help information required by the user.
-this.STK_RESULT_HELP_INFO_REQUIRED = 0x13;
-
-// USSD or SS transaction terminated by the user.
-this.STK_RESULT_USSD_SS_SESSION_TERM_BY_USER = 0x14;
-
-// Results '2X' indicate to the UICC that it may be worth re-trying the
-// command at a later opportunity.
-
-// Terminal currently unable to process command.
-this.STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS = 0x20;
-
-// Network currently unable to process command.
-this.STK_RESULT_NETWORK_CRNTLY_UNABLE_TO_PROCESS = 0x21;
-
-// User did not accept the proactive command.
-this.STK_RESULT_USER_NOT_ACCEPT = 0x22;
-
-// User cleared down call before connection or network release.
-this.STK_RESULT_USER_CLEAR_DOWN_CALL = 0x23;
-
-// Action in contradiction with the current timer state.
-this.STK_RESULT_CONTRADICTION_WITH_TIMER = 0x24;
-
-// Interaction with call control by NAA; temporary problem.
-this.STK_RESULT_NAA_CALL_CONTROL_TEMPORARY = 0x25;
-
-// Launch browser generic error code.
-this.STK_RESULT_LAUNCH_BROWSER_ERROR = 0x26;
-
-// MMS temporary problem.
-this.STK_RESULT_MMS_TEMPORARY = 0x27;
-
-// Results '3X' indicate that it is not worth the UICC re-trying with an
-// identical command; as it will only get the same response. However, the
-// decision to retry lies with the application.
-
-// Command beyond terminal's capabilities.
-this.STK_RESULT_BEYOND_TERMINAL_CAPABILITY = 0x30;
-
-// Command type not understood by terminal.
-this.STK_RESULT_CMD_TYPE_NOT_UNDERSTOOD = 0x31;
-
-// Command data not understood by terminal.
-this.STK_RESULT_CMD_DATA_NOT_UNDERSTOOD = 0x32;
-
-// Command number not known by terminal.
-this.STK_RESULT_CMD_NUM_NOT_KNOWN = 0x33;
-
-// SS Return Error.
-this.STK_RESULT_SS_RETURN_ERROR = 0x34;
-
-// SMS RP-ERROR.
-this.STK_RESULT_SMS_RP_ERROR = 0x35;
-
-// Error, required values are missing.
-this.STK_RESULT_REQUIRED_VALUES_MISSING = 0x36;
-
-// USSD Return Error.
-this.STK_RESULT_USSD_RETURN_ERROR = 0x37;
-
-// MultipleCard commands error.
-this.STK_RESULT_MULTI_CARDS_CMD_ERROR = 0x38;
-
-// Interaction with call control by USIM or MO short message control by
-// USIM; permanent problem.
-this.STK_RESULT_USIM_CALL_CONTROL_PERMANENT = 0x39;
-
-// Bearer Independent Protocol error.
-this.STK_RESULT_BIP_ERROR = 0x3a;
-
-// Access Technology unable to process command.
-this.STK_RESULT_ACCESS_TECH_UNABLE_TO_PROCESS = 0x3b;
-
-// Frames error.
-this.STK_RESULT_FRAMES_ERROR = 0x3c;
-
-// MMS Error.
-this.STK_RESULT_MMS_ERROR = 0x3d;
-
-// STK presentation types, TS 11.14, clause 12.6, Command Qualifier: Select Item
-this.STK_PRESENTATION_TYPE_NOT_SPECIFIED = 0x00; // Bit 1 is 0.
-this.STK_PRESENTATION_TYPE_DATA_VALUES = 0x01; // Bit 1 is 1, bit 2 is 0.
-this.STK_PRESENTATION_TYPE_NAVIGATION_OPTIONS = 0x03; // Bit 1 is 1, bit 2 is 1.
-
-// STK Coding Scheme.
-this.STK_TEXT_CODING_GSM_7BIT_PACKED = 0x00;
-this.STK_TEXT_CODING_GSM_8BIT = 0x04;
-this.STK_TEXT_CODING_UCS2 = 0x08;
-
-// STK Event List.
-this.STK_EVENT_TYPE_MT_CALL = 0x00;
-this.STK_EVENT_TYPE_CALL_CONNECTED = 0x01;
-this.STK_EVENT_TYPE_CALL_DISCONNECTED = 0x02;
-this.STK_EVENT_TYPE_LOCATION_STATUS = 0x03;
-this.STK_EVENT_TYPE_USER_ACTIVITY = 0x04;
-this.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE = 0x05;
-this.STK_EVENT_TYPE_CARD_READER_STATUS = 0x06;
-this.STK_EVENT_TYPE_LANGUAGE_SELECTION = 0x07;
-this.STK_EVENT_TYPE_BROWSER_TERMINATION = 0x08;
-this.STK_EVENT_TYPE_DATA_AVAILABLE = 0x09;
-this.STK_EVENT_TYPE_CHANNEL_STATUS = 0x0a;
-this.STK_EVENT_TYPE_SINGLE_ACCESS_TECHNOLOGY_CHANGED = 0x0b;
-this.STK_EVENT_TYPE_DISPLAY_PARAMETER_CHANGED = 0x0c;
-this.STK_EVENT_TYPE_LOCAL_CONNECTION = 0x0d;
-this.STK_EVENT_TYPE_NETWORK_SEARCH_MODE_CHANGED = 0x0e;
-this.STK_EVENT_TYPE_BROWSING_STATUS = 0x0f;
-
-// STK Service state of Location Status.
-this.STK_SERVICE_STATE_NORMAL = 0x00;
-this.STK_SERVICE_STATE_LIMITED = 0x01;
-this.STK_SERVICE_STATE_UNAVAILABLE = 0x02;
-
-// Refresh mode.
-this.STK_REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE = 0x00;
-this.STK_REFRESH_FILE_CHANGE = 0x01;
-this.STK_REFRESH_NAA_INIT_AND_FILE_CHANGE = 0x02;
-this.STK_REFRESH_NAA_INIT = 0x03;
-this.STK_REFRESH_UICC_RESET = 0x04;
-
-// Tone type.
-this.STK_TONE_TYPE_DIAL_TONE = 0x01;
-this.STK_TONE_TYPE_CALLED_SUBSCRIBER_BUSY = 0x02;
-this.STK_TONE_TYPE_CONGESTION = 0x03;
-this.STK_TONE_TYPE_RADIO_PATH_ACK = 0x04;
-this.STK_TONE_TYPE_RADIO_PATH_NOT_AVAILABLE = 0x05;
-this.STK_TONE_TYPE_ERROR = 0x06;
-this.STK_TONE_TYPE_CALL_WAITING_TONE = 0x07;
-this.STK_TONE_TYPE_RINGING_TONE = 0x08;
-this.STK_TONE_TYPE_GENERAL_BEEP = 0x10;
-this.STK_TONE_TYPE_POSITIVE_ACK_TONE = 0x11;
-this.STK_TONE_TYPE_NEGATIVE_ACK_TONE = 0x12;
-
-// Time unit.
-this.STK_TIME_UNIT_MINUTE = 0x00;
-this.STK_TIME_UNIT_SECOND = 0x01;
-this.STK_TIME_UNIT_TENTH_SECOND = 0x02;
-
-// Local Information type.
-this.STK_LOCAL_INFO_NNA = 0x00;
-this.STK_LOCAL_INFO_IMEI = 0x01;
-this.STK_LOCAL_INFO_NMR_FOR_NNA = 0x02;
-this.STK_LOCAL_INFO_DATE_TIME_ZONE = 0x03;
-this.STK_LOCAL_INFO_LANGUAGE = 0x04;
-this.STK_LOCAL_INFO_ACCESS_TECH = 0x06;
-this.STK_LOCAL_INFO_ESN = 0x07;
-this.STK_LOCAL_INFO_IMEISV = 0x08;
-this.STK_LOCAL_INFO_SEARCH_MODE = 0x09;
-this.STK_LOCAL_INFO_CHARGE_STATE = 0x0A;
-this.STK_LOCAL_INFO_MEID = 0x0B;
-this.STK_LOCAL_INFO_BROADCAST_NETWORK_INFO = 0x0D;
-this.STK_LOCAL_INFO_MULTIPLE_ACCESS_TECH = 0x0E;
-this.STK_LOCAL_INFO_INFO_FOR_MULTIPLE_ACCESS_TECH = 0x0F;
-this.STK_LOCAL_INFO_NMR_FOR_MULTIPLE_ACCESS_TECH = 0x10;
-
-// Timer Management.
-this.STK_TIMER_START = 0x00;
-this.STK_TIMER_DEACTIVATE = 0x01;
-this.STK_TMIER_GET_CURRENT_VALUE = 0x02;
-
-// Browser Launch Mode.
-this.STK_BROWSER_MODE_LAUNCH_IF_NOT_ALREADY_LAUNCHED = 0x00;
-this.STK_BROWSER_MODE_USING_EXISTING_BROWSER = 0x02;
-this.STK_BROWSER_MODE_USING_NEW_BROWSER = 0x03;
-
-// Browser Termination Cause.
-this.STK_BROWSER_TERMINATION_CAUSE_USER = 0x00;
-this.STK_BROWSER_TERMINATION_CAUSE_ERROR = 0x01;
-
-// Next Action Indicator.
-this.STK_NEXT_ACTION_NULL = 0x00;
-this.STK_NEXT_ACTION_END_PROACTIVE_SESSION = 0x81;
-
-/**
- * Supported Terminal Facilities.
- *
- * value = 1, supported.
- * 0, not supported.
- */
-this.STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD = 1;
-this.STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD = 1;
-this.STK_TERMINAL_SUPPORT_CELL_BROADCAST_DATA_DOWNLOAD = 0;
-this.STK_TERMINAL_SUPPORT_MENU_SELECTION = 1;
-this.STK_TERMINAL_SUPPORT_SIM_DATA_DOWNLOAD_ERROR = 0;
-this.STK_TERMINAL_SUPPORT_TIMER_EXPIRATION = 1;
-this.STK_TERMINAL_SUPPORT_USSD_IN_CALL_CONTROL = 0;
-this.STK_TERMINAL_SUPPORT_CALL_CONTROL_IN_REDIAL = 0;
-
-this.STK_TERMINAL_SUPPORT_COMMAND_RESULT = 1;
-this.STK_TERMINAL_SUPPORT_CALL_CONTROL = 1;
-this.STK_TERMINAL_SUPPORT_CALL_ID_INCLUDED = 0;
-this.STK_TERMINAL_SUPPORT_MO_SMS_CONTROL = 0;
-this.STK_TERMINAL_SUPPORT_ALPHA_ID_INDICATION = 0;
-this.STK_TERMINAL_SUPPORT_UCS2_ENTRY = 1;
-this.STK_TERMINAL_SUPPORT_UCS2_DISPLAY = 1;
-this.STK_TERMINAL_SUPPORT_EXTENSION_TEXT = 1;
-
-this.STK_TERMINAL_SUPPORT_PROACTIVE_DISPLAY_TEXT = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_GET_INKEY = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_GET_INPUT = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_MORE_TIME = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_PLAY_TONE = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_POLL_INTERVAL = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_POLL_OFF = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_REFRESH = 1;
-
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SELECT_ITEM = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SMS = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SS = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_USSD = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_CALL = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_MENU = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR = 0;
-
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_EVENT_LIST = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_MT_CALL = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_CALL_CONNECTED = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_CALL_DISCONNECTED = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_LOCATION_STATUS = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS = 0;
-
-this.STK_TERMINAL_SUPPORT_EVENT_LANGUAGE_SELECTION = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_BROWSER_TERMINATION = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_DATA_AVAILABLE = 0;
-this.STK_TERMINAL_SUPPORT_EVENT_CHANNEL_STATUS = 0;
-
-this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE = 1;
-this.STK_TERMINAL_SUPPORT_GET_INKEY = 1;
-this.STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT = 1;
-this.STK_TERMINAL_SUPPORT_RUN_AT_COMMAND = 0;
-this.STK_TERMINAL_SUPPORT_SET_UP_CALL = 1;
-this.STK_TERMINAL_SUPPORT_CALL_CONTROL_BY_NNA = 0;
-
-this.STK_TERMINAL_SUPPORT_DISPLAY_TEXT = 1;
-this.STK_TERMINAL_SUPPORT_SEND_DTMF_COMMAND = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR = 0;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_LANGUAGE = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_TIME_ADVANCE = 0;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION = 0;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH = 0;
-
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_OPEN_CHANNEL = 1;
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_CLOSE_CHANNEL = 1;
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_RECEIVE_DATA = 1;
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_SEND_DATA = 1;
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_GET_CHANNEL_STATUS = 0;
-
-/**
- * SAT profile
- *
- * @see ETSI TS 101.267, section 5.2.
- */
-this.STK_TERMINAL_PROFILE_DOWNLOAD =
- (STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD << 0) |
- (STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD << 1) |
- (STK_TERMINAL_SUPPORT_CELL_BROADCAST_DATA_DOWNLOAD << 2) |
- (STK_TERMINAL_SUPPORT_MENU_SELECTION << 3) |
- (STK_TERMINAL_SUPPORT_SIM_DATA_DOWNLOAD_ERROR << 4) |
- (STK_TERMINAL_SUPPORT_TIMER_EXPIRATION << 5) |
- (STK_TERMINAL_SUPPORT_USSD_IN_CALL_CONTROL << 6) |
- (STK_TERMINAL_SUPPORT_CALL_CONTROL_IN_REDIAL << 7);
-
-this.STK_TERMINAL_PROFILE_OTHER =
- (STK_TERMINAL_SUPPORT_COMMAND_RESULT << 0) |
- (STK_TERMINAL_SUPPORT_CALL_CONTROL << 1) |
- (STK_TERMINAL_SUPPORT_CALL_ID_INCLUDED << 2) |
- (STK_TERMINAL_SUPPORT_MO_SMS_CONTROL << 3) |
- (STK_TERMINAL_SUPPORT_ALPHA_ID_INDICATION << 4) |
- (STK_TERMINAL_SUPPORT_UCS2_ENTRY << 5) |
- (STK_TERMINAL_SUPPORT_UCS2_DISPLAY << 6) |
- (STK_TERMINAL_SUPPORT_EXTENSION_TEXT << 7);
-
-this.STK_TERMINAL_PROFILE_PROACTIVE_1 =
- (STK_TERMINAL_SUPPORT_PROACTIVE_DISPLAY_TEXT << 0) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_GET_INKEY << 1) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_GET_INPUT << 2) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_MORE_TIME << 3) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_PLAY_TONE << 4) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_POLL_INTERVAL << 5) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_POLL_OFF << 6) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_REFRESH << 7);
-
-this.STK_TERMINAL_PROFILE_PROACTIVE_2 =
- (STK_TERMINAL_SUPPORT_PROACTIVE_SELECT_ITEM << 0) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SMS << 1) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SS << 2) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SEND_USSD << 3) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_CALL << 4) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_MENU << 5) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO << 6) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR << 7);
-
-this.STK_TERMINAL_PROFILE_EVENT =
- (STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_EVENT_LIST << 0) |
- (STK_TERMINAL_SUPPORT_EVENT_MT_CALL << 1) |
- (STK_TERMINAL_SUPPORT_EVENT_CALL_CONNECTED << 2) |
- (STK_TERMINAL_SUPPORT_EVENT_CALL_DISCONNECTED << 3) |
- (STK_TERMINAL_SUPPORT_EVENT_LOCATION_STATUS << 4) |
- (STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY << 5) |
- (STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE << 6) |
- (STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS << 7);
-
-this.STK_TERMINAL_PROFILE_EVENT_EXT =
- (STK_TERMINAL_SUPPORT_EVENT_LANGUAGE_SELECTION << 0) |
- (STK_TERMINAL_SUPPORT_EVENT_BROWSER_TERMINATION << 1) |
- (STK_TERMINAL_SUPPORT_EVENT_DATA_AVAILABLE << 2) |
- (STK_TERMINAL_SUPPORT_EVENT_CHANNEL_STATUS << 3);
-
-this.STK_TERMINAL_PROFILE_PROACTIVE_3 =
- (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP << 0) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT << 1) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE << 2) |
- (STK_TERMINAL_SUPPORT_GET_INKEY << 3) |
- (STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT << 4) |
- (STK_TERMINAL_SUPPORT_RUN_AT_COMMAND << 5) |
- (STK_TERMINAL_SUPPORT_SET_UP_CALL << 6) |
- (STK_TERMINAL_SUPPORT_CALL_CONTROL_BY_NNA << 7);
-
-this.STK_TERMINAL_PROFILE_PROACTIVE_4 =
- (STK_TERMINAL_SUPPORT_DISPLAY_TEXT << 0) |
- (STK_TERMINAL_SUPPORT_SEND_DTMF_COMMAND << 1) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR << 2) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_LANGUAGE << 3) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_TIME_ADVANCE << 4) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION << 5) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER << 6) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH << 7);
-
-this.STK_TERMINAL_PROFILE_BIP_COMMAND =
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_OPEN_CHANNEL << 0) |
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_CLOSE_CHANNEL << 1) |
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_RECEIVE_DATA << 2) |
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_SEND_DATA << 3) |
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_GET_CHANNEL_STATUS << 4);
-
-this.STK_SUPPORTED_TERMINAL_PROFILE = [
- STK_TERMINAL_PROFILE_DOWNLOAD,
- STK_TERMINAL_PROFILE_OTHER,
- STK_TERMINAL_PROFILE_PROACTIVE_1,
- STK_TERMINAL_PROFILE_PROACTIVE_2,
- STK_TERMINAL_PROFILE_EVENT,
- STK_TERMINAL_PROFILE_EVENT_EXT, // Event extension
- 0x00, // Multiple card proactive commands
- STK_TERMINAL_PROFILE_PROACTIVE_3,
- STK_TERMINAL_PROFILE_PROACTIVE_4,
- 0x00, // Softkey support
- 0x00, // Softkey information
- STK_TERMINAL_PROFILE_BIP_COMMAND,
- 0x00, // BIP supported bearers
- 0x00, // Screen height
- 0x00, // Screen width
- 0x00, // 16, Screen effects
- 0x00, // 17, BIP supported transport interface
- 0x00, // 18, RFU
- 0x00, // 19, RFU
- 0x00, // 20, RFU
-];
-
-/**
- * ICC Services Table.
- *
- * @see 3GPP TS 51.011 10.3.7 (SIM) and 3GPP TS 31.102 4.2.8 (USIM).
- */
-this.GECKO_ICC_SERVICES = {
- // @see 3GPP TS 51.011 10.3.7 (SIM).
- sim: {
- ADN: 2,
- FDN: 3,
- PLMNSEL: 7,
- MSISDN: 9,
- EXT1: 10,
- EXT2: 11,
- CBMI: 14,
- GID1: 15,
- SPN: 17,
- SDN: 18,
- EXT3: 19,
- DATA_DOWNLOAD_SMS_CB: 25,
- DATA_DOWNLOAD_SMS_PP: 26,
- CBMIR: 30,
- BDN: 31,
- IMG: 39,
- PNN: 51,
- OPL: 52,
- MDN: 53,
- MWIS: 54,
- SPDI: 56
- },
- // @see 3GPP TS 31.102 4.2.8 (USIM).
- usim: {
- FDN: 2,
- EXT2: 3,
- SDN: 4,
- EXT3: 5,
- BDN: 6,
- CBMI: 15,
- CBMIR: 16,
- GID1: 17,
- SPN: 19,
- MSISDN: 21,
- IMG: 22,
- DATA_DOWNLOAD_SMS_PP: 28,
- DATA_DOWNLOAD_SMS_CB: 29,
- PNN: 45,
- OPL: 46,
- MDN: 47,
- MWIS: 48,
- SPDI: 51
- },
- // @see 3GPP2 C.S0023-D 3.4.18 (RUIM).
- ruim: {
- FDN: 3,
- ENHANCED_PHONEBOOK: 6,
- EXT1: 10,
- EXT2: 11,
- SPN: 17,
- SDN: 18,
- EXT3: 19,
- },
- // @see B.3.1.1 CPHS Information in CPHS Phase 2:
- // Indicates which of the CPHS 'optional' data-fields are present in the SIM card:
- // EF_CPHS_CSP, EF_CPHS_SST, EF_CPHS_MBN, EF_CPHS_ONSF, EF_CPHS_INFO_NUM
- // Note: Mandatory EFs are: (B.3.1 Enhanced SIM Requirements)
- // EF_CPHS_CFF, EF_CPHS_VMI, EF_CPHS_ONS, EF_CPHS_INFO
- cphs: {
- CSP: 1,
- SST: 2,
- MBN: 3,
- ONSF: 4,
- INFO_NUM: 5
- }
-};
-
-/**
- * Cell Broadcast constants
- */
-
-this.CB_FORMAT_GSM = 0;
-this.CB_FORMAT_ETWS = 1;
-this.CB_FORMAT_CMAS = 2;
-this.CB_FORMAT_UMTS = 3;
-
-// CBS Data Coding Scheme: Language groups
-// see 3GPP TS 23.038 section 5
-this.CB_DCS_LANG_GROUP_1 = [
- "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi",
- "no", "el", "tr", "hu", "pl", null
-];
-this.CB_DCS_LANG_GROUP_2 = [
- "cs", "he", "ar", "ru", "is", null, null, null, null, null,
- null, null, null, null, null, null
-];
-
-// See 3GPP TS 23.041 v11.2.0 section 9.4.1.2.2
-this.CB_NON_MMI_SETTABLE_RANGES = [
- /*0x1000 - 0x107F*/4096, 4224, /*0x1080 - 0x10FF*/4224, 4352,
- /*0x1112 - 0x1112*/4370, 4371, /*0x111F - 0x111F*/4383, 4384,
- /*0xF000 - 0xFFFE*/61440, 65535, /*0xFFFF - 0xFFFF*/65535, 65536
-];
-
-// User Data max length in septets
-this.CB_MAX_CONTENT_7BIT = 93;
-// User Data max length in octets
-this.CB_MAX_CONTENT_8BIT = 82;
-// User Data max length in chars
-this.CB_MAX_CONTENT_UCS2 = 41;
-
-// See 3GPP TS 23.041 v11.6.0 senction 9.3.19
-this.CB_MSG_PAGE_INFO_SIZE = 82;
-
-this.CB_MESSAGE_SIZE_ETWS = 56;
-this.CB_MESSAGE_SIZE_GSM = 88;
-this.CB_MESSAGE_SIZE_UMTS_MIN = 90;
-this.CB_MESSAGE_SIZE_UMTS_MAX = 1252;
-
-
-
-// GSM Cell Broadcast Geographical Scope
-// See 3GPP TS 23.041 clause 9.4.1.2.1
-this.CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0;
-this.CB_GSM_GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1;
-this.CB_GSM_GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE = 2;
-this.CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE = 3;
-
-// GSM Cell Broadcast Geographical Scope
-// See 3GPP TS 23.041 clause 9.4.1.2.1
-this.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES = [
- "cell-immediate",
- "plmn",
- "location-area",
- "cell"
-];
-
-// GSM Cell Broadcast Message Identifiers
-// see 3GPP TS 23.041 clause 9.4.1.2.2
-this.CB_GSM_MESSAGEID_ETWS_BEGIN = 0x1100;
-this.CB_GSM_MESSAGEID_ETWS_END = 0x1107;
-
-// ETWS Warning-Type
-// see 3GPP TS 23.041 clause 9.3.24
-this.CB_ETWS_WARNING_TYPE_NAMES = [
- "earthquake",
- "tsunami",
- "earthquake-tsunami",
- "test",
- "other"
-];
-
-// UMTS Message Type
-// see 3GPP TS 25.324 section 11.1
-this.CB_UMTS_MESSAGE_TYPE_CBS = 1;
-this.CB_UMTS_MESSAGE_TYPE_SCHEDULE = 2;
-this.CB_UMTS_MESSAGE_TYPE_CBS41 = 3;
-
-/**
- * Number plan identification defined in
- * |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
- */
-this.CALLED_PARTY_BCD_NPI_UNKNOWN = 0;
-this.CALLED_PARTY_BCD_NPI_ISDN = 1;
-this.CALLED_PARTY_BCD_NPI_DATA = 3;
-this.CALLED_PARTY_BCD_NPI_TELEX = 4;
-this.CALLED_PARTY_BCD_NPI_NATIONAL = 8;
-this.CALLED_PARTY_BCD_NPI_PRIVATE = 9;
-
-/**
- * Array of number plan identification values which can be used to map an
- * enumeration to the corresponding value. The indices should be consistent
- * with nsISmsService::NUMBER_PLAN_IDENTIFICATION_* constants.
- */
-this.CALLED_PARTY_BCD_NPI = [
- CALLED_PARTY_BCD_NPI_UNKNOWN,
- CALLED_PARTY_BCD_NPI_ISDN,
- CALLED_PARTY_BCD_NPI_DATA,
- CALLED_PARTY_BCD_NPI_TELEX,
- CALLED_PARTY_BCD_NPI_NATIONAL,
- CALLED_PARTY_BCD_NPI_PRIVATE
-];
-
-/**
- * GSM PDU constants
- */
-
-// PDU TYPE-OF-ADDRESS
-this.PDU_TOA_UNKNOWN = 0x80; // Unknown. This is used when the user or
- // network has no a priori information
- // about the numbering plan.
-this.PDU_TOA_ISDN = 0x81; // ISDN/Telephone numbering
-this.PDU_TOA_DATA_NUM = 0x83; // Data numbering plan
-this.PDU_TOA_TELEX_NUM = 0x84; // Telex numbering plan
-this.PDU_TOA_NATIONAL_NUM = 0x88; // National numbering plan
-this.PDU_TOA_PRIVATE_NUM = 0x89; // Private numbering plan
-this.PDU_TOA_ERMES_NUM = 0x8A; // Ermes numbering plan
-this.PDU_TOA_INTERNATIONAL = 0x90; // International number
-this.PDU_TOA_NATIONAL = 0xA0; // National number. Prefix or escape digits
- // shall not be included
-this.PDU_TOA_NETWORK_SPEC = 0xB0; // Network specific number This is used to
- // indicate administration/service number
- // specific to the serving network
-this.PDU_TOA_SUBSCRIBER = 0xC0; // Subscriber number. This is used when a
- // specific short number representation is
- // stored in one or more SCs as part of a
- // higher layer application
-this.PDU_TOA_ALPHANUMERIC = 0xD0; // Alphanumeric, (coded according to GSM TS
- // 03.38 7-bit default alphabet)
-this.PDU_TOA_ABBREVIATED = 0xE0; // Abbreviated number
-
-/**
- * First octet of the SMS-DELIVER PDU
- *
- * RP: 0 Reply Path parameter is not set in this PDU
- * 1 Reply Path parameter is set in this PDU
- *
- * UDHI: 0 The UD field contains only the short message
- * 1 The beginning of the UD field contains a header in addition of
- * the short message
- *
- * SRI: (is only set by the SMSC)
- * 0 A status report will not be returned to the SME
- * 1 A status report will be returned to the SME
- *
- * MMS: (is only set by the SMSC)
- * 0 More messages are waiting for the MS in the SMSC
- * 1 No more messages are waiting for the MS in the SMSC
- *
- * MTI: bit1 bit0 Message type
- * 0 0 SMS-DELIVER (SMSC ==> MS)
- * 0 0 SMS-DELIVER REPORT (MS ==> SMSC, is generated
- * automatically by the M20, after receiving a
- * SMS-DELIVER)
- * 0 1 SMS-SUBMIT (MS ==> SMSC)
- * 0 1 SMS-SUBMIT REPORT (SMSC ==> MS)
- * 1 0 SMS-STATUS REPORT (SMSC ==> MS)
- * 1 0 SMS-COMMAND (MS ==> SMSC)
- * 1 1 Reserved
- */
-this.PDU_RP = 0x80; // Reply path. Parameter indicating that
- // reply path exists.
-this.PDU_UDHI = 0x40; // User data header indicator. This bit is
- // set to 1 if the User Data field starts
- // with a header
-this.PDU_SRI_SRR = 0x20; // Status report indication (SMS-DELIVER)
- // or request (SMS-SUBMIT)
-this.PDU_VPF_ABSOLUTE = 0x18;// Validity period aboslute format
- // (SMS-SUBMIT only)
-this.PDU_VPF_RELATIVE = 0x10;// Validity period relative format
- // (SMS-SUBMIT only)
-this.PDU_VPF_ENHANCED = 0x8; // Validity period enhance format
- // (SMS-SUBMIT only)
-this.PDU_MMS_RD = 0x04;// More messages to send. (SMS-DELIVER only) or
- // Reject duplicates (SMS-SUBMIT only)
-
-// MTI - Message Type Indicator
-this.PDU_MTI_SMS_RESERVED = 0x03;
-this.PDU_MTI_SMS_STATUS_REPORT = 0x02;
-this.PDU_MTI_SMS_COMMAND = 0x02;
-this.PDU_MTI_SMS_SUBMIT = 0x01;
-this.PDU_MTI_SMS_DELIVER = 0x00;
-
-// PI - Parameter Indicator
-this.PDU_PI_EXTENSION = 0x80;
-this.PDU_PI_USER_DATA_LENGTH = 0x04;
-this.PDU_PI_DATA_CODING_SCHEME = 0x02;
-this.PDU_PI_PROTOCOL_IDENTIFIER = 0x01;
-this.PDU_PI_RESERVED = 0x78;
-
-// FCS - Failure Cause
-// 0...127 see 3GPP TS 24.011 clause E.2
-// 128...255 see 3GPP TS 23.040 clause 9.2.3.22
-// others see 3GPP TS 27.005 clause 3.2.5
-this.PDU_FCS_OK = 0x00;
-this.PDU_FCS_PROTOCOL_ERROR = 0x6F;
-this.PDU_FCS_MEMORY_CAPACITY_EXCEEDED = 0XD3;
-this.PDU_FCS_USAT_BUSY = 0XD4;
-this.PDU_FCS_USIM_DATA_DOWNLOAD_ERROR = 0xD5;
-this.PDU_FCS_RESERVED = 0xE0;
-this.PDU_FCS_UNSPECIFIED = 0xFF;
-// Special internal value that means we should not acknowledge an
-// incoming text right away, but need to wait for other components
-// (e.g. storage) to complete. This can be any value, so long it
-// doesn't conflict with the PDU_FCS_* constants above.
-this.MOZ_FCS_WAIT_FOR_EXPLICIT_ACK = 0x0F;
-
-// ST - Status
-// Bit 7..0 = 000xxxxx, short message transaction completed
-this.PDU_ST_0_RECEIVED = 0x00;
-this.PDU_ST_0_FORWARDED_NO_CONFIRM = 0x01;
-this.PDU_ST_0_REPLACED_BY_SC = 0x02;
-this.PDU_ST_0_RESERVED_BEGIN = 0x03;
-this.PDU_ST_0_SC_SPECIFIC_BEGIN = 0x10;
-this.PDU_ST_0_SC_SPECIFIC_END = 0x1F;
-// Bit 7..0 = 001xxxxx, temporary error, SC still trying to transfer SM
-this.PDU_ST_1_CONGESTION = 0x20;
-this.PDU_ST_1_SME_BUSY = 0x21;
-this.PDU_ST_1_SME_NO_RESPONSE = 0x22;
-this.PDU_ST_1_SERVICE_REJECTED = 0x23;
-this.PDU_ST_1_QOS_UNAVAILABLE = 0x24;
-this.PDU_ST_1_SME_ERROR = 0x25;
-this.PDU_ST_1_RESERVED_BEGIN = 0x26;
-this.PDU_ST_1_SC_SPECIFIC_BEGIN = 0x30;
-this.PDU_ST_1_SC_SPECIFIC_END = 0x3F;
-// Bit 7..0 = 010xxxxx, permanent error, SC is not making any more transfer
-// attempts
-this.PDU_ST_2_RPC_ERROR = 0x40;
-this.PDU_ST_2_DEST_INCOMPATIBLE = 0x41;
-this.PDU_ST_2_CONNECTION_REJECTED = 0x42;
-this.PDU_ST_2_NOT_OBTAINABLE = 0x43;
-this.PDU_ST_2_QOS_UNAVAILABLE = 0x44;
-this.PDU_ST_2_INTERWORKING_UNAVALIABLE = 0x45;
-this.PDU_ST_2_VALIDITY_EXPIRED = 0x46;
-this.PDU_ST_2_DELETED_BY_SME = 0x47;
-this.PDU_ST_2_DELETED_BY_SC = 0x48;
-this.PDU_ST_2_SM_MISSING = 0x49;
-this.PDU_ST_2_RESERVED_BEGIN = 0x4A;
-this.PDU_ST_2_SC_SPECIFIC_BEGIN = 0x50;
-this.PDU_ST_2_SC_SPECIFIC_END = 0x5F;
-// Bit 7..0 = 011xxxxx, temporary error, SC is not making any more transfer
-// attempts
-this.PDU_ST_3_CONGESTION = 0x60;
-this.PDU_ST_3_SME_BUSY = 0x61;
-this.PDU_ST_3_SME_NO_RESPONSE = 0x62;
-this.PDU_ST_3_SERVICE_REJECTED = 0x63;
-this.PDU_ST_3_QOS_UNAVAILABLE = 0x64;
-this.PDU_ST_3_SME_ERROR = 0x65;
-this.PDU_ST_3_RESERVED_BEGIN = 0x66;
-this.PDU_ST_3_SC_SPECIFIC_BEGIN = 0x70;
-this.PDU_ST_3_SC_SPECIFIC_END = 0x7F;
-
-this.GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE = "not-applicable";
-this.GECKO_SMS_DELIVERY_STATUS_SUCCESS = "success";
-this.GECKO_SMS_DELIVERY_STATUS_PENDING = "pending";
-this.GECKO_SMS_DELIVERY_STATUS_ERROR = "error";
-
-// User Data max length in septets
-this.PDU_MAX_USER_DATA_7BIT = 160;
-// User Data max length in octets
-this.PDU_MAX_USER_DATA_8BIT = 140;
-// User Data max length in chars
-this.PDU_MAX_USER_DATA_UCS2 = 70;
-
-// PID - Protocol Indicator
-this.PDU_PID_DEFAULT = 0x00;
-this.PDU_PID_TELEMATIC_INTERWORKING = 0x20;
-this.PDU_PID_SHORT_MESSAGE_TYPE_0 = 0x40;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_1 = 0x41;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_2 = 0x42;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_3 = 0x43;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_4 = 0x44;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_5 = 0x45;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_6 = 0x46;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_7 = 0x47;
-this.PDU_PID_ENHANDED_MESSAGE_SERVICE = 0x5E;
-this.PDU_PID_RETURN_CALL_MESSAGE = 0x5F;
-this.PDU_PID_ANSI_136_R_DATA = 0x7C;
-this.PDU_PID_ME_DATA_DOWNLOAD = 0x7D;
-this.PDU_PID_ME_DEPERSONALIZATION = 0x7E;
-this.PDU_PID_USIM_DATA_DOWNLOAD = 0x7F;
-
-// DCS - Data Coding Scheme
-this.PDU_DCS_MSG_CODING_7BITS_ALPHABET = 0x00;
-this.PDU_DCS_MSG_CODING_8BITS_ALPHABET = 0x04;
-this.PDU_DCS_MSG_CODING_16BITS_ALPHABET = 0x08;
-this.PDU_DCS_MSG_CLASS_0 = 0x00;
-this.PDU_DCS_MSG_CLASS_1 = 0x01;
-this.PDU_DCS_MSG_CLASS_2 = 0x02;
-this.PDU_DCS_MSG_CLASS_3 = 0x03;
-this.PDU_DCS_MSG_CLASS_USER_1 = 0x04;
-this.PDU_DCS_MSG_CLASS_USER_2 = 0x05;
-this.PDU_DCS_MSG_CLASS_NORMAL = 0x06;
-this.PDU_DCS_CODING_GROUP_BITS = 0xF0;
-this.PDU_DCS_MSG_CLASS_BITS = 0x03;
-this.PDU_DCS_MWI_ACTIVE_BITS = 0x08;
-this.PDU_DCS_MWI_ACTIVE_VALUE = 0x08;
-this.PDU_DCS_MWI_TYPE_BITS = 0x03;
-this.PDU_DCS_MWI_TYPE_VOICEMAIL = 0x00;
-this.PDU_DCS_MWI_TYPE_FAX = 0x01;
-this.PDU_DCS_MWI_TYPE_EMAIL = 0x02;
-this.PDU_DCS_MWI_TYPE_OTHER = 0x03;
-
-// Set as Array instead of Object for reversed-mapping with Array.indexOf().
-this.GECKO_SMS_MESSAGE_CLASSES = [];
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0] = "class-0";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1] = "class-1";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2] = "class-2";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3] = "class-3";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_1] = "user-1";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_2] = "user-2";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL] = "normal";
-
-// Because service center timestamp omit the century. Yay.
-this.PDU_TIMESTAMP_YEAR_OFFSET = 2000;
-
-// See 9.2.3.24 TP‑User Data (TP‑UD)
-this.PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT = 0x00;
-this.PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION = 0x01;
-this.PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT = 0x04;
-this.PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT = 0x05;
-this.PDU_IEI_SMSC_CONTROL_PARAMS = 0x06;
-this.PDU_IEI_UDH_SOURCE_INDICATOR = 0x07;
-this.PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT = 0x08;
-this.PDU_IEI_WIRELESS_CONTROL_MESSAGE_PROTOCOL = 0x09;
-this.PDU_IEI_TEXT_FORMATING = 0x0A;
-this.PDU_IEI_PREDEFINED_SOUND = 0x0B;
-this.PDU_IEI_USER_DATA_SOUND = 0x0C;
-this.PDU_IEI_PREDEFINED_ANIMATION = 0x0D;
-this.PDU_IEI_LARGE_ANIMATION = 0x0E;
-this.PDU_IEI_SMALL_ANIMATION = 0x0F;
-this.PDU_IEI_LARGE_PICTURE = 0x10;
-this.PDU_IEI_SMALL_PICTURE = 0x11;
-this.PDU_IEI_VARIABLE_PICTURE = 0x12;
-this.PDU_IEI_USER_PROMPT_INDICATOR = 0x13;
-this.PDU_IEI_EXTENDED_OBJECT = 0x14;
-this.PDU_IEI_REUSED_EXTENDED_OBJECT = 0x15;
-this.PDU_IEI_COMPRESS_CONTROL = 0x16;
-this.PDU_IEI_OBJECT_DISTRIBUTION_INDICATOR = 0x17;
-this.PDU_IEI_STANDARD_WVG_OBJECT = 0x18;
-this.PDU_IEI_CHARACTER_SIZE_WVG_OBJECT = 0x19;
-this.PDU_IEI_EXTENDED_OBJECT_DATA_REQUEST_COMMAND = 0x1A;
-this.PDU_IEI_RFC822_EMAIL_HEADER = 0x20;
-this.PDU_IEI_HYPERLINK_FORMAT_ELEMENT = 0x21;
-this.PDU_IEI_REPLY_ADDRESS_ELEMENT = 0x22;
-this.PDU_IEI_ENHANCED_VOICE_MAIL_INFORMATION = 0x23;
-this.PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT = 0x24;
-this.PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT = 0x25;
-
-// Application Port Addressing, see 3GPP TS 23.040 9.2.3.24.3
-this.PDU_APA_RESERVED_8BIT_PORTS = 240;
-this.PDU_APA_VALID_16BIT_PORTS = 49152;
-
-// 7bit alphabet escape character. The encoded value of this code point is left
-// undefined in official spec. Its code value is internally assigned to \uffff,
-// <noncharacter-FFFF> in Unicode basic multilingual plane.
-this.PDU_NL_EXTENDED_ESCAPE = 0x1B;
-
-// <SP>, <LF>, <CR> are only defined in locking shift tables.
-this.PDU_NL_SPACE = 0x20;
-this.PDU_NL_LINE_FEED = 0x0A;
-this.PDU_NL_CARRIAGE_RETURN = 0x0D;
-
-// 7bit alphabet page break character, only defined in single shift tables.
-// The encoded value of this code point is left undefined in official spec, but
-// the code point itself maybe be used for example in compressed CBS messages.
-// Its code value is internally assigned to \u000c, ASCII form feed, or new page.
-this.PDU_NL_PAGE_BREAK = 0x0A;
-// 7bit alphabet reserved control character, only defined in single shift
-// tables. The encoded value of this code point is left undefined in official
-// spec. Its code value is internally assigned to \ufffe, <noncharacter-FFFE>
-// in Unicode basic multilingual plane.
-this.PDU_NL_RESERVED_CONTROL = 0x0D;
-
-this.PDU_NL_IDENTIFIER_DEFAULT = 0;
-this.PDU_NL_IDENTIFIER_TURKISH = 1;
-this.PDU_NL_IDENTIFIER_SPANISH = 2;
-this.PDU_NL_IDENTIFIER_PORTUGUESE = 3;
-this.PDU_NL_IDENTIFIER_BENGALI = 4;
-this.PDU_NL_IDENTIFIER_GUJARATI = 5;
-this.PDU_NL_IDENTIFIER_HINDI = 6;
-this.PDU_NL_IDENTIFIER_KANNADA = 7;
-this.PDU_NL_IDENTIFIER_MALAYALAM = 8;
-this.PDU_NL_IDENTIFIER_ORIYA = 9;
-this.PDU_NL_IDENTIFIER_PUNJABI = 10;
-this.PDU_NL_IDENTIFIER_TAMIL = 11;
-this.PDU_NL_IDENTIFIER_TELUGU = 12;
-this.PDU_NL_IDENTIFIER_URDU = 13;
-
-// The mapping of mcc and their extra GSM national language locking / single
-// shift table tuples to enable. The default GSM alphabet and extension table
-// are always enabled and need not to be list here.
-//
-// The content should be updated when a relevant national regulatory body
-// requests. See 'NOTE 2' of 6.2.1.2.5 in 3GPP TS 23.038:
-// "
-// Encoding of a message using the national locking shift mechanism is not
-// intended to be implemented until a formal request is issued by the
-// relevant national regulatory body. This is because a receiving entity
-// not supporting the relevant locking-shift decoding will present different
-// characters from the ones intended by the sending entity.
-// "
-this.PDU_MCC_NL_TABLE_TUPLES_MAPPING = {
- // Configuration for Turkey.
- //
- // The Turkish single shift table contains 7 extra characters
- // (Ğ, İ, Ş, ç, ğ, ı, ş) than the GSM default alphabet extension table. Since
- // all the 7 characters are also included in Turkish locking shift table, it's
- // not necessary to enable Turkish single shift table. Using GSM default
- // alphabet extension table instead saves 3 octets when these extension table
- // characters present in a message.
- 286: [[PDU_NL_IDENTIFIER_TURKISH, PDU_NL_IDENTIFIER_DEFAULT]]
-};
-
-/*
- * 3GPP TS 23.038 - 6.2.1 GSM 7 bit Default Alphabet
- */
-this.PDU_NL_GSM_DEFAULT_ALPHABET =
- // 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "@\u00a3$\u00a5\u00e8\u00e9\u00f9\u00ec\u00f2\u00c7\n\u00d8\u00f8\r\u00c5\u00e5"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0394_\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398\u039e\uffff\u00c6\u00e6\u00df\u00c9"
- // 012.34.....56789ABCDEF
- + " !\"#\u00a4%&'()*+,-./"
- // 0123456789ABCDEF
- + "0123456789:;<=>?"
- // 0.....123456789ABCDEF
- + "\u00a1ABCDEFGHIJKLMNO"
- // 0123456789AB.....C.....D.....E.....F.....
- + "PQRSTUVWXYZ\u00c4\u00d6\u00d1\u00dc\u00a7"
- // 0.....123456789ABCDEF
- + "\u00bfabcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u00e4\u00f6\u00f1\u00fc\u00e0";
-
-// National Language Locking Shift Tables, see 3GPP TS 23.038
-this.PDU_NL_LOCKING_SHIFT_TABLES = [
- /**
- * National Language Identifier: 0x00
- * 6.2.1 GSM 7 bit Default Alphabet
- */
- PDU_NL_GSM_DEFAULT_ALPHABET,
-
- /**
- * National Language Identifier: 0x01
- * A.3.1 Turkish National Language Locking Shift Table
- */
- // 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "@\u00a3$\u00a5\u20ac\u00e9\u00f9\u0131\u00f2\u00c7\n\u011e\u011f\r\u00c5\u00e5"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0394_\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398\u039e\uffff\u015e\u015f\u00df\u00c9"
- // 012.34.....56789ABCDEF
- + " !\"#\u00a4%&'()*+,-./"
- // 0123456789ABCDEF
- + "0123456789:;<=>?"
- // 0.....123456789ABCDEF
- + "\u0130ABCDEFGHIJKLMNO"
- // 0123456789AB.....C.....D.....E.....F.....
- + "PQRSTUVWXYZ\u00c4\u00d6\u00d1\u00dc\u00a7"
- // 0.....123456789ABCDEF
- + "\u00e7abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u00e4\u00f6\u00f1\u00fc\u00e0",
-
- /**
- * National Language Identifier: 0x02
- * A.3.2 Void
- * Fallback to GSM Default Alphabet
- */
- PDU_NL_GSM_DEFAULT_ALPHABET,
-
- /**
- * National Language Identifier: 0x03
- * A.3.3 Portuguese National Language Locking Shift Table
- */
- // 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "@\u00a3$\u00a5\u00ea\u00e9\u00fa\u00ed\u00f3\u00e7\n\u00d4\u00f4\r\u00c1\u00e1"
- // 0.....12.....3.....4.....5.....67.8.....9.....AB.....C.....D.....E.....F.....
- + "\u0394_\u00aa\u00c7\u00c0\u221e^\\\u20ac\u00d3|\uffff\u00c2\u00e2\u00ca\u00c9"
- // 012.34.....56789ABCDEF
- + " !\"#\u00ba%&'()*+,-./"
- // 0123456789ABCDEF
- + "0123456789:;<=>?"
- // 0.....123456789ABCDEF
- + "\u00cdABCDEFGHIJKLMNO"
- // 0123456789AB.....C.....D.....E.....F.....
- + "PQRSTUVWXYZ\u00c3\u00d5\u00da\u00dc\u00a7"
- // 0123456789ABCDEF
- + "~abcdefghijklmno"
- // 0123456789AB.....C.....DE.....F.....
- + "pqrstuvwxyz\u00e3\u00f5`\u00fc\u00e0",
-
- /**
- * National Language Identifier: 0x04
- * A.3.4 Bengali National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.EF.....
- "\u0981\u0982\u0983\u0985\u0986\u0987\u0988\u0989\u098a\u098b\n\u098c \r \u098f"
- // 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0990 \u0993\u0994\u0995\u0996\u0997\u0998\u0999\u099a\uffff\u099b\u099c\u099d\u099e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u099f\u09a0\u09a1\u09a2\u09a3\u09a4)(\u09a5\u09a6,\u09a7.\u09a8"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u09aa\u09ab?"
- // 0.....1.....2.....3.....4.....56.....789A.....B.....C.....D.....E.....F.....
- + "\u09ac\u09ad\u09ae\u09af\u09b0 \u09b2 \u09b6\u09b7\u09b8\u09b9\u09bc\u09bd"
- // 0.....1.....2.....3.....4.....5.....6.....789.....A.....BCD.....E.....F.....
- + "\u09be\u09bf\u09c0\u09c1\u09c2\u09c3\u09c4 \u09c7\u09c8 \u09cb\u09cc\u09cd"
- // 0.....123456789ABCDEF
- + "\u09ceabcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u09d7\u09dc\u09dd\u09f0\u09f1",
-
- /**
- * National Language Identifier: 0x05
- * A.3.5 Gujarati National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.EF.....
- "\u0a81\u0a82\u0a83\u0a85\u0a86\u0a87\u0a88\u0a89\u0a8a\u0a8b\n\u0a8c\u0a8d\r \u0a8f"
- // 0.....1.....23.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0a90\u0a91 \u0a93\u0a94\u0a95\u0a96\u0a97\u0a98\u0a99\u0a9a\uffff\u0a9b\u0a9c\u0a9d\u0a9e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0a9f\u0aa0\u0aa1\u0aa2\u0aa3\u0aa4)(\u0aa5\u0aa6,\u0aa7.\u0aa8"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0aaa\u0aab?"
- // 0.....1.....2.....3.....4.....56.....7.....89.....A.....B.....C.....D.....E.....F.....
- + "\u0aac\u0aad\u0aae\u0aaf\u0ab0 \u0ab2\u0ab3 \u0ab5\u0ab6\u0ab7\u0ab8\u0ab9\u0abc\u0abd"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....CD.....E.....F.....
- + "\u0abe\u0abf\u0ac0\u0ac1\u0ac2\u0ac3\u0ac4\u0ac5 \u0ac7\u0ac8\u0ac9 \u0acb\u0acc\u0acd"
- // 0.....123456789ABCDEF
- + "\u0ad0abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0ae0\u0ae1\u0ae2\u0ae3\u0af1",
-
- /**
- * National Language Identifier: 0x06
- * A.3.6 Hindi National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "\u0901\u0902\u0903\u0905\u0906\u0907\u0908\u0909\u090a\u090b\n\u090c\u090d\r\u090e\u090f"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0910\u0911\u0912\u0913\u0914\u0915\u0916\u0917\u0918\u0919\u091a\uffff\u091b\u091c\u091d\u091e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u091f\u0920\u0921\u0922\u0923\u0924)(\u0925\u0926,\u0927.\u0928"
- // 0123456789ABC.....D.....E.....F
- + "0123456789:;\u0929\u092a\u092b?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u092c\u092d\u092e\u092f\u0930\u0931\u0932\u0933\u0934\u0935\u0936\u0937\u0938\u0939\u093c\u093d"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u093e\u093f\u0940\u0941\u0942\u0943\u0944\u0945\u0946\u0947\u0948\u0949\u094a\u094b\u094c\u094d"
- // 0.....123456789ABCDEF
- + "\u0950abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0972\u097b\u097c\u097e\u097f",
-
- /**
- * National Language Identifier: 0x07
- * A.3.7 Kannada National Language Locking Shift Table
- */
- // 01.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
- " \u0c82\u0c83\u0c85\u0c86\u0c87\u0c88\u0c89\u0c8a\u0c8b\n\u0c8c \r\u0c8e\u0c8f"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0c90 \u0c92\u0c93\u0c94\u0c95\u0c96\u0c97\u0c98\u0c99\u0c9a\uffff\u0c9b\u0c9c\u0c9d\u0c9e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0c9f\u0ca0\u0ca1\u0ca2\u0ca3\u0ca4)(\u0ca5\u0ca6,\u0ca7.\u0ca8"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0caa\u0cab?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....C.....D.....E.....F.....
- + "\u0cac\u0cad\u0cae\u0caf\u0cb0\u0cb1\u0cb2\u0cb3 \u0cb5\u0cb6\u0cb7\u0cb8\u0cb9\u0cbc\u0cbd"
- // 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
- + "\u0cbe\u0cbf\u0cc0\u0cc1\u0cc2\u0cc3\u0cc4 \u0cc6\u0cc7\u0cc8 \u0cca\u0ccb\u0ccc\u0ccd"
- // 0.....123456789ABCDEF
- + "\u0cd5abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0cd6\u0ce0\u0ce1\u0ce2\u0ce3",
-
- /**
- * National Language Identifier: 0x08
- * A.3.8 Malayalam National Language Locking Shift Table
- */
- // 01.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
- " \u0d02\u0d03\u0d05\u0d06\u0d07\u0d08\u0d09\u0d0a\u0d0b\n\u0d0c \r\u0d0e\u0d0f"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0d10 \u0d12\u0d13\u0d14\u0d15\u0d16\u0d17\u0d18\u0d19\u0d1a\uffff\u0d1b\u0d1c\u0d1d\u0d1e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0d1f\u0d20\u0d21\u0d22\u0d23\u0d24)(\u0d25\u0d26,\u0d27.\u0d28"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0d2a\u0d2b?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....EF.....
- + "\u0d2c\u0d2d\u0d2e\u0d2f\u0d30\u0d31\u0d32\u0d33\u0d34\u0d35\u0d36\u0d37\u0d38\u0d39 \u0d3d"
- // 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
- + "\u0d3e\u0d3f\u0d40\u0d41\u0d42\u0d43\u0d44 \u0d46\u0d47\u0d48 \u0d4a\u0d4b\u0d4c\u0d4d"
- // 0.....123456789ABCDEF
- + "\u0d57abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0d60\u0d61\u0d62\u0d63\u0d79",
-
- /**
- * National Language Identifier: 0x09
- * A.3.9 Oriya National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.EF.....
- "\u0b01\u0b02\u0b03\u0b05\u0b06\u0b07\u0b08\u0b09\u0b0a\u0b0b\n\u0b0c \r \u0b0f"
- // 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0b10 \u0b13\u0b14\u0b15\u0b16\u0b17\u0b18\u0b19\u0b1a\uffff\u0b1b\u0b1c\u0b1d\u0b1e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0b1f\u0b20\u0b21\u0b22\u0b23\u0b24)(\u0b25\u0b26,\u0b27.\u0b28"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0b2a\u0b2b?"
- // 0.....1.....2.....3.....4.....56.....7.....89.....A.....B.....C.....D.....E.....F.....
- + "\u0b2c\u0b2d\u0b2e\u0b2f\u0b30 \u0b32\u0b33 \u0b35\u0b36\u0b37\u0b38\u0b39\u0b3c\u0b3d"
- // 0.....1.....2.....3.....4.....5.....6.....789.....A.....BCD.....E.....F.....
- + "\u0b3e\u0b3f\u0b40\u0b41\u0b42\u0b43\u0b44 \u0b47\u0b48 \u0b4b\u0b4c\u0b4d"
- // 0.....123456789ABCDEF
- + "\u0b56abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0b57\u0b60\u0b61\u0b62\u0b63",
-
- /**
- * National Language Identifier: 0x0A
- * A.3.10 Punjabi National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9A.BCD.EF.....
- "\u0a01\u0a02\u0a03\u0a05\u0a06\u0a07\u0a08\u0a09\u0a0a \n \r \u0a0f"
- // 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0a10 \u0a13\u0a14\u0a15\u0a16\u0a17\u0a18\u0a19\u0a1a\uffff\u0a1b\u0a1c\u0a1d\u0a1e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0a1f\u0a20\u0a21\u0a22\u0a23\u0a24)(\u0a25\u0a26,\u0a27.\u0a28"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0a2a\u0a2b?"
- // 0.....1.....2.....3.....4.....56.....7.....89.....A.....BC.....D.....E.....F
- + "\u0a2c\u0a2d\u0a2e\u0a2f\u0a30 \u0a32\u0a33 \u0a35\u0a36 \u0a38\u0a39\u0a3c "
- // 0.....1.....2.....3.....4.....56789.....A.....BCD.....E.....F.....
- + "\u0a3e\u0a3f\u0a40\u0a41\u0a42 \u0a47\u0a48 \u0a4b\u0a4c\u0a4d"
- // 0.....123456789ABCDEF
- + "\u0a51abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0a70\u0a71\u0a72\u0a73\u0a74",
-
- /**
- * National Language Identifier: 0x0B
- * A.3.11 Tamil National Language Locking Shift Table
- */
- // 01.....2.....3.....4.....5.....6.....7.....8.....9A.BCD.E.....F.....
- " \u0b82\u0b83\u0b85\u0b86\u0b87\u0b88\u0b89\u0b8a \n \r\u0b8e\u0b8f"
- // 0.....12.....3.....4.....5.....6789.....A.....B.....CD.....EF.....
- + "\u0b90 \u0b92\u0b93\u0b94\u0b95 \u0b99\u0b9a\uffff \u0b9c \u0b9e"
- // 012.....3456.....7.....89ABCDEF.....
- + " !\u0b9f \u0ba3\u0ba4)( , .\u0ba8"
- // 0123456789ABC.....D.....EF
- + "0123456789:;\u0ba9\u0baa ?"
- // 012.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....EF
- + " \u0bae\u0baf\u0bb0\u0bb1\u0bb2\u0bb3\u0bb4\u0bb5\u0bb6\u0bb7\u0bb8\u0bb9 "
- // 0.....1.....2.....3.....4.....5678.....9.....A.....BC.....D.....E.....F.....
- + "\u0bbe\u0bbf\u0bc0\u0bc1\u0bc2 \u0bc6\u0bc7\u0bc8 \u0bca\u0bcb\u0bcc\u0bcd"
- // 0.....123456789ABCDEF
- + "\u0bd0abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0bd7\u0bf0\u0bf1\u0bf2\u0bf9",
-
- /**
- * National Language Identifier: 0x0C
- * A.3.12 Telugu National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
- "\u0c01\u0c02\u0c03\u0c05\u0c06\u0c07\u0c08\u0c09\u0c0a\u0c0b\n\u0c0c \r\u0c0e\u0c0f"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0c10 \u0c12\u0c13\u0c14\u0c15\u0c16\u0c17\u0c18\u0c19\u0c1a\uffff\u0c1b\u0c1c\u0c1d\u0c1e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0c1f\u0c20\u0c21\u0c22\u0c23\u0c24)(\u0c25\u0c26,\u0c27.\u0c28"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0c2a\u0c2b?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....C.....D.....EF.....
- + "\u0c2c\u0c2d\u0c2e\u0c2f\u0c30\u0c31\u0c32\u0c33 \u0c35\u0c36\u0c37\u0c38\u0c39 \u0c3d"
- // 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
- + "\u0c3e\u0c3f\u0c40\u0c41\u0c42\u0c43\u0c44 \u0c46\u0c47\u0c48 \u0c4a\u0c4b\u0c4c\u0c4d"
- // 0.....123456789ABCDEF
- + "\u0c55abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0c56\u0c60\u0c61\u0c62\u0c63",
-
- /**
- * National Language Identifier: 0x0D
- * A.3.13 Urdu National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "\u0627\u0622\u0628\u067b\u0680\u067e\u06a6\u062a\u06c2\u067f\n\u0679\u067d\r\u067a\u067c"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u062b\u062c\u0681\u0684\u0683\u0685\u0686\u0687\u062d\u062e\u062f\uffff\u068c\u0688\u0689\u068a"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u068f\u068d\u0630\u0631\u0691\u0693)(\u0699\u0632,\u0696.\u0698"
- // 0123456789ABC.....D.....E.....F
- + "0123456789:;\u069a\u0633\u0634?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0635\u0636\u0637\u0638\u0639\u0641\u0642\u06a9\u06aa\u06ab\u06af\u06b3\u06b1\u0644\u0645\u0646"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u06ba\u06bb\u06bc\u0648\u06c4\u06d5\u06c1\u06be\u0621\u06cc\u06d0\u06d2\u064d\u0650\u064f\u0657"
- // 0.....123456789ABCDEF
- + "\u0654abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0655\u0651\u0653\u0656\u0670"
-];
-
-// National Language Single Shift Tables, see 3GPP TS 23.038
-this.PDU_NL_SINGLE_SHIFT_TABLES = [
- /**
- * National Language Identifier: 0x00
- * 6.2.1.1 GSM 7 bit default alphabet extension table
- */
- // 0123456789A.....BCD.....EF
- " \u000c \ufffe "
- // 0123456789AB.....CDEF
- + " ^ \uffff "
- // 0123456789ABCDEF.
- + " {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "| "
- // 0123456789ABCDEF
- + " "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x01
- * A.2.1 Turkish National Language Single Shift Table
- */
- // 0123456789A.....BCD.....EF
- " \u000c \ufffe "
- // 0123456789AB.....CDEF
- + " ^ \uffff "
- // 0123456789ABCDEF.
- + " {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 01234567.....89.....ABCDEF
- + "| \u011e \u0130 "
- // 0123.....456789ABCDEF
- + " \u015e "
- // 0123.....45.....67.....89.....ABCDEF
- + " \u00e7 \u20ac \u011f \u0131 "
- // 0123.....456789ABCDEF
- + " \u015f ",
-
- /**
- * National Language Identifier: 0x02
- * A.2.2 Spanish National Language Single Shift Table
- */
- // 0123456789.....A.....BCD.....EF
- " \u00e7\u000c \ufffe "
- // 0123456789AB.....CDEF
- + " ^ \uffff "
- // 0123456789ABCDEF.
- + " {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 01.....23456789.....ABCDEF.....
- + "|\u00c1 \u00cd \u00d3"
- // 012345.....6789ABCDEF
- + " \u00da "
- // 01.....2345.....6789.....ABCDEF.....
- + " \u00e1 \u20ac \u00ed \u00f3"
- // 012345.....6789ABCDEF
- + " \u00fa ",
-
- /**
- * National Language Identifier: 0x03
- * A.2.3 Portuguese National Language Single Shift Table
- */
- // 012345.....6789.....A.....B.....C.....D.....E.....F.....
- " \u00ea \u00e7\u000c\u00d4\u00f4\ufffe\u00c1\u00e1"
- // 012.....3.....45.....6.....7.....8.....9.....AB.....CDEF.....
- + " \u03a6\u0393^\u03a9\u03a0\u03a8\u03a3\u0398 \uffff \u00ca"
- // 0123456789ABCDEF.
- + " {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 01.....23456789.....ABCDEF.....
- + "|\u00c0 \u00cd \u00d3"
- // 012345.....6789AB.....C.....DEF
- + " \u00da \u00c3\u00d5 "
- // 01.....2345.....6789.....ABCDEF.....
- + " \u00c2 \u20ac \u00ed \u00f3"
- // 012345.....6789AB.....C.....DEF.....
- + " \u00fa \u00e3\u00f5 \u00e2",
-
- /**
- * National Language Identifier: 0x04
- * A.2.4 Bengali National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u09e6\u09e7\uffff\u09e8\u09e9\u09ea\u09eb"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u09ec\u09ed\u09ee\u09ef\u09df\u09e0\u09e1\u09e2{}\u09e3\u09f2\u09f3\u09f4\u09f5\\"
- // 0.....1.....2.....3.....4.....56789ABCDEF
- + "\u09f6\u09f7\u09f8\u09f9\u09fa [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x05
- * A.2.5 Gujarati National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0ae6\u0ae7\u0ae8\u0ae9"
- // 0.....1.....2.....3.....4.....5.....6789ABCDEF.
- + "\u0aea\u0aeb\u0aec\u0aed\u0aee\u0aef {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x06
- * A.2.6 Hindi National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0966\u0967\u0968\u0969"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u096a\u096b\u096c\u096d\u096e\u096f\u0951\u0952{}\u0953\u0954\u0958\u0959\u095a\\"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....BCDEF
- + "\u095b\u095c\u095d\u095e\u095f\u0960\u0961\u0962\u0963\u0970\u0971 [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x07
- * A.2.7 Kannada National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0ce6\u0ce7\u0ce8\u0ce9"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....BCDEF.
- + "\u0cea\u0ceb\u0cec\u0ced\u0cee\u0cef\u0cde\u0cf1{}\u0cf2 \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x08
- * A.2.8 Malayalam National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0d66\u0d67\u0d68\u0d69"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u0d6a\u0d6b\u0d6c\u0d6d\u0d6e\u0d6f\u0d70\u0d71{}\u0d72\u0d73\u0d74\u0d75\u0d7a\\"
- // 0.....1.....2.....3.....4.....56789ABCDEF
- + "\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x09
- * A.2.9 Oriya National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0b66\u0b67\u0b68\u0b69"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....DEF.
- + "\u0b6a\u0b6b\u0b6c\u0b6d\u0b6e\u0b6f\u0b5c\u0b5d{}\u0b5f\u0b70\u0b71 \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x0A
- * A.2.10 Punjabi National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0a66\u0a67\u0a68\u0a69"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....EF.
- + "\u0a6a\u0a6b\u0a6c\u0a6d\u0a6e\u0a6f\u0a59\u0a5a{}\u0a5b\u0a5c\u0a5e\u0a75 \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x0B
- * A.2.11 Tamil National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0be6\u0be7\u0be8\u0be9"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u0bea\u0beb\u0bec\u0bed\u0bee\u0bef\u0bf3\u0bf4{}\u0bf5\u0bf6\u0bf7\u0bf8\u0bfa\\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x0C
- * A.2.12 Telugu National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789AB.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#* \uffff\u0c66\u0c67\u0c68\u0c69"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u0c6a\u0c6b\u0c6c\u0c6d\u0c6e\u0c6f\u0c58\u0c59{}\u0c78\u0c79\u0c7a\u0c7b\u0c7c\\"
- // 0.....1.....2.....3456789ABCDEF
- + "\u0c7d\u0c7e\u0c7f [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x0D
- * A.2.13 Urdu National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0600\u0601\uffff\u06f0\u06f1\u06f2\u06f3"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u060c\u060d{}\u060e\u060f\u0610\u0611\u0612\\"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....CDEF.....
- + "\u0613\u0614\u061b\u061f\u0640\u0652\u0658\u066b\u066c\u0672\u0673\u06cd[~]\u06d4"
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " "
-];
-
-// Special SMS Message Indication constants
-this.PDU_MWI_STORE_TYPE_BIT = 0x80;
-this.PDU_MWI_STORE_TYPE_DISCARD = 0x00;
-this.PDU_MWI_STORE_TYPE_STORE = 0x80;
-
-this.GSM_SMS_STRICT_7BIT_CHARMAP = {
-//"\u0024": "\u0024", // "$" => "$", already in default alphabet
-//"\u00a5": "\u00a5", // "¥" => "¥", already in default alphabet
- "\u00c0": "\u0041", // "À" => "A"
- "\u00c1": "\u0041", // "Á" => "A"
- "\u00c2": "\u0041", // "Â" => "A"
- "\u00c3": "\u0041", // "Ã" => "A"
-//"\u00c4": "\u00c4", // "Ä" => "Ä", already in default alphabet
-//"\u00c5": "\u00c5", // "Å" => "Å", already in default alphabet
-//"\u00c6": "\u00c6", // "Æ" => "Æ", already in default alphabet
-//"\u00c7": "\u00c7", // "Ç" => "Ç", already in default alphabet
- "\u00c8": "\u0045", // "È" => "E"
-//"\u00c9": "\u00c9", // "É" => "É", already in default alphabet
- "\u00ca": "\u0045", // "Ê" => "E"
- "\u00cb": "\u0045", // "Ë" => "E"
- "\u00cc": "\u0049", // "Ì" => "I"
- "\u00cd": "\u0049", // "Í" => "I"
- "\u00ce": "\u0049", // "Î" => "I"
- "\u00cf": "\u0049", // "Ï" => "I"
-//"\u00d1": "\u00d1", // "Ñ" => "Ñ", already in default alphabet
- "\u00d2": "\u004f", // "Ò" => "O"
- "\u00d3": "\u004f", // "Ó" => "O"
- "\u00d4": "\u004f", // "Ô" => "O"
- "\u00d5": "\u004f", // "Õ" => "O"
-//"\u00d6": "\u00d6", // "Ö" => "Ö", already in default alphabet
- "\u00d9": "\u0055", // "Ù" => "U"
- "\u00da": "\u0055", // "Ú" => "U"
- "\u00db": "\u0055", // "Û" => "U"
-//"\u00dc": "\u00dc", // "Ü" => "Ü", already in default alphabet
-//"\u00df": "\u00df", // "ß" => "ß", already in default alphabet
-//"\u00e0": "\u00e0", // "à" => "à", already in default alphabet
- "\u00e1": "\u0061", // "á" => "a"
- "\u00e2": "\u0061", // "â" => "a"
- "\u00e3": "\u0061", // "ã" => "a"
-//"\u00e4": "\u00e4", // "ä" => "ä", already in default alphabet
-//"\u00e5": "\u00e5", // "å" => "å", already in default alphabet
-//"\u00e6": "\u00e6", // "æ" => "æ", already in default alphabet
- "\u00e7": "\u00c7", // "ç" => "Ç"
-//"\u00e8": "\u00e8", // "è" => "è", already in default alphabet
-//"\u00e9": "\u00e9", // "é" => "é", already in default alphabet
- "\u00ea": "\u0065", // "ê" => "e"
- "\u00eb": "\u0065", // "ë" => "e"
-//"\u00ec": "\u00ec", // "ì" => "ì", already in default alphabet
- "\u00ed": "\u0069", // "í" => "i"
- "\u00ee": "\u0069", // "î" => "i"
- "\u00ef": "\u0069", // "ï" => "i"
-//"\u00f1": "\u00f1", // "ñ" => "ñ", already in default alphabet
-//"\u00f2": "\u00f2", // "ò" => "ò", already in default alphabet
- "\u00f3": "\u006f", // "ó" => "o"
- "\u00f4": "\u006f", // "ô" => "o"
- "\u00f5": "\u006f", // "õ" => "o"
-//"\u00f6": "\u00f6", // "ö" => "ö", already in default alphabet
-//"\u00f8": "\u00f8", // "ø" => "ø", already in default alphabet
-//"\u00f9": "\u00f9", // "ù" => "ù", already in default alphabet
- "\u00fa": "\u0075", // "ú" => "u"
- "\u00fb": "\u0075", // "û" => "u"
-//"\u00fc": "\u00fc", // "ü" => "ü", already in default alphabet
- "\u00fe": "\u0074", // "þ" => "t"
- "\u0100": "\u0041", // "Ā" => "A"
- "\u0101": "\u0061", // "ā" => "a"
- "\u0106": "\u0043", // "Ć" => "C"
- "\u0107": "\u0063", // "ć" => "c"
- "\u010c": "\u0043", // "Č" => "C"
- "\u010d": "\u0063", // "č" => "c"
- "\u010f": "\u0064", // "ď" => "d"
- "\u0110": "\u0044", // "Đ" => "D"
- "\u0111": "\u0064", // "đ" => "d"
- "\u0112": "\u0045", // "Ē" => "E"
- "\u0113": "\u0065", // "ē" => "e"
- "\u0118": "\u0045", // "Ę" => "E"
- "\u0119": "\u0065", // "ę" => "e"
- "\u0128": "\u0049", // "Ĩ" => "I"
- "\u0129": "\u0069", // "ĩ" => "i"
- "\u012a": "\u0049", // "Ī" => "I"
- "\u012b": "\u0069", // "ī" => "i"
- "\u012e": "\u0049", // "Į" => "I"
- "\u012f": "\u0069", // "į" => "i"
- "\u0141": "\u004c", // "Ł" => "L"
- "\u0142": "\u006c", // "ł" => "l"
- "\u0143": "\u004e", // "Ń" => "N"
- "\u0144": "\u006e", // "ń" => "n"
- "\u0147": "\u004e", // "Ň" => "N"
- "\u0148": "\u006e", // "ň" => "n"
- "\u014c": "\u004f", // "Ō" => "O"
- "\u014d": "\u006f", // "ō" => "o"
- "\u0152": "\u004f", // "Œ" => "O"
- "\u0153": "\u006f", // "œ" => "o"
- "\u0158": "\u0052", // "Ř" => "R"
- "\u0159": "\u0072", // "ř" => "r"
- "\u0160": "\u0053", // "Š" => "S"
- "\u0161": "\u0073", // "š" => "s"
- "\u0165": "\u0074", // "ť" => "t"
- "\u0168": "\u0055", // "Ū" => "U"
- "\u0169": "\u0075", // "ū" => "u"
- "\u016a": "\u0055", // "Ū" => "U"
- "\u016b": "\u0075", // "ū" => "u"
- "\u0178": "\u0059", // "Ÿ" => "Y"
- "\u0179": "\u005a", // "Ź" => "Z"
- "\u017a": "\u007a", // "ź" => "z"
- "\u017b": "\u005a", // "Ż" => "Z"
- "\u017c": "\u007a", // "ż" => "z"
- "\u017d": "\u005a", // "Ž" => "Z"
- "\u017e": "\u007a", // "ž" => "z"
- "\u025b": "\u0045", // "ɛ" => "E"
-//"\u0398": "\u0398", // "Θ" => "Θ", already in default alphabet
- "\u1e7c": "\u0056", // "Ṽ" => "V"
- "\u1e7d": "\u0076", // "ṽ" => "v"
- "\u1ebc": "\u0045", // "Ẽ" => "E"
- "\u1ebd": "\u0065", // "ẽ" => "e"
- "\u1ef8": "\u0059", // "Ỹ" => "Y"
- "\u1ef9": "\u0079", // "ỹ" => "y"
- "\u20a4": "\u00a3", // "₤" => "£"
-//"\u20ac": "\u20ac", // "€" => "€", already in default alphabet
-};
-
-this.RADIOTECH_FAMILY_3GPP = 1; // GSM, WCDMA, LTE
-this.RADIOTECH_FAMILY_3GPP2 = 2; // CDMA, EVDO
-
-this.DATACALL_RADIOTECHNOLOGY_CDMA = 0;
-this.DATACALL_RADIOTECHNOLOGY_GSM = 1;
-
-this.DATACALL_AUTH_NONE = 0;
-this.DATACALL_AUTH_PAP = 1;
-this.DATACALL_AUTH_CHAP = 2;
-this.DATACALL_AUTH_PAP_OR_CHAP = 3;
-
-this.GECKO_DATACALL_AUTH_NONE = "none";
-this.GECKO_DATACALL_AUTH_PAP = "pap";
-this.GECKO_DATACALL_AUTH_CHAP = "chap";
-this.GECKO_DATACALL_AUTH_PAP_OR_CHAP = "papOrChap";
-this.GECKO_DATACALL_AUTH_DEFAULT = GECKO_DATACALL_AUTH_PAP_OR_CHAP;
-this.RIL_DATACALL_AUTH_TO_GECKO = [
- GECKO_DATACALL_AUTH_NONE, // DATACALL_AUTH_NONE
- GECKO_DATACALL_AUTH_PAP, // DATACALL_AUTH_PAP
- GECKO_DATACALL_AUTH_CHAP, // DATACALL_AUTH_CHAP
- GECKO_DATACALL_AUTH_PAP_OR_CHAP // DATACALL_AUTH_PAP_OR_CHAP
-];
-
-this.GECKO_DATACALL_PDP_TYPE_IP = "IP";
-this.GECKO_DATACALL_PDP_TYPE_IPV4V6 = "IPV4V6";
-this.GECKO_DATACALL_PDP_TYPE_IPV6 = "IPV6";
-this.GECKO_DATACALL_PDP_TYPE_DEFAULT = GECKO_DATACALL_PDP_TYPE_IP;
-this.RIL_DATACALL_PDP_TYPES = [
- GECKO_DATACALL_PDP_TYPE_IP,
- GECKO_DATACALL_PDP_TYPE_IPV4V6,
- GECKO_DATACALL_PDP_TYPE_IPV6,
-];
-
-this.DATACALL_PROFILE_DEFAULT = 0;
-this.DATACALL_PROFILE_TETHERED = 1;
-this.DATACALL_PROFILE_OEM_BASE = 1000;
-
-this.DATACALL_DEACTIVATE_NO_REASON = 0;
-this.DATACALL_DEACTIVATE_RADIO_SHUTDOWN = 1;
-
-this.DATACALL_ACTIVE_UNKNOWN = -1;
-this.DATACALL_INACTIVE = 0;
-this.DATACALL_ACTIVE_DOWN = 1;
-this.DATACALL_ACTIVE_UP = 2;
-
-this.DATACALL_FAIL_NONE = 0;
-this.DATACALL_FAIL_OPERATOR_BARRED = 0x08;
-this.DATACALL_FAIL_INSUFFICIENT_RESOURCES = 0x1A;
-this.DATACALL_FAIL_MISSING_UKNOWN_APN = 0x1B;
-this.DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;
-this.DATACALL_FAIL_USER_AUTHENTICATION = 0x1D;
-this.DATACALL_FAIL_ACTIVATION_REJECT_GGSN = 0x1E;
-this.DATACALL_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
-this.DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20;
-this.DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;
-this.DATACALL_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22;
-this.DATACALL_FAIL_NSAPI_IN_USE = 0x23;
-this.DATACALL_FAIL_ONLY_IPV4_ALLOWED = 0x32;
-this.DATACALL_FAIL_ONLY_IPV6_ALLOWED = 0x33;
-this.DATACALL_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34;
-this.DATACALL_FAIL_PROTOCOL_ERRORS = 0x6F;
-this.DATACALL_FAIL_VOICE_REGISTRATION_FAIL = -1;
-this.DATACALL_FAIL_DATA_REGISTRATION_FAIL = -2;
-this.DATACALL_FAIL_SIGNAL_LOST = -3;
-this.DATACALL_FAIL_PREF_RADIO_TECH_CHANGED = -4;
-this.DATACALL_FAIL_RADIO_POWER_OFF = -5;
-this.DATACALL_FAIL_TETHERED_CALL_ACTIVE = -6;
-this.DATACALL_FAIL_ERROR_UNSPECIFIED = 0xffff;
-
-// Keep consistent with nsINetworkManager.NETWORK_STATE_*.
-this.GECKO_NETWORK_STATE_UNKNOWN = -1;
-this.GECKO_NETWORK_STATE_CONNECTING = 0;
-this.GECKO_NETWORK_STATE_CONNECTED = 1;
-this.GECKO_NETWORK_STATE_DISCONNECTING = 2;
-this.GECKO_NETWORK_STATE_DISCONNECTED = 3;
-
-// 3GPP 24.008 Annex H.
-this.CALL_FAIL_UNOBTAINABLE_NUMBER = 1;
-this.CALL_FAIL_NO_ROUTE_TO_DESTINATION = 3;
-this.CALL_FAIL_CHANNEL_UNACCEPTABLE = 6;
-this.CALL_FAIL_OPERATOR_DETERMINED_BARRING = 8;
-this.CALL_FAIL_NORMAL = 16;
-this.CALL_FAIL_BUSY = 17;
-this.CALL_FAIL_NO_USER_RESPONDING = 18;
-this.CALL_FAIL_USER_ALERTING = 19;
-this.CALL_FAIL_CALL_REJECTED = 21;
-this.CALL_FAIL_NUMBER_CHANGED = 22;
-this.CALL_FAIL_CALL_REJECTED_DESTINATION_FEATURE = 24;
-this.CALL_FAIL_CALL_PRE_EMPTION = 25;
-this.CALL_FAIL_DEST_OUT_OF_ORDER = 27;
-this.CALL_FAIL_INVALID_FORMAT = 28;
-this.CALL_FAIL_FACILITY_REJECTED = 29;
-this.CALL_FAIL_RESPONSE_TO_STATUS_ENQUIRY = 30;
-this.CALL_FAIL_NORMAL_UNSPECIFIED = 31;
-this.CALL_FAIL_CONGESTION = 34;
-this.CALL_FAIL_NETWORK_OUT_OF_ORDER = 38;
-this.CALL_FAIL_NETWORK_TEMP_FAILURE = 41;
-this.CALL_FAIL_SWITCHING_EQUIP_CONGESTION = 42;
-this.CALL_FAIL_ACCESS_INFO_DISCARDED = 43;
-this.CALL_FAIL_REQUESTED_CHANNEL_NOT_AVAILABLE = 44;
-this.CALL_FAIL_RESOURCE_UNAVAILABLE = 47;
-this.CALL_FAIL_QOS_UNAVAILABLE = 49;
-this.CALL_FAIL_REQUESTED_FACILITY_NOT_SUBSCRIBED = 50;
-this.CALL_FAIL_INCOMING_CALLS_BARRED_WITHIN_CUG = 55;
-this.CALL_FAIL_BEARER_CAPABILITY_NOT_AUTHORIZED = 57;
-this.CALL_FAIL_BEARER_CAPABILITY_NOT_AVAILABLE = 58;
-this.CALL_FAIL_SERVICE_NOT_AVAILABLE = 63;
-this.CALL_FAIL_BEARER_NOT_IMPLEMENTED = 65;
-this.CALL_FAIL_ACM_LIMIT_EXCEEDED = 68;
-this.CALL_FAIL_REQUESTED_FACILITY_NOT_IMPLEMENTED = 69;
-this.CALL_FAIL_UNRESTRICTED_BEARER_NOT_AVAILABLE = 70;
-this.CALL_FAIL_SERVICE_NOT_IMPLEMENTED = 79;
-this.CALL_FAIL_INVALID_TRANSACTION_ID = 81;
-this.CALL_FAIL_USER_NOT_CUG_MEMBER = 87;
-this.CALL_FAIL_INCOMPATIBLE_DESTINATION = 88;
-this.CALL_FAIL_INVALID_TRANSIT_NETWORK_SELECTION = 91;
-this.CALL_FAIL_SEMANTICALLY_INCORRECT_MESSAGE = 95;
-this.CALL_FAIL_INVALID_MANDATORY_INFO = 96;
-this.CALL_FAIL_MESSAGE_TYPE_NOT_IMPLEMENTED = 97;
-this.CALL_FAIL_MESSAGE_TYPE_INCOMPATIBLE_PROTOCOL_STATE = 98;
-this.CALL_FAIL_INFO_ELEMENT_NOT_IMPLEMENTED = 99;
-this.CALL_FAIL_CONDITIONAL_IE_ERROR = 100;
-this.CALL_FAIL_MESSAGE_INCOMPABITLE_PROTOCOL_STATE = 101;
-this.CALL_FAIL_RECOVERY_ON_TIMER_EXPIRY = 102;
-this.CALL_FAIL_PROTOCOL_ERROR = 111;
-this.CALL_FAIL_INTERWORKING = 127;
-// AOSP ril.h
-this.CALL_FAIL_CALL_BARRED = 240;
-this.CALL_FAIL_FDN_BLOCKED = 241;
-this.CALL_FAIL_IMSI_UNKNOWN_IN_VLR = 242;
-this.CALL_FAIL_IMEI_NOT_ACCEPTED = 243;
-this.CALL_FAIL_DIAL_MODIFIED_TO_USSD = 244; // STK Call Control
-this.CALL_FAIL_DIAL_MODIFIED_TO_SS = 245;
-this.CALL_FAIL_DIAL_MODIFIED_TO_DIAL = 246;
-this.CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000;
-this.CALL_FAIL_CDMA_DROP = 1001;
-this.CALL_FAIL_CDMA_INTERCEPT = 1002;
-this.CALL_FAIL_CDMA_REORDER = 1003;
-this.CALL_FAIL_CDMA_SO_REJECT = 1004;
-this.CALL_FAIL_CDMA_RETRY_ORDER = 1005;
-this.CALL_FAIL_CDMA_ACCESS_FAILURE = 1006;
-this.CALL_FAIL_CDMA_PREEMPTED = 1007;
-this.CALL_FAIL_CDMA_NOT_EMERGENCY = 1008; // For non-emergency number dialed
- // during emergency callback mode
-this.CALL_FAIL_CDMA_ACCESS_BLOCKED = 1009;
-this.CALL_FAIL_ERROR_UNSPECIFIED = 0xffff;
-
-// See nsIMobileConnection::MOBILE_RADIO_STATE_*
-this.GECKO_RADIOSTATE_UNKNOWN = -1;
-this.GECKO_RADIOSTATE_ENABLED = 0;
-this.GECKO_RADIOSTATE_DISABLED = 1;
-
-// Only used in ril_worker.js
-this.GECKO_CARDSTATE_UNINITIALIZED = 4294967294; // UINT32_MAX - 1
-// See nsIIcc::CARD_STATE_*
-this.GECKO_CARDSTATE_UNDETECTED = 4294967295; // UINT32_MAX
-this.GECKO_CARDSTATE_UNKNOWN = 0;
-this.GECKO_CARDSTATE_READY = 1;
-this.GECKO_CARDSTATE_PIN_REQUIRED = 2;
-this.GECKO_CARDSTATE_PUK_REQUIRED = 3;
-this.GECKO_CARDSTATE_PERMANENT_BLOCKED = 4;
-this.GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS = 5;
-this.GECKO_CARDSTATE_PERSONALIZATION_READY = 6;
-this.GECKO_CARDSTATE_NETWORK_LOCKED = 7;
-this.GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED = 8;
-this.GECKO_CARDSTATE_CORPORATE_LOCKED = 9;
-this.GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED = 10;
-this.GECKO_CARDSTATE_SIM_LOCKED = 11;
-this.GECKO_CARDSTATE_NETWORK_PUK_REQUIRED = 12;
-this.GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED = 13;
-this.GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED = 14;
-this.GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED = 15;
-this.GECKO_CARDSTATE_SIM_PUK_REQUIRED = 16;
-this.GECKO_CARDSTATE_NETWORK1_LOCKED = 17;
-this.GECKO_CARDSTATE_NETWORK2_LOCKED = 18;
-this.GECKO_CARDSTATE_HRPD_NETWORK_LOCKED = 19;
-this.GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED = 20;
-this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED = 21;
-this.GECKO_CARDSTATE_RUIM_LOCKED = 22;
-this.GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED = 23;
-this.GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED = 24;
-this.GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED = 25;
-this.GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
-this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
-this.GECKO_CARDSTATE_RUIM_PUK_REQUIRED = 28;
-this.GECKO_CARDSTATE_ILLEGAL = 29;
-
-// See nsIIcc::CARD_LOCK_TYPE_*
-this.GECKO_CARDLOCK_PIN = 0;
-this.GECKO_CARDLOCK_PIN2 = 1;
-this.GECKO_CARDLOCK_PUK = 2;
-this.GECKO_CARDLOCK_PUK2 = 3;
-this.GECKO_CARDLOCK_NCK = 4;
-this.GECKO_CARDLOCK_NSCK = 5;
-this.GECKO_CARDLOCK_NCK1 = 6;
-this.GECKO_CARDLOCK_NCK2 = 7;
-this.GECKO_CARDLOCK_HNCK = 8;
-this.GECKO_CARDLOCK_CCK = 9;
-this.GECKO_CARDLOCK_SPCK = 10;
-this.GECKO_CARDLOCK_PCK = 11;
-this.GECKO_CARDLOCK_RCCK = 12;
-this.GECKO_CARDLOCK_RSPCK = 13;
-this.GECKO_CARDLOCK_NCK_PUK = 14;
-this.GECKO_CARDLOCK_NSCK_PUK = 15;
-this.GECKO_CARDLOCK_NCK1_PUK = 16;
-this.GECKO_CARDLOCK_NCK2_PUK = 17;
-this.GECKO_CARDLOCK_HNCK_PUK = 18;
-this.GECKO_CARDLOCK_CCK_PUK = 19;
-this.GECKO_CARDLOCK_SPCK_PUK = 20;
-this.GECKO_CARDLOCK_PCK_PUK = 21;
-this.GECKO_CARDLOCK_RCCK_PUK = 22;
-this.GECKO_CARDLOCK_RSPCK_PUK = 23;
-this.GECKO_CARDLOCK_FDN = 24;
-
-this.GECKO_CARDLOCK_TO_FACILITY = {};
-GECKO_CARDLOCK_TO_FACILITY[GECKO_CARDLOCK_PIN] = ICC_CB_FACILITY_SIM;
-GECKO_CARDLOCK_TO_FACILITY[GECKO_CARDLOCK_FDN] = ICC_CB_FACILITY_FDN;
-
-this.GECKO_CARDLOCK_TO_SEL_CODE = {};
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PIN] = ICC_SEL_CODE_SIM_PIN;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PIN2] = ICC_SEL_CODE_SIM_PIN2;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PUK] = ICC_SEL_CODE_SIM_PUK;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PUK2] = ICC_SEL_CODE_SIM_PUK2;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_NCK] = ICC_SEL_CODE_PH_NET_PIN;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_NSCK] = ICC_SEL_CODE_PH_NETSUB_PIN;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_CCK] = ICC_SEL_CODE_PH_CORP_PIN;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_SPCK] = ICC_SEL_CODE_PH_SP_PIN;
-// TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM @
-// ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_PCK.
-
-// See nsIIcc::CARD_CONTACT_TYPE_*
-this.GECKO_CARDCONTACT_TYPE_ADN = 0;
-this.GECKO_CARDCONTACT_TYPE_FDN = 1;
-this.GECKO_CARDCONTACT_TYPE_SDN = 2;
-
-// See nsIIcc::CARD_MVNO_TYPE_*
-this.GECKO_CARDMVNO_TYPE_IMSI = 0;
-this.GECKO_CARDMVNO_TYPE_SPN = 1;
-this.GECKO_CARDMVNO_TYPE_GID = 2;
-
-// See nsIIcc::CARD_SERVICE_*
-this.GECKO_CARDSERVICE_FDN = 0;
-
-// See ril.h RIL_PersoSubstate
-this.PERSONSUBSTATE = {};
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_UNKNOWN] = GECKO_CARDSTATE_UNKNOWN;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_IN_PROGRESS] = GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_READY] = GECKO_CARDSTATE_PERSONALIZATION_READY;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK] = GECKO_CARDSTATE_NETWORK_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET] = GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE] = GECKO_CARDSTATE_CORPORATE_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER] = GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SIM] = GECKO_CARDSTATE_SIM_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_PUK] = GECKO_CARDSTATE_NETWORK_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK] = GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK] = GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SIM_PUK] = GECKO_CARDSTATE_SIM_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1] = GECKO_CARDSTATE_NETWORK1_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2] = GECKO_CARDSTATE_NETWORK2_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_HRPD] = GECKO_CARDSTATE_HRPD_NETWORK_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_CORPORATE] = GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER] = GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_RUIM] = GECKO_CARDSTATE_RUIM_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK] = GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK] = GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_HRPD_PUK] = GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK] = GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_RUIM_PUK] = GECKO_CARDSTATE_RUIM_PUK_REQUIRED;
-
-// See nsIMobileConnection::NETWORK_SELECTION_MODE_*
-this.GECKO_NETWORK_SELECTION_UNKNOWN = -1;
-this.GECKO_NETWORK_SELECTION_AUTOMATIC = 0;
-this.GECKO_NETWORK_SELECTION_MANUAL = 1;
-
-this.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN = null;
-this.GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING = "notSearching";
-this.GECKO_MOBILE_CONNECTION_STATE_SEARCHING = "searching";
-this.GECKO_MOBILE_CONNECTION_STATE_REGISTERED = "registered";
-this.GECKO_MOBILE_CONNECTION_STATE_DENIED = "denied";
-
-this.NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE = {};
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_HOME] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_SEARCHING;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED] = GECKO_MOBILE_CONNECTION_STATE_DENIED;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_ROAMING] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_SEARCHING;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_DENIED;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
-
-
-// Should match enum TelephonyCallDisconnectedReason defined in TelephonyCall.webidl
-this.GECKO_CALL_ERROR_BAD_NUMBER = "BadNumberError";
-this.GECKO_CALL_ERROR_NO_ROUTE_TO_DESTINATION = "NoRouteToDestinationError";
-this.GECKO_CALL_ERROR_CHANNEL_UNACCEPTABLE = "ChannelUnacceptableError";
-this.GECKO_CALL_ERROR_OPERATOR_DETERMINED_BARRING = "OperatorDeterminedBarringError";
-this.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING = "NormalCallClearingError";
-this.GECKO_CALL_ERROR_BUSY = "BusyError";
-this.GECKO_CALL_ERROR_NO_USER_RESPONDING = "NoUserRespondingError";
-this.GECKO_CALL_ERROR_USER_ALERTING = "UserAlertingNoAnswerError";
-this.GECKO_CALL_ERROR_REJECTED = "CallRejectedError";
-this.GECKO_CALL_ERROR_NUMBER_CHANGED = "NumberChangedError";
-this.GECKO_CALL_ERROR_REJECTED_DETINATION_FEATURE = "CallRejectedDestinationFeatureError";
-this.GECKO_CALL_ERROR_PRE_EMPTION = "PreEmptionError";
-this.GECKO_CALL_ERROR_DEST_OUT_OF_ORDER = "DestinationOutOfOrderError";
-this.GECKO_CALL_ERROR_INVALID_NUMBER_FORMAT = "InvalidNumberFormatError";
-this.GECKO_CALL_ERROR_FACILITY_REJECTED = "FacilityRejectedError";
-this.GECKO_CALL_ERROR_RESPONSE_TO_STATUS_ENQUIRY = "ResponseToStatusEnquiryError";
-this.GECKO_CALL_ERROR_CONGESTION = "CongestionError";
-this.GECKO_CALL_ERROR_NETWORK_OUT_OF_ORDER = "NetworkOutOfOrderError";
-this.GECKO_CALL_ERROR_NETWORK_TEMP_FAILURE = "NetworkTempFailureError";
-this.GECKO_CALL_ERROR_SWITCHING_EQUIP_CONGESTION = "SwitchingEquipCongestionError";
-this.GECKO_CALL_ERROR_ACCESS_INFO_DISCARDED = "AccessInfoDiscardedError";
-this.GECKO_CALL_ERROR_REQUESTED_CHANNEL_NOT_AVAILABLE = "RequestedChannelNotAvailableError";
-this.GECKO_CALL_ERROR_RESOURCE_UNAVAILABLE = "ResourceUnavailableError";
-this.GECKO_CALL_ERROR_QOS_UNAVAILABLE = "QosUnavailableError";
-this.GECKO_CALL_ERROR_REQUESTED_FACILITY_NOT_SUBSCRIBED = "RequestedFacilityNotSubscribedError";
-this.GECKO_CALL_ERROR_INCOMING_CALLS_BARRED_WITHIN_CUG = "IncomingCallsBarredWithinCugError";
-this.GECKO_CALL_ERROR_BEARER_CAPABILITY_NOT_AUTHORIZED = "BearerCapabilityNotAuthorizedError";
-this.GECKO_CALL_ERROR_BEARER_CAPABILITY_NOT_AVAILABLE = "BearerCapabilityNotAvailableError";
-this.GECKO_CALL_ERROR_BEARER_NOT_IMPLEMENTED = "BearerNotImplementedError";
-this.GECKO_CALL_ERROR_SERVICE_NOT_AVAILABLE = "ServiceNotAvailableError";
-this.GECKO_CALL_ERROR_INCOMING_CALL_EXCEEDED = "IncomingCallExceededError";
-this.GECKO_CALL_ERROR_REQUESTED_FACILITY_NOT_IMPLEMENTED = "RequestedFacilityNotImplementedError";
-this.GECKO_CALL_ERROR_UNRESTRICTED_BEARER_NOT_AVAILABLE = "UnrestrictedBearerNotAvailableError";
-this.GECKO_CALL_ERROR_SERVICE_NOT_IMPLEMENTED = "ServiceNotImplementedError";
-this.GECKO_CALL_ERROR_INVALID_TRANSACTION_ID = "InvalidTransactionIdError";
-this.GECKO_CALL_ERROR_USER_NOT_CUG_MEMBER = "NotCugMemberError";
-this.GECKO_CALL_ERROR_INCOMPATIBLE_DESTINATION = "IncompatibleDestinationError";
-this.GECKO_CALL_ERROR_INVALID_TRANSIT_NETWORK_SELECTION = "InvalidTransitNetworkSelectionError";
-this.GECKO_CALL_ERROR_SEMANTICALLY_INCORRECT_MESSAGE = "SemanticallyIncorrectMessageError";
-this.GECKO_CALL_ERROR_INVALID_MANDATORY_INFO = "InvalidMandatoryInfoError";
-this.GECKO_CALL_ERROR_MESSAGE_TYPE_NOT_IMPLEMENTED = "MessageTypeNotImplementedError";
-this.GECKO_CALL_ERROR_MESSAGE_TYPE_INCOMPATIBLE_PROTOCOL_STATE = "MessageTypeIncompatibleProtocolStateError";
-this.GECKO_CALL_ERROR_INFO_ELEMENT_NOT_IMPLEMENTED = "InfoElementNotImplementedError";
-this.GECKO_CALL_ERROR_CONDITIONAL_IE = "ConditionalIeError";
-this.GECKO_CALL_ERROR_MESSAGE_INCOMPATIBLE_PROTOCOL_STATE = "MessageIncompatibleProtocolStateError";
-this.GECKO_CALL_ERROR_RECOVERY_ON_TIMER_EXPIRY = "RecoveryOnTimerExpiryError";
-this.GECKO_CALL_ERROR_PROTOCOL = "ProtocolError";
-this.GECKO_CALL_ERROR_INTERWORKING = "InterworkingError";
-this.GECKO_CALL_ERROR_BARRED = "BarredError";
-this.GECKO_CALL_ERROR_FDN_BLOCKED = "FDNBlockedError";
-this.GECKO_CALL_ERROR_SUBSCRIBER_UNKNOWN = "SubscriberUnknownError";
-this.GECKO_CALL_ERROR_DEVICE_NOT_ACCEPTED = "DeviceNotAcceptedError";
-this.GECKO_CALL_ERROR_MODIFIED_TO_DIAL_FAILED = "ModifiedDialError";
-this.GECKO_CALL_ERROR_CDMA_LOCKED_UNTIL_POWER_CYCLE = "CdmaLockedUntilPowerCycleError";
-this.GECKO_CALL_ERROR_CDMA_DROP = "CdmaDropError";
-this.GECKO_CALL_ERROR_CDMA_INTERCEPT = "CdmaInterceptError";
-this.GECKO_CALL_ERROR_CDMA_REORDER = "CdmaReorderError";
-this.GECKO_CALL_ERROR_CDMA_SO_REJECT = "CdmaSoRejectError";
-this.GECKO_CALL_ERROR_CDMA_RETRY_ORDER = "CdmaRetryOrderError";
-this.GECKO_CALL_ERROR_CDMA_ACCESS_FAILURE = "CdmaAcessError";
-this.GECKO_CALL_ERROR_CDMA_PREEMPTED = "CdmaPreemptedError";
-this.GECKO_CALL_ERROR_CDMA_NOT_EMERGENCY = "CdmaNotEmergencyError";
-this.GECKO_CALL_ERROR_CDMA_ACCESS_BLOCKED = "CdmaAccessBlockedError";
-this.GECKO_CALL_ERROR_UNSPECIFIED = "UnspecifiedError";
-
-this.RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR = {};
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNOBTAINABLE_NUMBER] = GECKO_CALL_ERROR_BAD_NUMBER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NO_ROUTE_TO_DESTINATION] = GECKO_CALL_ERROR_NO_ROUTE_TO_DESTINATION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CHANNEL_UNACCEPTABLE] = GECKO_CALL_ERROR_CHANNEL_UNACCEPTABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_OPERATOR_DETERMINED_BARRING] = GECKO_CALL_ERROR_OPERATOR_DETERMINED_BARRING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NORMAL] = GECKO_CALL_ERROR_NORMAL_CALL_CLEARING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BUSY] = GECKO_CALL_ERROR_BUSY;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NO_USER_RESPONDING] = GECKO_CALL_ERROR_NO_USER_RESPONDING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_USER_ALERTING] = GECKO_CALL_ERROR_USER_ALERTING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_REJECTED] = GECKO_CALL_ERROR_REJECTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NUMBER_CHANGED] = GECKO_CALL_ERROR_NUMBER_CHANGED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_REJECTED_DESTINATION_FEATURE] = GECKO_CALL_ERROR_REJECTED_DETINATION_FEATURE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_PRE_EMPTION] = GECKO_CALL_ERROR_PRE_EMPTION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_DEST_OUT_OF_ORDER] = GECKO_CALL_ERROR_DEST_OUT_OF_ORDER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INVALID_FORMAT] = GECKO_CALL_ERROR_INVALID_NUMBER_FORMAT;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_FACILITY_REJECTED] = GECKO_CALL_ERROR_FACILITY_REJECTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_RESPONSE_TO_STATUS_ENQUIRY] = GECKO_CALL_ERROR_RESPONSE_TO_STATUS_ENQUIRY;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NORMAL_UNSPECIFIED] = GECKO_CALL_ERROR_NORMAL_CALL_CLEARING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CONGESTION] = GECKO_CALL_ERROR_CONGESTION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NETWORK_OUT_OF_ORDER] = GECKO_CALL_ERROR_NETWORK_OUT_OF_ORDER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NETWORK_TEMP_FAILURE] = GECKO_CALL_ERROR_NETWORK_TEMP_FAILURE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_SWITCHING_EQUIP_CONGESTION] = GECKO_CALL_ERROR_SWITCHING_EQUIP_CONGESTION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_ACCESS_INFO_DISCARDED] = GECKO_CALL_ERROR_ACCESS_INFO_DISCARDED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_REQUESTED_CHANNEL_NOT_AVAILABLE] = GECKO_CALL_ERROR_REQUESTED_CHANNEL_NOT_AVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_RESOURCE_UNAVAILABLE] = GECKO_CALL_ERROR_RESOURCE_UNAVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_QOS_UNAVAILABLE] = GECKO_CALL_ERROR_QOS_UNAVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_REQUESTED_FACILITY_NOT_SUBSCRIBED] = GECKO_CALL_ERROR_REQUESTED_FACILITY_NOT_SUBSCRIBED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INCOMING_CALLS_BARRED_WITHIN_CUG] = GECKO_CALL_ERROR_INCOMING_CALLS_BARRED_WITHIN_CUG;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BEARER_CAPABILITY_NOT_AUTHORIZED] = GECKO_CALL_ERROR_BEARER_CAPABILITY_NOT_AUTHORIZED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BEARER_CAPABILITY_NOT_AVAILABLE] = GECKO_CALL_ERROR_BEARER_CAPABILITY_NOT_AVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_SERVICE_NOT_AVAILABLE] = GECKO_CALL_ERROR_SERVICE_NOT_AVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BEARER_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_BEARER_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_ACM_LIMIT_EXCEEDED] = GECKO_CALL_ERROR_INCOMING_CALL_EXCEEDED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_REQUESTED_FACILITY_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_REQUESTED_FACILITY_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNRESTRICTED_BEARER_NOT_AVAILABLE] = GECKO_CALL_ERROR_UNRESTRICTED_BEARER_NOT_AVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_SERVICE_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_SERVICE_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INVALID_TRANSACTION_ID] = GECKO_CALL_ERROR_INVALID_TRANSACTION_ID;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_USER_NOT_CUG_MEMBER] = GECKO_CALL_ERROR_USER_NOT_CUG_MEMBER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INCOMPATIBLE_DESTINATION] = GECKO_CALL_ERROR_INCOMPATIBLE_DESTINATION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INVALID_TRANSIT_NETWORK_SELECTION] = GECKO_CALL_ERROR_INVALID_TRANSIT_NETWORK_SELECTION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_SEMANTICALLY_INCORRECT_MESSAGE] = GECKO_CALL_ERROR_SEMANTICALLY_INCORRECT_MESSAGE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INVALID_MANDATORY_INFO] = GECKO_CALL_ERROR_INVALID_MANDATORY_INFO;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_MESSAGE_TYPE_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_MESSAGE_TYPE_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_MESSAGE_TYPE_INCOMPATIBLE_PROTOCOL_STATE] = GECKO_CALL_ERROR_MESSAGE_TYPE_INCOMPATIBLE_PROTOCOL_STATE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INFO_ELEMENT_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_INFO_ELEMENT_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CONDITIONAL_IE_ERROR] = GECKO_CALL_ERROR_CONDITIONAL_IE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_MESSAGE_INCOMPABITLE_PROTOCOL_STATE] = GECKO_CALL_ERROR_MESSAGE_INCOMPATIBLE_PROTOCOL_STATE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_RECOVERY_ON_TIMER_EXPIRY] = GECKO_CALL_ERROR_RECOVERY_ON_TIMER_EXPIRY;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_PROTOCOL_ERROR] = GECKO_CALL_ERROR_PROTOCOL;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INTERWORKING] = GECKO_CALL_ERROR_INTERWORKING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_BARRED] = GECKO_CALL_ERROR_BARRED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_FDN_BLOCKED] = GECKO_CALL_ERROR_FDN_BLOCKED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_IMSI_UNKNOWN_IN_VLR] = GECKO_CALL_ERROR_SUBSCRIBER_UNKNOWN;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_IMEI_NOT_ACCEPTED] = GECKO_CALL_ERROR_DEVICE_NOT_ACCEPTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_DIAL_MODIFIED_TO_USSD] = GECKO_CALL_ERROR_MODIFIED_TO_DIAL_FAILED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_DIAL_MODIFIED_TO_SS] = GECKO_CALL_ERROR_MODIFIED_TO_DIAL_FAILED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_DIAL_MODIFIED_TO_DIAL] = GECKO_CALL_ERROR_MODIFIED_TO_DIAL_FAILED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE] = GECKO_CALL_ERROR_CDMA_LOCKED_UNTIL_POWER_CYCLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_DROP] = GECKO_CALL_ERROR_CDMA_DROP;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_INTERCEPT] = GECKO_CALL_ERROR_CDMA_INTERCEPT;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_REORDER] = GECKO_CALL_ERROR_CDMA_REORDER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_SO_REJECT] = GECKO_CALL_ERROR_CDMA_SO_REJECT;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_RETRY_ORDER] = GECKO_CALL_ERROR_CDMA_RETRY_ORDER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_ACCESS_FAILURE] = GECKO_CALL_ERROR_CDMA_ACCESS_FAILURE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_PREEMPTED] = GECKO_CALL_ERROR_CDMA_PREEMPTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_NOT_EMERGENCY] = GECKO_CALL_ERROR_CDMA_NOT_EMERGENCY;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_ACCESS_BLOCKED] = GECKO_CALL_ERROR_CDMA_ACCESS_BLOCKED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_ERROR_UNSPECIFIED] = GECKO_CALL_ERROR_UNSPECIFIED;
-
-this.GECKO_DATACALL_ERROR_OPERATOR_BARRED = "OperatorBarredError";
-this.GECKO_DATACALL_ERROR_INSUFFICIENT_RESOURCES = "InsufficientResourcesError";
-this.GECKO_DATACALL_ERROR_MISSING_UKNOWN_APN = "MissingUnknownAPNError";
-this.GECKO_DATACALL_ERROR_UNKNOWN_PDP_ADDRESS_TYPE = "UnknownPDPAddressTypeError";
-this.GECKO_DATACALL_ERROR_USER_AUTHENTICATION = "UserAuthenticationError";
-this.GECKO_DATACALL_ERROR_ACTIVATION_REJECT_GGSN = "ActivationRejectGGSNError";
-this.GECKO_DATACALL_ERROR_ACTIVATION_REJECT_UNSPECIFIED = "ActivationRejectUnspecifiedError";
-this.GECKO_DATACALL_ERROR_SERVICE_OPTION_NOT_SUPPORTED = "ServiceOptionNotSupportedError";
-this.GECKO_DATACALL_ERROR_SERVICE_OPTION_NOT_SUBSCRIBED = "ServiceOptionNotSubscribedError";
-this.GECKO_DATACALL_ERROR_SERVICE_OPTION_OUT_OF_ORDER = "ServiceOptionOutOfOrderError";
-this.GECKO_DATACALL_ERROR_NSAPI_IN_USE = "NSAPIInUseError";
-this.GECKO_DATACALL_ERROR_ONLY_IPV4_ALLOWED = "OnlyIPv4Error";
-this.GECKO_DATACALL_ERROR_ONLY_IPV6_ALLOWED = "OnlyIPv6Error";
-this.GECKO_DATACALL_ERROR_ONLY_SINGLE_BEARER_ALLOWED = "OnlySingleBearerAllowedError";
-this.GECKO_DATACALL_ERROR_PROTOCOL_ERRORS = "ProtocolErrorsError";
-this.GECKO_DATACALL_ERROR_VOICE_REGISTRATION_FAIL = "VoiceRegistrationFailError";
-this.GECKO_DATACALL_ERROR_DATA_REGISTRATION_FAIL = "DataRegistrationFailError";
-this.GECKO_DATACALL_ERROR_SIGNAL_LOST = "SignalLostError";
-this.GECKO_DATACALL_ERROR_PREF_RADIO_TECH_CHANGED = "PrefRadioTechChangedError";
-this.GECKO_DATACALL_ERROR_RADIO_POWER_OFF = "RadioPowerOffError";
-this.GECKO_DATACALL_ERROR_TETHERED_CALL_ACTIVE = "TetheredCallActiveError";
-this.GECKO_DATACALL_ERROR_UNSPECIFIED = "UnspecifiedError";
-
-this.RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR = {};
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_OPERATOR_BARRED] = GECKO_DATACALL_ERROR_OPERATOR_BARRED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_INSUFFICIENT_RESOURCES] = GECKO_DATACALL_ERROR_INSUFFICIENT_RESOURCES;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_MISSING_UKNOWN_APN] = GECKO_DATACALL_ERROR_MISSING_UKNOWN_APN;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE] = GECKO_DATACALL_ERROR_UNKNOWN_PDP_ADDRESS_TYPE;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_USER_AUTHENTICATION] = GECKO_DATACALL_ERROR_USER_AUTHENTICATION;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ACTIVATION_REJECT_GGSN] = GECKO_DATACALL_ERROR_ACTIVATION_REJECT_GGSN;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ACTIVATION_REJECT_UNSPECIFIED] = GECKO_DATACALL_ERROR_ACTIVATION_REJECT_UNSPECIFIED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED] = GECKO_DATACALL_ERROR_SERVICE_OPTION_NOT_SUPPORTED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED] = GECKO_DATACALL_ERROR_SERVICE_OPTION_NOT_SUBSCRIBED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_SERVICE_OPTION_OUT_OF_ORDER] = GECKO_DATACALL_ERROR_SERVICE_OPTION_OUT_OF_ORDER;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_NSAPI_IN_USE] = GECKO_DATACALL_ERROR_NSAPI_IN_USE;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ONLY_IPV4_ALLOWED] = GECKO_DATACALL_ERROR_ONLY_IPV4_ALLOWED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ONLY_IPV6_ALLOWED] = GECKO_DATACALL_ERROR_ONLY_IPV6_ALLOWED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ONLY_SINGLE_BEARER_ALLOWED] = GECKO_DATACALL_ERROR_ONLY_SINGLE_BEARER_ALLOWED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_PROTOCOL_ERRORS] = GECKO_DATACALL_ERROR_PROTOCOL_ERRORS;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_VOICE_REGISTRATION_FAIL] = GECKO_DATACALL_ERROR_VOICE_REGISTRATION_FAIL;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_DATA_REGISTRATION_FAIL] = GECKO_DATACALL_ERROR_DATA_REGISTRATION_FAIL;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_SIGNAL_LOST] = GECKO_DATACALL_ERROR_SIGNAL_LOST;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_PREF_RADIO_TECH_CHANGED] = GECKO_DATACALL_ERROR_PREF_RADIO_TECH_CHANGED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_RADIO_POWER_OFF] = GECKO_DATACALL_ERROR_RADIO_POWER_OFF;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_TETHERED_CALL_ACTIVE] = GECKO_DATACALL_ERROR_TETHERED_CALL_ACTIVE;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ERROR_UNSPECIFIED] = GECKO_DATACALL_ERROR_UNSPECIFIED;
-
-this.GECKO_RADIO_TECH = [
- null,
- "gprs",
- "edge",
- "umts",
- "is95a",
- "is95b",
- "1xrtt",
- "evdo0",
- "evdoa",
- "hsdpa",
- "hsupa",
- "hspa",
- "evdob",
- "ehrpd",
- "lte",
- "hspa+",
- "gsm",
- null,
- "hspa+", // DC-HSPA+
- "hspa+"
-];
-
-this.GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN = -1;
-
-// Call forwarding action. Must be in sync with nsIMobileConnectionService interface
-this.CALL_FORWARD_ACTION_DISABLE = 0;
-this.CALL_FORWARD_ACTION_ENABLE = 1;
-this.CALL_FORWARD_ACTION_QUERY_STATUS = 2;
-this.CALL_FORWARD_ACTION_REGISTRATION = 3;
-this.CALL_FORWARD_ACTION_ERASURE = 4;
-
-// Call forwarding reason. Must be in sync with nsIMobileConnectionService interface
-this.CALL_FORWARD_REASON_UNCONDITIONAL = 0;
-this.CALL_FORWARD_REASON_MOBILE_BUSY = 1;
-this.CALL_FORWARD_REASON_NO_REPLY = 2;
-this.CALL_FORWARD_REASON_NOT_REACHABLE = 3;
-this.CALL_FORWARD_REASON_ALL_CALL_FORWARDING = 4;
-this.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING = 5;
-
-// Call barring program. Must be in sync with nsIMobileConnectionService interface
-this.CALL_BARRING_PROGRAM_ALL_OUTGOING = 0;
-this.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL = 1;
-this.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME = 2;
-this.CALL_BARRING_PROGRAM_ALL_INCOMING = 3;
-this.CALL_BARRING_PROGRAM_INCOMING_ROAMING = 4;
-this.CALL_BARRING_PROGRAM_ALL_SERVICE = 5;
-this.CALL_BARRING_PROGRAM_OUTGOING_SERVICE = 6;
-this.CALL_BARRING_PROGRAM_INCOMING_SERVICE = 7;
-
-this.CALL_BARRING_PROGRAM_TO_FACILITY = {};
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_OUTGOING] = ICC_CB_FACILITY_BAOC;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL] = ICC_CB_FACILITY_BAOIC;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME] = ICC_CB_FACILITY_BAOICxH;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_INCOMING] = ICC_CB_FACILITY_BAIC;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_INCOMING_ROAMING] = ICC_CB_FACILITY_BAICr;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_SERVICE] = ICC_CB_FACILITY_BA_ALL;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_SERVICE] = ICC_CB_FACILITY_BA_MO;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_INCOMING_SERVICE] = ICC_CB_FACILITY_BA_MT;
-
-/**
- * CDMA PDU constants
- */
-
-// SMS Message Type, as defined in 3GPP2 C.S0015-A v2.0, Table 3.4-1
-this.PDU_CDMA_MSG_TYPE_P2P = 0x00; // Point-to-Point
-this.PDU_CDMA_MSG_TYPE_BROADCAST = 0x01; // Broadcast
-this.PDU_CDMA_MSG_TYPE_ACK = 0x02; // Acknowledge
-
-// SMS Teleservice Identitifier, as defined in 3GPP2 N.S0005, Table 175
-this.PDU_CDMA_MSG_TELESERIVCIE_ID_SMS = 0x1002; // SMS
-this.PDU_CDMA_MSG_TELESERIVCIE_ID_WAP = 0x1004; // WAP
-this.PDU_CDMA_MSG_TELESERIVCIE_ID_WEMT = 0x1005; // Wireless Enhanced Messaging Teleservice
- // required for fragmented SMS
-
-// SMS Service Category, as defined in 3GPP2 C.R1001-D, Table 9.3.1-1
-this.PDU_CDMA_MSG_CATEGORY_UNSPEC = 0x00; // Unknown/Unspecified
-
-// Address Information, Digit Mode, as defined in 3GPP2 C.S0015-A v2.0, sec 3.4.3.3
-this.PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF = 0x00; // Digit Mode : DTMF
-this.PDU_CDMA_MSG_ADDR_DIGIT_MODE_ASCII = 0x01; // Digit Mode : 8-bit ASCII with MSB = 0
-
-// Address Information, Number Mode, as defined in 3GPP2 C.S0015-A v2.0, sec 3.4.3.3
-this.PDU_CDMA_MSG_ADDR_NUMBER_MODE_ANSI = 0x00; // Number Mode : ANSI T1.607-2000(R2004)
-this.PDU_CDMA_MSG_ADDR_NUMBER_MODE_ASCII = 0x01; // Number Mode : Data network address format
-
-// Address Information, Number Type, as defined in 3GPP2 C.S0015-A v2.0, Table 3.4.3.3-1
-this.PDU_CDMA_MSG_ADDR_NUMBER_TYPE_UNKNOWN = 0x00; // Number Type : Unknown
-this.PDU_CDMA_MSG_ADDR_NUMBER_TYPE_INTERNATIONAL = 0x01; // Number Type : Internaltional number(+XXXXX)
-this.PDU_CDMA_MSG_ADDR_NUMBER_TYPE_NATIONAL = 0x02; // Number Type : National number
-
-// Address Information, Number Plan, as defined in 3GPP2 C.S0005-D v2.0, Table 2.7.1.3.2.4-3
-this.PDU_CDMA_MSG_ADDR_NUMBER_PLAN_UNKNOWN = 0x00; // Number Plan : Unknown
-this.PDU_CDMA_MSG_ADDR_NUMBER_PLAN_ISDN = 0x01; // Number Plan : ISDN/Telephony numbering plan
-
-// SMS Encoding, as defined in 3GPP2 C.R1001-D, Table 9.1-1
-this.PDU_CDMA_MSG_CODING_OCTET = 0x00; // octet(8-bit), Not tested
-this.PDU_CDMA_MSG_CODING_IS_91 = 0x01; // IS-91 Extended Protocol Message(variable), Not tested
-this.PDU_CDMA_MSG_CODING_7BITS_ASCII = 0x02; // 7-bit ASCII(7-bit)
-this.PDU_CDMA_MSG_CODING_IA5 = 0x03; // IA5(7-bit), Not tested
-this.PDU_CDMA_MSG_CODING_UNICODE = 0x04; // Unicode(16-bit)
-this.PDU_CDMA_MSG_CODING_SHIFT_JIS = 0x05; // Shift-6 JIS(8/16-bit variable), Not supported
-this.PDU_CDMA_MSG_CODING_KOREAN = 0x06; // Korean(8/16-bit variable), Not supported
-this.PDU_CDMA_MSG_CODING_LATIN_HEBREW = 0x07; // Latin/ Hebrew(8-bit), ISO/IEC 8859-8, Not supported
-this.PDU_CDMA_MSG_CODING_LATIN = 0x08; // Latin(8-bit), ISO/IEC 8859-1, Not tested
-this.PDU_CDMA_MSG_CODING_7BITS_GSM = 0x09; // GSM 7-bit default alphabet(7-bit), Not tested
-this.PDU_CDMA_MSG_CODING_GSM_DCS = 0x0A; // GSM Data-Coding-Scheme, Not supported
-
-// SMS Message Type, as defined in 3GPP2 C.S0015-A v2.0, Table 4.5.1-1
-this.PDU_CDMA_MSG_TYPE_DELIVER = 0x01; // Deliver
-this.PDU_CDMA_MSG_TYPE_SUBMIT = 0x02; // Submit
-this.PDU_CDMA_MSG_TYPE_DELIVER_ACK = 0x04; // Delivery Acknowledgment
-
-// SMS User Data Subparameters, as defined in 3GPP2 C.S0015-A v2.0, Table 4.5-1
-this.PDU_CDMA_MSG_USERDATA_MSG_ID = 0x00; // Message Identifier
-this.PDU_CDMA_MSG_USERDATA_BODY = 0x01; // User Data Body
-this.PDU_CDMA_MSG_USERDATA_TIMESTAMP = 0x03; // Message Center Time Stamp
-this.PDU_CDMA_MSG_USERDATA_REPLY_OPTION = 0x0A; // Reply Option
-this.PDU_CDMA_LANGUAGE_INDICATOR = 0x0D; // Language Indicator
-this.PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER = 0x0E; // Callback Number
-this.PDU_CDMA_MSG_USER_DATA_MSG_STATUS = 0x14; // Message Status
-
-// CDMA Language Indicator: Language groups
-// see 3GPP2 C.R1001-F table 9.2-1
-this.CB_CDMA_LANG_GROUP = [
- null, "en", "fr", "es", "ja", "ko", "zh", "he"
-];
-
-// IS-91 Message Type, as defined in TIA/EIA/IS-91-A, Table 9
-this.PDU_CDMA_MSG_CODING_IS_91_TYPE_VOICEMAIL_STATUS = 0x82;
-this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS_FULL = 0x83;
-this.PDU_CDMA_MSG_CODING_IS_91_TYPE_CLI = 0x84;
-this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS = 0x85;
-
-// Information Record Type, reference from ril.h
-this.PDU_CDMA_INFO_REC_TYPE_DISPLAY = 0;
-this.PDU_CDMA_INFO_REC_TYPE_CALLED_PARTY_NUMBER = 1;
-this.PDU_CDMA_INFO_REC_TYPE_CALLING_PARTY_NUMBER = 2;
-this.PDU_CDMA_INFO_REC_TYPE_CONNECTED_NUMBER =3;
-this.PDU_CDMA_INFO_REC_TYPE_SIGNAL = 4;
-this.PDU_CDMA_INFO_REC_TYPE_REDIRECTING_NUMBER = 5;
-this.PDU_CDMA_INFO_REC_TYPE_LINE_CONTROL = 6;
-this.PDU_CDMA_INFO_REC_TYPE_EXTENDED_DISPLAY = 7;
-this.PDU_CDMA_INFO_REC_TYPE_T53_CLIR = 8;
-this.PDU_CDMA_INFO_REC_TYPE_T53_RELEASE = 9;
-this.PDU_CDMA_INFO_REC_TYPE_T53_AUDIO_CONTROL = 10;
-
-// Display type of extended display of information record,
-// as defined in C.S0005-F v1.0, Table 3.7.5.16-2
-this.INFO_REC_EXTENDED_DISPLAY_BLANK = 0x80;
-this.INFO_REC_EXTENDED_DISPLAY_SKIP = 0x81;
-this.INFO_REC_EXTENDED_DISPLAY_CONTINATION = 0x82;
-this.INFO_REC_EXTENDED_DISPLAY_CALLED_ADDRESS = 0x83;
-this.INFO_REC_EXTENDED_DISPLAY_CAUSE = 0x84;
-this.INFO_REC_EXTENDED_DISPLAY_PROGRESS_INDICATOR = 0x85;
-this.INFO_REC_EXTENDED_DISPLAY_NOTIFICATION_INDICATOR = 0x86;
-this.INFO_REC_EXTENDED_DISPLAY_PROMPT = 0x87;
-this.INFO_REC_EXTENDED_DISPLAY_ACCUMULATED_DIGITS = 0x88;
-this.INFO_REC_EXTENDED_DISPLAY_STATUS = 0x89;
-this.INFO_REC_EXTENDED_DISPLAY_INBAND = 0x8A;
-this.INFO_REC_EXTENDED_DISPLAY_CALLING_ADDRESS = 0x8B;
-this.INFO_REC_EXTENDED_DISPLAY_REASON = 0x8C;
-this.INFO_REC_EXTENDED_DISPLAY_CALLING_PARTY_NAME = 0x8D;
-this.INFO_REC_EXTENDED_DISPLAY_CALLED_PARTY_NAME = 0x8E;
-this.INFO_REC_EXTENDED_DISPLAY_ORIGINAL_CALLED_NAME = 0x8F;
-this.INFO_REC_EXTENDED_DISPLAY_REDIRECT_NAME = 0x90;
-this.INFO_REC_EXTENDED_DISPLAY_CONNECTED_NAME = 0x91;
-this.INFO_REC_EXTENDED_DISPLAY_ORIGINATING_RESTRICTIONS = 0x92;
-this.INFO_REC_EXTENDED_DISPLAY_DATE_TIME_OF_DAY = 0x93;
-this.INFO_REC_EXTENDED_DISPLAY_CALL_APPEARANCE_ID = 0x94;
-this.INFO_REC_EXTENDED_DISPLAY_FEATURE_ADDRESS = 0x95;
-this.INFO_REC_EXTENDED_DISPLAY_REDIRECTION_NAME = 0x96;
-this.INFO_REC_EXTENDED_DISPLAY_REDIRECTION_NUMBER = 0x97;
-this.INFO_REC_EXTENDED_DISPLAY_REDIRECTING_NUMBER = 0x98;
-this.INFO_REC_EXTENDED_DISPLAY_ORIGINAL_CALLED_NUMBER = 0x99;
-this.INFO_REC_EXTENDED_DISPLAY_CONNECTED_NUMBER = 0x9A;
-this.INFO_REC_EXTENDED_DISPLAY_TEXT = 0x9B;
-
-/**
- * The table for MCC/MNC which the length of MNC is 3.
- *
- * This table is built from below links.
- * - http://www.itu.int/pub/T-SP-E.212B-2013
- * - http://en.wikipedia.org/wiki/Mobile_Network_Code
- */
-this.PLMN_HAVING_3DIGITS_MNC = {
- // Puerto Rico.
- "330":
- ["110", // América Móvil
- "120" // PR Wireless
- ],
- // Trinidad and Tobago.
- "374":
- ["130", // Digicel Trinidad and Tobago Ltd.
- "140" // LaqTel Ltd.
- ],
- // India.
- "405":
- ["000", // Shyam Telelink Ltd.
- "005", // Reliance, Delhi
- "006", // Reliance, Gujarat
- "007", // Reliance, Haryana
- "009", // Reliance, J&K
- "010", // Reliance, Karnataka
- "011", // Reliance, Kerala
- "012", // Reliance, Andhra Pradesh
- "013", // Reliance, Maharashtr
- "014", // Reliance, Madhya Pradesh
- "018", // Reliance, Punjab
- "020", // Reliance, Tamilnadu
- "021", // Reliance, UP (East)
- "022", // Reliance, UP (West)
- "025", // TATA DOCOMO, Andhra Pradesh
- "026", // TATA DOCOMO, Assam
- "027", // TATA DOCOMO, Bihar
- "028", // TATA DOCOMO, Chennai
- "029", // TATA DOCOMO, Delhi
- "030", // TATA DOCOMO, Gujarat
- "031", // TATA DOCOMO, Haryana
- "032", // TATA DOCOMO, Himachal Pradesh
- "033", // Reliance, Bihar
- "034", // TATA DOCOMO, Kamataka
- "035", // TATA DOCOMO, Kerala
- "036", // TATA DOCOMO, Kolkata
- "037", // TATA DOCOMO, Maharashtra
- "038", // TATA DOCOMO, Madhya Pradesh
- "039", // TATA DOCOMO, Mumbai
- "040", // Reliance, Chennai
- "041", // TATA DOCOMO, Orissa
- "042", // TATA DOCOMO, Punjab
- "043", // TATA DOCOMO, Rajasthan
- "044", // TATA DOCOMO, Tamilnadu
- "045", // TATA DOCOMO, UP (East)
- "046", // TATA DOCOMO, UP (West)
- "047", // TATA DOCOMO, West Bengal
- "750", // Vodafone IN, J&K
- "751", // Vodafone IN, Assam
- "752", // Vodafone IN, Bihar
- "753", // Vodafone IN, Orissa
- "754", // Vodafone IN, Himachal Pradesh
- "755", // Vodafone IN, North East
- "756", // Vodafone IN, Madhya Pradesh & Chhattisgarh
- "799", // Idea, MUMBAI
- "800", // Aircell, Delhi
- "801", // Aircell, Andhra Pradesh
- "802", // Aircell, Gujarat
- "803", // Aircell, Kamataka
- "804", // Aircell, Maharashtra
- "805", // Aircell, Mumbai
- "806", // Aircell, Rajasthan
- "807", // Aircell, Haryana
- "808", // Aircell, Madhya Pradesh
- "809", // Aircell, Kerala
- "810", // Aircell, Uttar Pradesh (East)
- "811", // Aircell, Uttar Pradesh (West)
- "812", // Aircell, Punjab
- "818", // Uninor, Uttar Pradesh (West)
- "819", // Uninor, Andhra Pradesh
- "820", // Uninor, Karnataka
- "821", // Uninor, Kerala
- "822", // Uninor, Kolkata
- "824", // Videocon, Assam
- "827", // Videocon, Gujarat
- "834", // Videocon, Madhya Pradesh
- "840", // Jio, West Bengal
- "844", // Uninor, Delhi & NCR
- "845", // IDEA, Assam
- "846", // IDEA, Jammu & Kashmir
- "847", // IDEA, Karnataka
- "848", // IDEA, Kolkata
- "849", // IDEA, North East
- "850", // IDEA, Orissa
- "851", // IDEA, Punjab
- "852", // IDEA, Tamil Nadu
- "853", // IDEA, West Bengal
- "854", // Jio, Andra Pradesh
- "855", // Jio, Assam
- "856", // Jio, Bihar
- "857", // Jio, Gujarat
- "858", // Jio, Haryana
- "859", // Jio, Himachal Pradesh
- "860", // Jio, Jammu Kashmir
- "861", // Jio, Karnataka
- "862", // Jio, Kerala
- "863", // Jio, Madhyya Pradesh
- "864", // Jio, Maharashtra
- "865", // Jio, North East
- "866", // Jio, Orissa
- "867", // Jio, Punjab
- "868", // Jio, Rajasthan
- "869", // Jio, Tamil Nadu Chennai
- "870", // Jio, Uttar Pradesh West
- "871", // Jio, Uttar Pradesh East
- "872", // Jio, Delhi
- "873", // Jio, Kolkatta
- "874", // Jio, Mumbai
- "875", // Uninor, Assam
- "880", // Uninor, West Bengal
- "881", // S Tel, Assam
- "908", // IDEA, Andhra Pradesh
- "909", // IDEA, Delhi
- "910", // IDEA, Haryana
- "911", // Etisalat, Maharashtra
- "912", // Etisalat, Andhra Pradesh
- "913", // Etisalat, Delhi & NCR
- "914", // Etisalat, Gujarat
- "917", // Etisalat, Kerala
- "927", // Uninor, Gujarat
- "929" // Uninor, Maharashtra
- ],
- // Malaysia.
- "502":
- ["150", // Tune Talk Sdn Bhd
- "151", // Baraka Telecom Sdn Bhd (MVNE)
- "152", // YTL Communications Sdn Bhd
- "156" // Altel Communications Sdn Bhd
- ],
- // Brazil.
- "724":
- ["055" // Sercomtel
- ]
-};
-
-/**
- * The table for MCC which the length of MNC is 3
- *
- * This table is built from below links.
- * - http://www.itu.int/pub/T-SP-E.212B-2013
- * - http://en.wikipedia.org/wiki/Mobile_Network_Code
- */
-this.MCC_TABLE_FOR_MNC_LENGTH_IS_3 = [
- "302", // Canada
- "310", // United States of America
- "311", // United States of America
- "312", // United States of America
- "313", // United States of America
- "316", // United States of America
- "330", // Puerto Rico
- "334", // Mexico
- "338", // Jamaica
- "342", // Barbados
- "344", // Antigua and Barbuda
- "346", // Cayman Islands
- "348", // British Virgin Islands
- "350", // Bermuda
- "352", // Grenada
- "354", // Montserrat
- "356", // Saint Kitts and Nevis
- "358", // Saint Lucia
- "360", // Saint Vincent and the Grenadines
- "365", // Anguilla
- "366", // Dominica
- "376", // Turks and Caicos Islands
- "708", // Honduras
- "722", // Argentina
- "732", // Colombia
- "750" // Falkland Islands (Malvinas)
-];
-
-// Supplementary service notifications, code2, as defined in 3GPP 27.007 7.17
-this.SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD = 2;
-this.SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED = 3;
-
-this.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD = "RemoteHeld";
-this.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED = "RemoteResumed";
-
-this.GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2 = {};
-GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2[SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD] = GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD;
-GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2[SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED] = GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED;
-
-/**
- * The status for an Over-the-Air Service Provisioning / Over-the-Air
- * Parameter Administration (OTASP/OTAPA) session.
- *
- * @see 3GPP2 C.S0016
- */
-this.GECKO_OTA_STATUS_SPL_UNLOCKED = "spl_unlocked";
-this.GECKO_OTA_STATUS_SPC_RETRIES_EXCEEDED = "spc_retries_exceeded";
-this.GECKO_OTA_STATUS_A_KEY_EXCHANGED = "a_key_exchanged";
-this.GECKO_OTA_STATUS_SSD_UPDATED = "ssd_updated";
-this.GECKO_OTA_STATUS_NAM_DOWNLOADED = "nam_downloaded";
-this.GECKO_OTA_STATUS_MDN_DOWNLOADED = "mdn_downloaded";
-this.GECKO_OTA_STATUS_IMSI_DOWNLOADED = "imsi_downloaded";
-this.GECKO_OTA_STATUS_PRL_DOWNLOADED = "prl_downloaded";
-this.GECKO_OTA_STATUS_COMMITTED = "committed";
-this.GECKO_OTA_STATUS_OTAPA_STARTED = "otapa_started";
-this.GECKO_OTA_STATUS_OTAPA_STOPPED = "otapa_stopped";
-this.GECKO_OTA_STATUS_OTAPA_ABORTED = "otapa_aborted";
-this.CDMA_OTA_PROVISION_STATUS_TO_GECKO = [
- GECKO_OTA_STATUS_SPL_UNLOCKED,
- GECKO_OTA_STATUS_SPC_RETRIES_EXCEEDED,
- GECKO_OTA_STATUS_A_KEY_EXCHANGED,
- GECKO_OTA_STATUS_SSD_UPDATED,
- GECKO_OTA_STATUS_NAM_DOWNLOADED,
- GECKO_OTA_STATUS_MDN_DOWNLOADED,
- GECKO_OTA_STATUS_IMSI_DOWNLOADED,
- GECKO_OTA_STATUS_PRL_DOWNLOADED,
- GECKO_OTA_STATUS_COMMITTED,
- GECKO_OTA_STATUS_OTAPA_STARTED,
- GECKO_OTA_STATUS_OTAPA_STOPPED,
- GECKO_OTA_STATUS_OTAPA_ABORTED
-];
-
-// Allow this file to be imported via Components.utils.import().
-this.EXPORTED_SYMBOLS = Object.keys(this);
diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js
deleted file mode 100644
index 0608a5be3..000000000
--- a/dom/system/gonk/ril_worker.js
+++ /dev/null
@@ -1,15206 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * This file implements the RIL worker thread. It communicates with
- * the main thread to provide a high-level API to the phone's RIL
- * stack, and with the RIL IPC thread to communicate with the RIL
- * device itself. These communication channels use message events as
- * known from Web Workers:
- *
- * - postMessage()/"message" events for main thread communication
- *
- * - postRILMessage()/"RILMessageEvent" events for RIL IPC thread
- * communication.
- *
- * The two main objects in this file represent individual parts of this
- * communication chain:
- *
- * - RILMessageEvent -> Buf -> RIL -> postMessage() -> nsIRadioInterfaceLayer
- * - nsIRadioInterfaceLayer -> postMessage() -> RIL -> Buf -> postRILMessage()
- *
- * Note: The code below is purposely lean on abstractions to be as lean in
- * terms of object allocations. As a result, it may look more like C than
- * JavaScript, and that's intended.
- */
-
-/* global BufObject */
-/* global TelephonyRequestQueue */
-
-"use strict";
-
-importScripts("ril_consts.js");
-importScripts("resource://gre/modules/workers/require.js");
-importScripts("ril_worker_buf_object.js");
-importScripts("ril_worker_telephony_request_queue.js");
-
-// set to true in ril_consts.js to see debug messages
-var DEBUG = DEBUG_WORKER;
-var GLOBAL = this;
-
-if (!this.debug) {
- // Debugging stub that goes nowhere.
- this.debug = function debug(message) {
- dump("RIL Worker: " + message + "\n");
- };
-}
-
-// Timeout value for emergency callback mode.
-const EMERGENCY_CB_MODE_TIMEOUT_MS = 300000; // 5 mins = 300000 ms.
-
-const ICC_MAX_LINEAR_FIXED_RECORDS = 0xfe;
-
-const GET_CURRENT_CALLS_RETRY_MAX = 3;
-
-var RILQUIRKS_CALLSTATE_EXTRA_UINT32;
-var RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL;
-var RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS;
-var RILQUIRKS_SIGNAL_EXTRA_INT32;
-var RILQUIRKS_AVAILABLE_NETWORKS_EXTRA_STRING;
-// Needed for call-waiting on Peak device
-var RILQUIRKS_EXTRA_UINT32_2ND_CALL;
-// On the emulator we support querying the number of lock retries
-var RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT;
-// Ril quirk to Send STK Profile Download
-var RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD;
-// Ril quirk to attach data registration on demand.
-var RILQUIRKS_DATA_REGISTRATION_ON_DEMAND;
-// Ril quirk to control the uicc/data subscription.
-var RILQUIRKS_SUBSCRIPTION_CONTROL;
-// Ril quirk to describe the SMSC address format.
-var RILQUIRKS_SMSC_ADDRESS_FORMAT;
-
-/**
- * The RIL state machine.
- *
- * This object communicates with rild via parcels and with the main thread
- * via post messages. It maintains state about the radio, ICC, calls, etc.
- * and acts upon state changes accordingly.
- */
-function RilObject(aContext) {
- this.context = aContext;
-
- this.telephonyRequestQueue = new TelephonyRequestQueue(this);
- this.currentConferenceState = CALL_STATE_UNKNOWN;
- this._pendingSentSmsMap = {};
- this.pendingNetworkType = {};
- this._receivedSmsCbPagesMap = {};
- this._getCurrentCallsRetryCount = 0;
-}
-RilObject.prototype = {
- context: null,
-
- /**
- * RIL version.
- */
- version: null,
-
- /**
- * Call state of current conference group.
- */
- currentConferenceState: null,
-
- /**
- * Outgoing messages waiting for SMS-STATUS-REPORT.
- */
- _pendingSentSmsMap: null,
-
- /**
- * Marker object.
- */
- pendingNetworkType: null,
-
- /**
- * Global Cell Broadcast switch.
- */
- cellBroadcastDisabled: false,
-
- /**
- * Parsed Cell Broadcast search lists.
- * cellBroadcastConfigs.MMI should be preserved over rild reset.
- */
- cellBroadcastConfigs: null,
- mergedCellBroadcastConfig: null,
-
- _receivedSmsCbPagesMap: null,
-
- initRILState: function() {
- /**
- * One of the RADIO_STATE_* constants.
- */
- this.radioState = GECKO_RADIOSTATE_UNKNOWN;
-
- /**
- * True if we are on a CDMA phone.
- */
- this._isCdma = false;
-
- /**
- * True if we are in emergency callback mode.
- */
- this._isInEmergencyCbMode = false;
-
- /**
- * Set when radio is ready but radio tech is unknown. That is, we are
- * waiting for REQUEST_VOICE_RADIO_TECH
- */
- this._waitingRadioTech = false;
-
- /**
- * Card state
- */
- this.cardState = GECKO_CARDSTATE_UNINITIALIZED;
-
- /**
- * Device Identities including IMEI, IMEISV, ESN and MEID.
- */
- this.deviceIdentities = null;
-
- /**
- * ICC information that is not exposed to Gaia.
- */
- this.iccInfoPrivate = {};
-
- /**
- * ICC information, such as MSISDN, MCC, MNC, SPN...etc.
- */
- this.iccInfo = {};
-
- /**
- * CDMA specific information. ex. CDMA Network ID, CDMA System ID... etc.
- */
- this.cdmaHome = null;
-
- /**
- * Application identification for apps in ICC.
- */
- this.aid = null;
-
- /**
- * Application type for apps in ICC.
- */
- this.appType = null;
-
- this.networkSelectionMode = GECKO_NETWORK_SELECTION_UNKNOWN;
-
- this.voiceRegistrationState = {};
- this.dataRegistrationState = {};
-
- /**
- * List of strings identifying the network operator.
- */
- this.operator = null;
-
- /**
- * String containing the baseband version.
- */
- this.basebandVersion = null;
-
- // Clean up currentCalls: rild might have restarted.
- this.sendChromeMessage({
- rilMessageType: "currentCalls",
- calls: {}
- });
-
- // Don't clean up this._pendingSentSmsMap
- // because on rild restart: we may continue with the pending segments.
-
- /**
- * Whether or not the multiple requests in requestNetworkInfo() are currently
- * being processed
- */
- this._processingNetworkInfo = false;
-
- /**
- * Multiple requestNetworkInfo() in a row before finishing the first
- * request, hence we need to fire requestNetworkInfo() again after
- * gathering all necessary stuffs. This is to make sure that ril_worker
- * gets precise network information.
- */
- this._needRepollNetworkInfo = false;
-
- /**
- * Pending messages to be send in batch from requestNetworkInfo()
- */
- this._pendingNetworkInfo = {rilMessageType: "networkinfochanged"};
-
- /**
- * Cell Broadcast Search Lists.
- */
- let cbmmi = this.cellBroadcastConfigs && this.cellBroadcastConfigs.MMI;
- this.cellBroadcastConfigs = {
- MMI: cbmmi || null
- };
- this.mergedCellBroadcastConfig = null;
-
- /**
- * True when the request to report SMS Memory Status is pending.
- */
- this.pendingToReportSmsMemoryStatus = false;
- this.smsStorageAvailable = true;
- },
-
- /**
- * Parse an integer from a string, falling back to a default value
- * if the the provided value is not a string or does not contain a valid
- * number.
- *
- * @param string
- * String to be parsed.
- * @param defaultValue [optional]
- * Default value to be used.
- * @param radix [optional]
- * A number that represents the numeral system to be used. Default 10.
- */
- parseInt: function(string, defaultValue, radix) {
- let number = parseInt(string, radix || 10);
- if (!isNaN(number)) {
- return number;
- }
- if (defaultValue === undefined) {
- defaultValue = null;
- }
- return defaultValue;
- },
-
-
- /**
- * Outgoing requests to the RIL. These can be triggered from the
- * main thread via messages that look like this:
- *
- * {rilMessageType: "methodName",
- * extra: "parameters",
- * go: "here"}
- *
- * So if one of the following methods takes arguments, it takes only one,
- * an object, which then contains all of the parameters as attributes.
- * The "@param" documentation is to be interpreted accordingly.
- */
-
- /**
- * Retrieve the ICC's status.
- */
- getICCStatus: function() {
- this.context.Buf.simpleRequest(REQUEST_GET_SIM_STATUS);
- },
-
- /**
- * Helper function for unlocking ICC locks.
- */
- iccUnlockCardLock: function(options) {
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN:
- this.enterICCPIN(options);
- break;
- case GECKO_CARDLOCK_PIN2:
- this.enterICCPIN2(options);
- break;
- case GECKO_CARDLOCK_PUK:
- this.enterICCPUK(options);
- break;
- case GECKO_CARDLOCK_PUK2:
- this.enterICCPUK2(options);
- break;
- case GECKO_CARDLOCK_NCK:
- case GECKO_CARDLOCK_NSCK:
- case GECKO_CARDLOCK_NCK1:
- case GECKO_CARDLOCK_NCK2:
- case GECKO_CARDLOCK_HNCK:
- case GECKO_CARDLOCK_CCK:
- case GECKO_CARDLOCK_SPCK:
- case GECKO_CARDLOCK_PCK:
- case GECKO_CARDLOCK_RCCK:
- case GECKO_CARDLOCK_RSPCK:
- case GECKO_CARDLOCK_NCK_PUK:
- case GECKO_CARDLOCK_NSCK_PUK:
- case GECKO_CARDLOCK_NCK1_PUK:
- case GECKO_CARDLOCK_NCK2_PUK:
- case GECKO_CARDLOCK_HNCK_PUK:
- case GECKO_CARDLOCK_CCK_PUK:
- case GECKO_CARDLOCK_SPCK_PUK:
- case GECKO_CARDLOCK_PCK_PUK:
- case GECKO_CARDLOCK_RCCK_PUK: // Fall through.
- case GECKO_CARDLOCK_RSPCK_PUK:
- this.enterDepersonalization(options);
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- }
- },
-
- /**
- * Enter a PIN to unlock the ICC.
- *
- * @param password
- * String containing the PIN.
- * @param [optional] aid
- * AID value.
- */
- enterICCPIN: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_SIM_PIN, options);
- Buf.writeInt32(2);
- Buf.writeString(options.password);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Enter a PIN2 to unlock the ICC.
- *
- * @param password
- * String containing the PIN2.
- * @param [optional] aid
- * AID value.
- */
- enterICCPIN2: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_SIM_PIN2, options);
- Buf.writeInt32(2);
- Buf.writeString(options.password);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Requests a network personalization be deactivated.
- *
- * @param personlization
- * One of CARD_PERSOSUBSTATE_*
- * @param password
- * String containing the password.
- */
- enterDepersonalization: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE, options);
- Buf.writeInt32(1);
- Buf.writeString(options.password);
- Buf.sendParcel();
- },
-
- /**
- * Change the current ICC PIN number.
- *
- * @param password
- * String containing the old PIN value
- * @param newPassword
- * String containing the new PIN value
- * @param [optional] aid
- * AID value.
- */
- changeICCPIN: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CHANGE_SIM_PIN, options);
- Buf.writeInt32(3);
- Buf.writeString(options.password);
- Buf.writeString(options.newPassword);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Change the current ICC PIN2 number.
- *
- * @param password
- * String containing the old PIN2 value
- * @param newPassword
- * String containing the new PIN2 value
- * @param [optional] aid
- * AID value.
- */
- changeICCPIN2: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CHANGE_SIM_PIN2, options);
- Buf.writeInt32(3);
- Buf.writeString(options.password);
- Buf.writeString(options.newPassword);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Supplies ICC PUK and a new PIN to unlock the ICC.
- *
- * @param password
- * String containing the PUK value.
- * @param newPassword
- * String containing the new PIN value.
- * @param [optional] aid
- * AID value.
- */
- enterICCPUK: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_SIM_PUK, options);
- Buf.writeInt32(3);
- Buf.writeString(options.password);
- Buf.writeString(options.newPin);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Supplies ICC PUK2 and a new PIN2 to unlock the ICC.
- *
- * @param password
- * String containing the PUK2 value.
- * @param newPassword
- * String containing the new PIN2 value.
- * @param [optional] aid
- * AID value.
- */
- enterICCPUK2: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_SIM_PUK2, options);
- Buf.writeInt32(3);
- Buf.writeString(options.password);
- Buf.writeString(options.newPin);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Helper function for changing ICC locks.
- */
- iccChangeCardLockPassword: function(options) {
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN:
- this.changeICCPIN(options);
- break;
- case GECKO_CARDLOCK_PIN2:
- this.changeICCPIN2(options);
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- }
- },
-
- /**
- * Helper function for setting the state of ICC locks.
- */
- iccSetCardLockEnabled: function(options) {
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN: // Fall through.
- case GECKO_CARDLOCK_FDN:
- options.facility = GECKO_CARDLOCK_TO_FACILITY[options.lockType];
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- options.serviceClass = ICC_SERVICE_CLASS_VOICE |
- ICC_SERVICE_CLASS_DATA |
- ICC_SERVICE_CLASS_FAX;
- this.setICCFacilityLock(options);
- },
-
- /**
- * Helper function for fetching the state of ICC locks.
- */
- iccGetCardLockEnabled: function(options) {
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN: // Fall through.
- case GECKO_CARDLOCK_FDN:
- options.facility = GECKO_CARDLOCK_TO_FACILITY[options.lockType];
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- options.password = ""; // For query no need to provide pin.
- options.serviceClass = ICC_SERVICE_CLASS_VOICE |
- ICC_SERVICE_CLASS_DATA |
- ICC_SERVICE_CLASS_FAX;
- this.queryICCFacilityLock(options);
- },
-
- /**
- * Helper function for fetching the number of unlock retries of ICC locks.
- *
- * We only query the retry count when we're on the emulator. The phones do
- * not support the request id and their rild doesn't return an error.
- */
- iccGetCardLockRetryCount: function(options) {
- if (!RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT) {
- // Only the emulator supports this request.
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN:
- case GECKO_CARDLOCK_PIN2:
- case GECKO_CARDLOCK_PUK:
- case GECKO_CARDLOCK_PUK2:
- case GECKO_CARDLOCK_NCK:
- case GECKO_CARDLOCK_NSCK:
- case GECKO_CARDLOCK_CCK: // Fall through.
- case GECKO_CARDLOCK_SPCK:
- // TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM
- // @ ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_SPCK.
- options.selCode = GECKO_CARDLOCK_TO_SEL_CODE[options.lockType];
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- this.queryICCLockRetryCount(options);
- },
-
- /**
- * Query ICC lock retry count.
- *
- * @param selCode
- * One of ICC_SEL_CODE_*.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_*.
- */
- queryICCLockRetryCount: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_GET_UNLOCK_RETRY_COUNT, options);
- Buf.writeInt32(1);
- Buf.writeString(options.selCode);
- Buf.sendParcel();
- },
-
- /**
- * Query ICC facility lock.
- *
- * @param facility
- * One of ICC_CB_FACILITY_*.
- * @param password
- * Password for the facility, or "" if not required.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_*.
- * @param [optional] aid
- * AID value.
- */
- queryICCFacilityLock: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_QUERY_FACILITY_LOCK, options);
- Buf.writeInt32(4);
- Buf.writeString(options.facility);
- Buf.writeString(options.password);
- Buf.writeString(options.serviceClass.toString());
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Set ICC facility lock.
- *
- * @param facility
- * One of ICC_CB_FACILITY_*.
- * @param enabled
- * true to enable, false to disable.
- * @param password
- * Password for the facility, or "" if not required.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_*.
- * @param [optional] aid
- * AID value.
- */
- setICCFacilityLock: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_FACILITY_LOCK, options);
- Buf.writeInt32(5);
- Buf.writeString(options.facility);
- Buf.writeString(options.enabled ? "1" : "0");
- Buf.writeString(options.password);
- Buf.writeString(options.serviceClass.toString());
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Request an ICC I/O operation.
- *
- * See TS 27.007 "restricted SIM" operation, "AT Command +CRSM".
- * The sequence is in the same order as how libril reads this parcel,
- * see the struct RIL_SIM_IO_v5 or RIL_SIM_IO_v6 defined in ril.h
- *
- * @param command
- * The I/O command, one of the ICC_COMMAND_* constants.
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- * @param pathId
- * String type, check the 'pathid' parameter from TS 27.007 +CRSM.
- * @param p1, p2, p3
- * Arbitrary integer parameters for the command.
- * @param [optional] dataWriter
- * The function for writing string parameter for the ICC_COMMAND_UPDATE_RECORD.
- * @param [optional] pin2
- * String containing the PIN2.
- * @param [optional] aid
- * AID value.
- */
- iccIO: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SIM_IO, options);
- Buf.writeInt32(options.command);
- Buf.writeInt32(options.fileId);
- Buf.writeString(options.pathId);
- Buf.writeInt32(options.p1);
- Buf.writeInt32(options.p2);
- Buf.writeInt32(options.p3);
-
- // Write data.
- if (options.command == ICC_COMMAND_UPDATE_RECORD &&
- options.dataWriter) {
- options.dataWriter(options.p3);
- } else {
- Buf.writeString(null);
- }
-
- // Write pin2.
- if (options.command == ICC_COMMAND_UPDATE_RECORD &&
- options.pin2) {
- Buf.writeString(options.pin2);
- } else {
- Buf.writeString(null);
- }
-
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Get IMSI.
- *
- * @param [optional] aid
- * AID value.
- */
- getIMSI: function(aid) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_GET_IMSI);
- Buf.writeInt32(1);
- Buf.writeString(aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Retrieve ICC's GID1 field.
- */
- getGID1: function(options) {
- options.gid1 = this.iccInfoPrivate.gid1;
- this.sendChromeMessage(options);
- },
-
- /**
- * Read UICC Phonebook contacts.
- *
- * @param contactType
- * One of GECKO_CARDCONTACT_TYPE_*.
- * @param requestId
- * Request id from RadioInterfaceLayer.
- */
- readICCContacts: function(options) {
- if (!this.appType) {
- options.errorMsg = CONTACT_ERR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- this.context.ICCContactHelper.readICCContacts(
- this.appType,
- options.contactType,
- function onsuccess(contacts) {
- for (let i = 0; i < contacts.length; i++) {
- let contact = contacts[i];
- let pbrIndex = contact.pbrIndex || 0;
- let recordIndex = pbrIndex * ICC_MAX_LINEAR_FIXED_RECORDS + contact.recordId;
- contact.contactId = this.iccInfo.iccid + recordIndex;
- }
- // Reuse 'options' to get 'requestId' and 'contactType'.
- options.contacts = contacts;
- this.sendChromeMessage(options);
- }.bind(this),
- function onerror(errorMsg) {
- options.errorMsg = errorMsg;
- this.sendChromeMessage(options);
- }.bind(this));
- },
-
- /**
- * Update UICC Phonebook.
- *
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param contact The contact will be updated.
- * @param pin2 PIN2 is required for updating FDN.
- * @param requestId Request id from RadioInterfaceLayer.
- */
- updateICCContact: function(options) {
- let onsuccess = function onsuccess(updatedContact) {
- let recordIndex =
- updatedContact.pbrIndex * ICC_MAX_LINEAR_FIXED_RECORDS + updatedContact.recordId;
- updatedContact.contactId = this.iccInfo.iccid + recordIndex;
- options.contact = updatedContact;
- // Reuse 'options' to get 'requestId' and 'contactType'.
- this.sendChromeMessage(options);
- }.bind(this);
-
- let onerror = function onerror(errorMsg) {
- options.errorMsg = errorMsg;
- this.sendChromeMessage(options);
- }.bind(this);
-
- if (!this.appType || !options.contact) {
- onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED );
- return;
- }
-
- let contact = options.contact;
- let iccid = this.iccInfo.iccid;
- let isValidRecordId = false;
- if (typeof contact.contactId === "string" &&
- contact.contactId.startsWith(iccid)) {
- let recordIndex = contact.contactId.substring(iccid.length);
- contact.pbrIndex = Math.floor(recordIndex / ICC_MAX_LINEAR_FIXED_RECORDS);
- contact.recordId = recordIndex % ICC_MAX_LINEAR_FIXED_RECORDS;
- isValidRecordId = contact.recordId > 0 && contact.recordId < 0xff;
- }
-
- if (DEBUG) {
- this.context.debug("Update ICC Contact " + JSON.stringify(contact));
- }
-
- let ICCContactHelper = this.context.ICCContactHelper;
- // If contact has 'recordId' property, updates corresponding record.
- // If not, inserts the contact into a free record.
- if (isValidRecordId) {
- ICCContactHelper.updateICCContact(
- this.appType, options.contactType, contact, options.pin2, onsuccess, onerror);
- } else {
- ICCContactHelper.addICCContact(
- this.appType, options.contactType, contact, options.pin2, onsuccess, onerror);
- }
- },
-
- /**
- * Check if operator name needs to be overriden by current voiceRegistrationState
- * , EFOPL and EFPNN. See 3GPP TS 31.102 clause 4.2.58 EFPNN and 4.2.59 EFOPL
- * for detail.
- *
- * @return true if operator name is overridden, false otherwise.
- */
- overrideICCNetworkName: function() {
- if (!this.operator) {
- return false;
- }
-
- // We won't get network name using PNN and OPL if voice registration isn't
- // ready.
- if (!this.voiceRegistrationState.cell ||
- this.voiceRegistrationState.cell.gsmLocationAreaCode == -1) {
- return false;
- }
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- let networkName = ICCUtilsHelper.getNetworkNameFromICC(
- this.operator.mcc,
- this.operator.mnc,
- this.voiceRegistrationState.cell.gsmLocationAreaCode);
-
- if (!networkName) {
- return false;
- }
-
- if (DEBUG) {
- this.context.debug("Operator names will be overriden: " +
- "longName = " + networkName.fullName + ", " +
- "shortName = " + networkName.shortName);
- }
-
- this.operator.longName = networkName.fullName;
- this.operator.shortName = networkName.shortName;
-
- this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator);
- return true;
- },
-
- /**
- * Request the phone's radio to be enabled or disabled.
- *
- * @param enabled
- * Boolean indicating the desired state.
- */
- setRadioEnabled: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_RADIO_POWER, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.enabled ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Query call waiting status.
- *
- */
- queryCallWaiting: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_QUERY_CALL_WAITING, options);
- Buf.writeInt32(1);
- // As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service
- // class parameter in call waiting interrogation to network.
- Buf.writeInt32(ICC_SERVICE_CLASS_NONE);
- Buf.sendParcel();
- },
-
- /**
- * Set call waiting status.
- *
- * @param enabled
- * Boolean indicating the desired waiting status.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- */
- setCallWaiting: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_CALL_WAITING, options);
- Buf.writeInt32(2);
- Buf.writeInt32(options.enabled ? 1 : 0);
- Buf.writeInt32(options.serviceClass);
- Buf.sendParcel();
- },
-
- /**
- * Queries current CLIP status.
- */
- queryCLIP: function(options) {
- this.context.Buf.simpleRequest(REQUEST_QUERY_CLIP, options);
- },
-
- /**
- * Queries current CLIR status.
- *
- */
- getCLIR: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_CLIR, options);
- },
-
- /**
- * Enables or disables the presentation of the calling line identity (CLI) to
- * the called party when originating a call.
- *
- * @param options.clirMode
- * One of the CLIR_* constants.
- */
- setCLIR: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_CLIR, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.clirMode);
- Buf.sendParcel();
- },
-
- /**
- * Set screen state.
- *
- * @param on
- * Boolean indicating whether the screen should be on or off.
- */
- setScreenState: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SCREEN_STATE);
- Buf.writeInt32(1);
- Buf.writeInt32(options.on ? 1 : 0);
- Buf.sendParcel();
- },
-
- getVoiceRegistrationState: function() {
- this.context.Buf.simpleRequest(REQUEST_VOICE_REGISTRATION_STATE);
- },
-
- getVoiceRadioTechnology: function() {
- this.context.Buf.simpleRequest(REQUEST_VOICE_RADIO_TECH);
- },
-
- getDataRegistrationState: function() {
- this.context.Buf.simpleRequest(REQUEST_DATA_REGISTRATION_STATE);
- },
-
- getOperator: function() {
- this.context.Buf.simpleRequest(REQUEST_OPERATOR);
- },
-
- /**
- * Set the preferred network type.
- *
- * @param options An object contains a valid value of
- * RIL_PREFERRED_NETWORK_TYPE_TO_GECKO as its `type` attribute.
- */
- setPreferredNetworkType: function(options) {
- let networkType = options.type;
- if (networkType < 0 || networkType >= RIL_PREFERRED_NETWORK_TYPE_TO_GECKO.length) {
- options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_PREFERRED_NETWORK_TYPE, options);
- Buf.writeInt32(1);
- Buf.writeInt32(networkType);
- Buf.sendParcel();
- },
-
- /**
- * Get the preferred network type.
- */
- getPreferredNetworkType: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_PREFERRED_NETWORK_TYPE, options);
- },
-
- /**
- * Request neighboring cell ids in GSM network.
- */
- getNeighboringCellIds: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_NEIGHBORING_CELL_IDS, options);
- },
-
- /**
- * Request all of the current cell information known to the radio.
- */
- getCellInfoList: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_CELL_INFO_LIST, options);
- },
-
- /**
- * Request various states about the network.
- */
- requestNetworkInfo: function() {
- if (this._processingNetworkInfo) {
- if (DEBUG) {
- this.context.debug("Network info requested, but we're already " +
- "requesting network info.");
- }
- this._needRepollNetworkInfo = true;
- return;
- }
-
- if (DEBUG) this.context.debug("Requesting network info");
-
- this._processingNetworkInfo = true;
- this.getVoiceRegistrationState();
- this.getDataRegistrationState(); //TODO only GSM
- this.getOperator();
- this.getNetworkSelectionMode();
- this.getSignalStrength();
- },
-
- /**
- * Get the available networks
- */
- getAvailableNetworks: function(options) {
- if (DEBUG) this.context.debug("Getting available networks");
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_QUERY_AVAILABLE_NETWORKS, options);
- Buf.sendParcel();
- },
-
- /**
- * Request the radio's network selection mode
- */
- getNetworkSelectionMode: function() {
- if (DEBUG) this.context.debug("Getting network selection mode");
- this.context.Buf.simpleRequest(REQUEST_QUERY_NETWORK_SELECTION_MODE);
- },
-
- /**
- * Tell the radio to automatically choose a voice/data network
- */
- selectNetworkAuto: function(options) {
- if (DEBUG) this.context.debug("Setting automatic network selection");
- this.context.Buf.simpleRequest(REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, options);
- },
-
- /**
- * Set the roaming preference mode
- */
- setRoamingPreference: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CDMA_SET_ROAMING_PREFERENCE, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.mode);
- Buf.sendParcel();
- },
-
- /**
- * Get the roaming preference mode
- */
- queryRoamingPreference: function(options) {
- this.context.Buf.simpleRequest(REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, options);
- },
-
- /**
- * Set the voice privacy mode
- */
- setVoicePrivacyMode: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.enabled ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Get the voice privacy mode
- */
- queryVoicePrivacyMode: function(options) {
- this.context.Buf.simpleRequest(REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, options);
- },
-
- /**
- * Open Logical UICC channel (aid) for Secure Element access
- */
- iccOpenChannel: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SIM_OPEN_CHANNEL, options);
- Buf.writeString(options.aid);
- Buf.sendParcel();
- },
-
- /**
- * Exchange APDU data on an open Logical UICC channel
- */
- iccExchangeAPDU: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SIM_TRANSMIT_APDU_CHANNEL, options);
- Buf.writeInt32(options.channel);
- Buf.writeInt32(options.apdu.cla);
- Buf.writeInt32(options.apdu.command);
- Buf.writeInt32(options.apdu.p1);
- Buf.writeInt32(options.apdu.p2);
- Buf.writeInt32(options.apdu.p3);
- Buf.writeString(options.apdu.data);
- Buf.sendParcel();
- },
-
- /**
- * Close Logical UICC channel
- */
- iccCloseChannel: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SIM_CLOSE_CHANNEL, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.channel);
- Buf.sendParcel();
- },
-
- /**
- * Get UICC service state
- */
- getIccServiceState: function(options) {
- switch (options.service) {
- case GECKO_CARDSERVICE_FDN:
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- options.result = ICCUtilsHelper.isICCServiceAvailable("FDN");
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- break;
- }
- this.sendChromeMessage(options);
- },
-
- /**
- * Enable/Disable UICC subscription
- */
- setUiccSubscription: function(options) {
- if (DEBUG) {
- this.context.debug("setUiccSubscription: " + JSON.stringify(options));
- }
-
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_UICC_SUBSCRIPTION, options);
- Buf.writeInt32(this.context.clientId);
- Buf.writeInt32(options.appIndex);
- Buf.writeInt32(this.context.clientId);
- Buf.writeInt32(options.enabled ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Tell the radio to choose a specific voice/data network
- */
- selectNetwork: function(options) {
- if (DEBUG) {
- this.context.debug("Setting manual network selection: " +
- options.mcc + ", " + options.mnc);
- }
-
- let numeric = (options.mcc && options.mnc) ? options.mcc + options.mnc : null;
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_NETWORK_SELECTION_MANUAL, options);
- Buf.writeString(numeric);
- Buf.sendParcel();
- },
-
- /**
- * Get the signal strength.
- */
- getSignalStrength: function() {
- this.context.Buf.simpleRequest(REQUEST_SIGNAL_STRENGTH);
- },
-
- getDeviceIdentity: function() {
- this.deviceIdentities || this.context.Buf.simpleRequest(REQUEST_DEVICE_IDENTITY);
- },
-
- getBasebandVersion: function() {
- this.context.Buf.simpleRequest(REQUEST_BASEBAND_VERSION);
- },
-
- sendExitEmergencyCbModeRequest: function(options) {
- this.context.Buf.simpleRequest(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, options);
- },
-
- getCdmaSubscription: function() {
- this.context.Buf.simpleRequest(REQUEST_CDMA_SUBSCRIPTION);
- },
-
- exitEmergencyCbMode: function(options) {
- // The function could be called by an API from RadioInterfaceLayer or by
- // ril_worker itself. From ril_worker, we won't pass the parameter
- // 'options'. In this case, it is marked as internal.
- if (!options) {
- options = {internal: true};
- }
- this._cancelEmergencyCbModeTimeout();
- this.sendExitEmergencyCbModeRequest(options);
- },
-
- /**
- * Dial a non-emergency number.
- *
- * @param isEmergency
- * Whether the number is an emergency number.
- * @param number
- * String containing the number to dial.
- * @param clirMode
- * Integer for showing/hidding the caller Id to the called party.
- * @param uusInfo
- * Integer doing something XXX TODO
- */
- dial: function(options) {
- if (options.isEmergency) {
- options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ?
- REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL;
-
- } else {
- options.request = REQUEST_DIAL;
-
- // Exit emergency callback mode when user dial a non-emergency call.
- if (this._isInEmergencyCbMode) {
- this.exitEmergencyCbMode();
- }
- }
-
- this.telephonyRequestQueue.push(options.request, () => {
- let Buf = this.context.Buf;
- Buf.newParcel(options.request, options);
- Buf.writeString(options.number);
- Buf.writeInt32(options.clirMode || 0);
- Buf.writeInt32(options.uusInfo || 0);
- // TODO Why do we need this extra 0? It was put it in to make this
- // match the format of the binary message.
- Buf.writeInt32(0);
- Buf.sendParcel();
- });
- },
-
- /**
- * CDMA flash.
- *
- * @param featureStr (optional)
- * Dialing number when the command is used for three-way-calling
- */
- cdmaFlash: function(options) {
- let Buf = this.context.Buf;
- options.request = REQUEST_CDMA_FLASH;
- Buf.newParcel(options.request, options);
- Buf.writeString(options.featureStr || "");
- Buf.sendParcel();
- },
-
- /**
- * Hang up the phone.
- *
- * @param callIndex
- * Call index (1-based) as reported by REQUEST_GET_CURRENT_CALLS.
- */
- hangUpCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_HANGUP, () => {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_HANGUP, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.callIndex);
- Buf.sendParcel();
- });
- },
-
- hangUpForeground: function(options) {
- this.telephonyRequestQueue.push(REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, () => {
- this.context.Buf.simpleRequest(REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
- options);
- });
- },
-
- hangUpBackground: function(options) {
- this.telephonyRequestQueue.push(REQUEST_HANGUP_WAITING_OR_BACKGROUND, () => {
- this.context.Buf.simpleRequest(REQUEST_HANGUP_WAITING_OR_BACKGROUND,
- options);
- });
- },
-
- switchActiveCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, () => {
- this.context.Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
- options);
- });
- },
-
- udub: function(options) {
- this.telephonyRequestQueue.push(REQUEST_UDUB, () => {
- this.context.Buf.simpleRequest(REQUEST_UDUB, options);
- });
- },
-
- answerCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_ANSWER, () => {
- this.context.Buf.simpleRequest(REQUEST_ANSWER, options);
- });
- },
-
- conferenceCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_CONFERENCE, () => {
- this.context.Buf.simpleRequest(REQUEST_CONFERENCE, options);
- });
- },
-
- separateCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_SEPARATE_CONNECTION, () => {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SEPARATE_CONNECTION, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.callIndex);
- Buf.sendParcel();
- });
- },
-
- /**
- * Get current calls.
- */
- getCurrentCalls: function(options) {
- this.telephonyRequestQueue.push(REQUEST_GET_CURRENT_CALLS, () => {
- this.context.Buf.simpleRequest(REQUEST_GET_CURRENT_CALLS, options);
- });
- },
-
- /**
- * Mute or unmute the radio.
- *
- * @param mute
- * Boolean to indicate whether to mute or unmute the radio.
- */
- setMute: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_MUTE);
- Buf.writeInt32(1);
- Buf.writeInt32(options.muted ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Send an SMS.
- *
- * The `options` parameter object should contain the following attributes:
- *
- * @param number
- * String containing the recipient number.
- * @param body
- * String containing the message text.
- * @param envelopeId
- * Numeric value identifying the sms request.
- */
- sendSMS: function(options) {
- options.langIndex = options.langIndex || PDU_NL_IDENTIFIER_DEFAULT;
- options.langShiftIndex = options.langShiftIndex || PDU_NL_IDENTIFIER_DEFAULT;
-
- if (!options.segmentSeq) {
- // Fist segment to send
- options.segmentSeq = 1;
- options.body = options.segments[0].body;
- options.encodedBodyLength = options.segments[0].encodedBodyLength;
- }
-
- let Buf = this.context.Buf;
- if (this._isCdma) {
- Buf.newParcel(REQUEST_CDMA_SEND_SMS, options);
- this.context.CdmaPDUHelper.writeMessage(options);
- } else {
- Buf.newParcel(REQUEST_SEND_SMS, options);
- Buf.writeInt32(2);
- Buf.writeString(options.SMSC);
- this.context.GsmPDUHelper.writeMessage(options);
- }
- Buf.sendParcel();
- },
-
- /**
- * Acknowledge the receipt and handling of an SMS.
- *
- * @param success
- * Boolean indicating whether the message was successfuly handled.
- * @param cause
- * SMS_* constant indicating the reason for unsuccessful handling.
- */
- acknowledgeGsmSms: function(success, cause) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SMS_ACKNOWLEDGE);
- Buf.writeInt32(2);
- Buf.writeInt32(success ? 1 : 0);
- Buf.writeInt32(cause);
- Buf.sendParcel();
- },
-
- /**
- * Acknowledge the receipt and handling of an SMS.
- *
- * @param success
- * Boolean indicating whether the message was successfuly handled.
- */
- ackSMS: function(options) {
- if (options.result == PDU_FCS_RESERVED) {
- return;
- }
- if (this._isCdma) {
- this.acknowledgeCdmaSms(options.result == PDU_FCS_OK, options.result);
- } else {
- this.acknowledgeGsmSms(options.result == PDU_FCS_OK, options.result);
- }
- },
-
- /**
- * Acknowledge the receipt and handling of a CDMA SMS.
- *
- * @param success
- * Boolean indicating whether the message was successfuly handled.
- * @param cause
- * SMS_* constant indicating the reason for unsuccessful handling.
- */
- acknowledgeCdmaSms: function(success, cause) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CDMA_SMS_ACKNOWLEDGE);
- Buf.writeInt32(success ? 0 : 1);
- Buf.writeInt32(cause);
- Buf.sendParcel();
- },
-
- /**
- * Update received MWI into EF_MWIS.
- */
- updateMwis: function(options) {
- if (this.context.ICCUtilsHelper.isICCServiceAvailable("MWIS")) {
- this.context.SimRecordHelper.updateMWIS(options.mwi);
- }
- },
-
- /**
- * Report SMS storage status to modem.
- */
- _updateSmsMemoryStatus: function() {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_REPORT_SMS_MEMORY_STATUS);
- Buf.writeInt32(1);
- Buf.writeInt32(this.smsStorageAvailable ? 1 : 0);
- Buf.sendParcel();
- },
-
- reportSmsMemoryStatus: function(options) {
- this.pendingToReportSmsMemoryStatus = true;
- this.smsStorageAvailable = options.isAvailable;
- this._updateSmsMemoryStatus();
- },
-
- setCellBroadcastDisabled: function(options) {
- this.cellBroadcastDisabled = options.disabled;
-
- // If |this.mergedCellBroadcastConfig| is null, either we haven't finished
- // reading required SIM files, or no any channel is ever configured. In
- // the former case, we'll call |this.updateCellBroadcastConfig()| later
- // with correct configs; in the latter case, we don't bother resetting CB
- // to disabled again.
- if (this.mergedCellBroadcastConfig) {
- this.updateCellBroadcastConfig();
- }
- },
-
- setCellBroadcastSearchList: function(options) {
- let getSearchListStr = function(aSearchList) {
- if (typeof aSearchList === "string" || aSearchList instanceof String) {
- return aSearchList;
- }
-
- // TODO: Set search list for CDMA/GSM individually. Bug 990926
- let prop = this._isCdma ? "cdma" : "gsm";
-
- return aSearchList && aSearchList[prop];
- }.bind(this);
-
- try {
- let str = getSearchListStr(options.searchList);
- this.cellBroadcastConfigs.MMI = this._convertCellBroadcastSearchList(str);
- } catch (e) {
- if (DEBUG) {
- this.context.debug("Invalid Cell Broadcast search list: " + e);
- }
- options.errorMsg = GECKO_ERROR_UNSPECIFIED_ERROR;
- }
-
- this.sendChromeMessage(options);
- if (options.errorMsg) {
- return;
- }
-
- this._mergeAllCellBroadcastConfigs();
- },
-
- updateCellBroadcastConfig: function() {
- let activate = !this.cellBroadcastDisabled &&
- (this.mergedCellBroadcastConfig != null) &&
- (this.mergedCellBroadcastConfig.length > 0);
- if (activate) {
- this.setSmsBroadcastConfig(this.mergedCellBroadcastConfig);
- } else {
- // It's unnecessary to set config first if we're deactivating.
- this.setSmsBroadcastActivation(false);
- }
- },
-
- setGsmSmsBroadcastConfig: function(config) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_GSM_SET_BROADCAST_SMS_CONFIG);
-
- let numConfigs = config ? config.length / 2 : 0;
- Buf.writeInt32(numConfigs);
- for (let i = 0; i < config.length;) {
- // convert [from, to) to [from, to - 1]
- Buf.writeInt32(config[i++]);
- Buf.writeInt32(config[i++] - 1);
- Buf.writeInt32(0x00);
- Buf.writeInt32(0xFF);
- Buf.writeInt32(1);
- }
-
- Buf.sendParcel();
- },
-
- /**
- * Send CDMA SMS broadcast config.
- *
- * @see 3GPP2 C.R1001 Sec. 9.2 and 9.3
- */
- setCdmaSmsBroadcastConfig: function(config) {
- let Buf = this.context.Buf;
- // |config| is an array of half-closed range: [[from, to), [from, to), ...].
- // It will be further decomposed, ex: [1, 4) => 1, 2, 3.
- Buf.newParcel(REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG);
-
- let numConfigs = 0;
- for (let i = 0; i < config.length; i += 2) {
- numConfigs += (config[i+1] - config[i]);
- }
-
- Buf.writeInt32(numConfigs);
- for (let i = 0; i < config.length;) {
- let begin = config[i++];
- let end = config[i++];
-
- for (let j = begin; j < end; ++j) {
- Buf.writeInt32(j);
- Buf.writeInt32(0); // Language Indicator: Unknown or unspecified.
- Buf.writeInt32(1);
- }
- }
-
- Buf.sendParcel();
- },
-
- setSmsBroadcastConfig: function(config) {
- if (this._isCdma) {
- this.setCdmaSmsBroadcastConfig(config);
- } else {
- this.setGsmSmsBroadcastConfig(config);
- }
- },
-
- setSmsBroadcastActivation: function(activate) {
- let parcelType = this._isCdma ? REQUEST_CDMA_SMS_BROADCAST_ACTIVATION :
- REQUEST_GSM_SMS_BROADCAST_ACTIVATION;
- let Buf = this.context.Buf;
- Buf.newParcel(parcelType);
- Buf.writeInt32(1);
- // See hardware/ril/include/telephony/ril.h, 0 - Activate, 1 - Turn off.
- Buf.writeInt32(activate ? 0 : 1);
- Buf.sendParcel();
- },
-
- /**
- * Start a DTMF Tone.
- *
- * @param dtmfChar
- * DTMF signal to send, 0-9, *, +
- */
- startTone: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_DTMF_START, options);
- Buf.writeString(options.dtmfChar);
- Buf.sendParcel();
- },
-
- stopTone: function() {
- this.context.Buf.simpleRequest(REQUEST_DTMF_STOP);
- },
-
- /**
- * Send a DTMF tone.
- *
- * @param dtmfChar
- * DTMF signal to send, 0-9, *, +
- */
- sendTone: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_DTMF);
- Buf.writeString(options.dtmfChar);
- Buf.sendParcel();
- },
-
- /**
- * Get the Short Message Service Center address.
- */
- getSmscAddress: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_SMSC_ADDRESS, options);
- },
-
- /**
- * Set the Short Message Service Center address.
- *
- * @param smscAddress
- * Number part of the SMSC address.
- * @param typeOfNumber
- * Type of number in integer, as defined in
- * |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
- * @param numberPlanIdentification
- * The index of number plan identification value in
- * CALLED_PARTY_BCD_NPI array.
- */
- setSmscAddress: function(options) {
- let ton = options.typeOfNumber;
- let npi = CALLED_PARTY_BCD_NPI[options.numberPlanIdentification];
-
- // If any of the mandatory arguments is not available, return an error
- // immediately.
- if (ton === undefined || npi === undefined || !options.smscAddress) {
- options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
- this.sendChromeMessage(options);
- return;
- }
-
- // Remove all illegal characters in the number string for user-input fault
- // tolerance.
- let numStart = options.smscAddress[0] === "+" ? 1 : 0;
- let number = options.smscAddress.substring(0, numStart) +
- options.smscAddress.substring(numStart)
- .replace(/[^0-9*#abc]/ig, "");
-
- // If the filtered number is an empty string, return an error immediately.
- if (number.length === 0) {
- options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
- this.sendChromeMessage(options);
- return;
- }
-
- // Init parcel.
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_SMSC_ADDRESS, options);
-
- // +---+-----------+---------------+
- // | 1 | TON | NPI |
- // +---+-----------+---------------+
- let tosca = (0x1 << 7) + (ton << 4) + npi;
- if (RILQUIRKS_SMSC_ADDRESS_FORMAT === "pdu") {
- let pduHelper = this.context.GsmPDUHelper;
-
- // Remove the preceding '+', and covert the special BCD digits defined in
- // |Called party BCD number| of 3GPP TS 24.008 to corresponding
- // hexadecimal values (refer the following table).
- //
- // +=========+=======+=====+
- // | value | digit | hex |
- // +========================
- // | 1 0 1 0 | * | 0xA |
- // | 1 0 1 1 | # | 0xB |
- // | 1 1 0 0 | a | 0xC |
- // | 1 1 0 1 | b | 0xD |
- // | 1 1 1 0 | c | 0xE |
- // +=========+=======+=====+
- //
- // The replace order is reversed intentionally, because if the digits are
- // replaced in ascending order, "#" will be converted to "b" and then be
- // converted again to "d", which generates incorrect result.
- let pureNumber = number.substring(numStart)
- .replace(/c/ig, "e")
- .replace(/b/ig, "d")
- .replace(/a/ig, "c")
- .replace(/\#/g, "b")
- .replace(/\*/g, "a");
-
- // address length and string length
- let length = Math.ceil(pureNumber.length / 2) + 1; // +1 octet for TOA
- let strlen = length * 2 + 2; // +2 semi-octets for length octet
-
- Buf.writeInt32(strlen);
- pduHelper.writeHexOctet(length);
- pduHelper.writeHexOctet(tosca);
- pduHelper.writeSwappedNibbleBCD(pureNumber);
- Buf.writeStringDelimiter(strlen);
- } else /* RILQUIRKS_SMSC_ADDRESS_FORMAT === "text" */ {
- let sca;
- sca = '"' + number + '"' + ',' + tosca;
- Buf.writeString(sca);
- }
-
- Buf.sendParcel();
- },
-
- /**
- * Setup a data call.
- *
- * @param radioTech
- * Integer to indicate radio technology.
- * DATACALL_RADIOTECHNOLOGY_CDMA => CDMA.
- * DATACALL_RADIOTECHNOLOGY_GSM => GSM.
- * @param apn
- * String containing the name of the APN to connect to.
- * @param user
- * String containing the username for the APN.
- * @param passwd
- * String containing the password for the APN.
- * @param chappap
- * Integer containing CHAP/PAP auth type.
- * DATACALL_AUTH_NONE => PAP and CHAP is never performed.
- * DATACALL_AUTH_PAP => PAP may be performed.
- * DATACALL_AUTH_CHAP => CHAP may be performed.
- * DATACALL_AUTH_PAP_OR_CHAP => PAP / CHAP may be performed.
- * @param pdptype
- * String containing PDP type to request. ("IP", "IPV6", ...)
- */
- setupDataCall: function(options) {
- // From ./hardware/ril/include/telephony/ril.h:
- // ((const char **)data)[0] Radio technology to use: 0-CDMA, 1-GSM/UMTS, 2...
- // for values above 2 this is RIL_RadioTechnology + 2.
- //
- // From frameworks/base/telephony/java/com/android/internal/telephony/DataConnection.java:
- // if the mRilVersion < 6, radio technology must be GSM/UMTS or CDMA.
- // Otherwise, it must be + 2
- //
- // See also bug 901232 and 867873
- let radioTech = options.radioTech + 2;
- let Buf = this.context.Buf;
- let token = Buf.newParcel(REQUEST_SETUP_DATA_CALL, options);
- Buf.writeInt32(7);
- Buf.writeString(radioTech.toString());
- Buf.writeString(DATACALL_PROFILE_DEFAULT.toString());
- Buf.writeString(options.apn);
- Buf.writeString(options.user);
- Buf.writeString(options.passwd);
- Buf.writeString(options.chappap.toString());
- Buf.writeString(options.pdptype);
- Buf.sendParcel();
- return token;
- },
-
- /**
- * Deactivate a data call.
- *
- * @param cid
- * String containing CID.
- * @param reason
- * One of DATACALL_DEACTIVATE_* constants.
- */
- deactivateDataCall: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_DEACTIVATE_DATA_CALL, options);
- Buf.writeInt32(2);
- Buf.writeString(options.cid.toString());
- Buf.writeString(options.reason !== undefined ?
- options.reason.toString() :
- DATACALL_DEACTIVATE_NO_REASON.toString());
- Buf.sendParcel();
- },
-
- /**
- * Get a list of data calls.
- */
- getDataCallList: function(options) {
- this.context.Buf.simpleRequest(REQUEST_DATA_CALL_LIST, options);
- },
-
- _attachDataRegistration: false,
- /**
- * Manually attach/detach data registration.
- *
- * @param attach
- * Boolean value indicating attach or detach.
- */
- setDataRegistration: function(options) {
- this._attachDataRegistration = options.attach;
-
- if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
- let request = options.attach ? RIL_REQUEST_GPRS_ATTACH :
- RIL_REQUEST_GPRS_DETACH;
- this.context.Buf.simpleRequest(request, options);
- return;
- } else if (RILQUIRKS_SUBSCRIPTION_CONTROL && options.attach) {
- this.context.Buf.simpleRequest(REQUEST_SET_DATA_SUBSCRIPTION, options);
- return;
- }
-
- // We don't really send a request to rild, so instantly reply success to
- // RadioInterfaceLayer.
- this.sendChromeMessage(options);
- },
-
- /**
- * Get failure casue code for the most recently failed PDP context.
- */
- getFailCause: function(options) {
- this.context.Buf.simpleRequest(REQUEST_LAST_CALL_FAIL_CAUSE, options);
- },
-
- /**
- * Send USSD.
- *
- * @param ussd
- * String containing the USSD code.
- */
- sendUSSD: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SEND_USSD, options);
- Buf.writeString(options.ussd);
- Buf.sendParcel();
- },
-
- /**
- * Cancel pending USSD.
- */
- cancelUSSD: function(options) {
- this.context.Buf.simpleRequest(REQUEST_CANCEL_USSD, options);
- },
-
- /**
- * Queries current call forward rules.
- *
- * @param reason
- * One of CALL_FORWARD_REASON_* constants.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- * @param number
- * Phone number of forwarding address.
- */
- queryCallForwardStatus: function(options) {
- let Buf = this.context.Buf;
- let number = options.number || "";
- Buf.newParcel(REQUEST_QUERY_CALL_FORWARD_STATUS, options);
- Buf.writeInt32(CALL_FORWARD_ACTION_QUERY_STATUS);
- Buf.writeInt32(options.reason);
- Buf.writeInt32(options.serviceClass || ICC_SERVICE_CLASS_NONE);
- Buf.writeInt32(this._toaFromString(number));
- Buf.writeString(number);
- Buf.writeInt32(0);
- Buf.sendParcel();
- },
-
- /**
- * Configures call forward rule.
- *
- * @param action
- * One of CALL_FORWARD_ACTION_* constants.
- * @param reason
- * One of CALL_FORWARD_REASON_* constants.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- * @param number
- * Phone number of forwarding address.
- * @param timeSeconds
- * Time in seconds to wait beforec all is forwarded.
- */
- setCallForward: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_CALL_FORWARD, options);
- Buf.writeInt32(options.action);
- Buf.writeInt32(options.reason);
- Buf.writeInt32(options.serviceClass);
- Buf.writeInt32(this._toaFromString(options.number));
- Buf.writeString(options.number);
- Buf.writeInt32(options.timeSeconds);
- Buf.sendParcel();
- },
-
- /**
- * Queries current call barring rules.
- *
- * @param program
- * One of CALL_BARRING_PROGRAM_* constants.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- */
- queryCallBarringStatus: function(options) {
- options.facility = CALL_BARRING_PROGRAM_TO_FACILITY[options.program];
- options.password = ""; // For query no need to provide it.
-
- // For some operators, querying specific serviceClass doesn't work. We use
- // serviceClass 0 instead, and then process the response to extract the
- // answer for queryServiceClass.
- options.queryServiceClass = options.serviceClass;
- options.serviceClass = 0;
-
- this.queryICCFacilityLock(options);
- },
-
- /**
- * Configures call barring rule.
- *
- * @param program
- * One of CALL_BARRING_PROGRAM_* constants.
- * @param enabled
- * Enable or disable the call barring.
- * @param password
- * Barring password.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- */
- setCallBarring: function(options) {
- options.facility = CALL_BARRING_PROGRAM_TO_FACILITY[options.program];
- this.setICCFacilityLock(options);
- },
-
- /**
- * Change call barring facility password.
- *
- * @param pin
- * Old password.
- * @param newPin
- * New password.
- */
- changeCallBarringPassword: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CHANGE_BARRING_PASSWORD, options);
- Buf.writeInt32(3);
- // Set facility to ICC_CB_FACILITY_BA_ALL by following TS.22.030 clause
- // 6.5.4 and Table B.1.
- Buf.writeString(ICC_CB_FACILITY_BA_ALL);
- Buf.writeString(options.pin);
- Buf.writeString(options.newPin);
- Buf.sendParcel();
- },
-
- /**
- * Handle STK CALL_SET_UP request.
- *
- * @param hasConfirmed
- * Does use have confirmed the call requested from ICC?
- */
- stkHandleCallSetup: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM);
- Buf.writeInt32(1);
- Buf.writeInt32(options.hasConfirmed ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Send STK Profile Download.
- *
- * @param profile Profile supported by ME.
- */
- sendStkTerminalProfile: function(profile) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- Buf.newParcel(REQUEST_STK_SET_PROFILE);
- Buf.writeInt32(profile.length * 2);
- for (let i = 0; i < profile.length; i++) {
- GsmPDUHelper.writeHexOctet(profile[i]);
- }
- Buf.writeInt32(0);
- Buf.sendParcel();
- },
-
- /**
- * Send STK terminal response.
- *
- * @param command
- * @param deviceIdentities
- * @param resultCode
- * @param [optional] additionalInformation
- * @param [optional] itemIdentifier
- * @param [optional] input
- * @param [optional] isYesNo
- * @param [optional] hasConfirmed
- * @param [optional] localInfo
- * @param [optional] timer
- */
- sendStkTerminalResponse: function(response) {
- if (response.hasConfirmed !== undefined) {
- this.stkHandleCallSetup(response);
- return;
- }
-
- let Buf = this.context.Buf;
- let ComprehensionTlvHelper = this.context.ComprehensionTlvHelper;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let command = response.command;
- Buf.newParcel(REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // 1st mark for Parcel size
- Buf.startCalOutgoingSize(function(size) {
- // Parcel size is in string length, which costs 2 uint8 per char.
- Buf.writeInt32(size / 2);
- });
-
- // Command Details
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(3);
- if (command) {
- GsmPDUHelper.writeHexOctet(command.commandNumber);
- GsmPDUHelper.writeHexOctet(command.typeOfCommand);
- GsmPDUHelper.writeHexOctet(command.commandQualifier);
- } else {
- GsmPDUHelper.writeHexOctet(0x00);
- GsmPDUHelper.writeHexOctet(0x00);
- GsmPDUHelper.writeHexOctet(0x00);
- }
-
- // Device Identifier
- // According to TS102.223/TS31.111 section 6.8 Structure of
- // TERMINAL RESPONSE, "For all SIMPLE-TLV objects with Min=N,
- // the ME should set the CR(comprehension required) flag to
- // comprehension not required.(CR=0)"
- // Since DEVICE_IDENTITIES and DURATION TLVs have Min=N,
- // the CR flag is not set.
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DEVICE_ID);
- GsmPDUHelper.writeHexOctet(2);
- GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_ME);
- GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_SIM);
-
- // Result
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- if ("additionalInformation" in response) {
- // In |12.12 Result| TS 11.14, the length of additional information is
- // varied and all possible values are addressed in 12.12.1-11 of TS 11.14
- // and 8.12.1-13 in TS 31.111.
- // However,
- // 1. Only SEND SS requires info with more than 1 octet.
- // 2. In rild design, SEND SS is expected to be handled by modem and
- // UNSOLICITED_STK_EVENT_NOTIFY will be sent to application layer to
- // indicate appropriate messages to users. TR is not required in this
- // case.
- // Hence, we simplify the structure of |additionalInformation| to a
- // numeric value instead of a octet array.
- GsmPDUHelper.writeHexOctet(2);
- GsmPDUHelper.writeHexOctet(response.resultCode);
- GsmPDUHelper.writeHexOctet(response.additionalInformation);
- } else {
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(response.resultCode);
- }
-
- // Item Identifier
- if (response.itemIdentifier != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ITEM_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(response.itemIdentifier);
- }
-
- // No need to process Text data if user requests help information.
- if (response.resultCode != STK_RESULT_HELP_INFO_REQUIRED) {
- let text;
- let coding = command.options.isUCS2 ?
- STK_TEXT_CODING_UCS2 :
- (command.options.isPacked ?
- STK_TEXT_CODING_GSM_7BIT_PACKED :
- STK_TEXT_CODING_GSM_8BIT);
- if (response.isYesNo !== undefined) {
- // Tag: GET_INKEY
- // When the ME issues a successful TERMINAL RESPONSE for a GET INKEY
- // ("Yes/No") command with command qualifier set to "Yes/No", it shall
- // supply the value '01' when the answer is "positive" and the value
- // '00' when the answer is "negative" in the Text string data object.
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- // Length: 2
- GsmPDUHelper.writeHexOctet(2);
- // Value: Coding, Yes/No.
- GsmPDUHelper.writeHexOctet(coding);
- GsmPDUHelper.writeHexOctet(response.isYesNo ? 0x01 : 0x00);
- } else {
- if (response.input !== undefined) {
- ComprehensionTlvHelper.writeTextStringTlv(response.input, coding);
- }
- }
- }
-
- // Duration
- if (response.resultCode === STK_RESULT_NO_RESPONSE_FROM_USER) {
- // In TS102 223, 6.4.2 GET INKEY, "if the UICC requests a variable timeout,
- // the terminal shall wait until either the user enters a single character
- // or the timeout expires. The timer starts when the text is displayed on
- // the screen and stops when the TERMINAL RESPONSE is sent. The terminal
- // shall pass the total display text duration (command execution duration)
- // to the UICC using the TERMINAL RESPONSE. The time unit of the response
- // is identical to the time unit of the requested variable timeout."
- let duration = command && command.options && command.options.duration;
- if (duration) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DURATION);
- GsmPDUHelper.writeHexOctet(2);
- GsmPDUHelper.writeHexOctet(duration.timeUnit);
- GsmPDUHelper.writeHexOctet(duration.timeInterval);
- }
- }
-
- // Local Information
- if (response.localInfo) {
- let localInfo = response.localInfo;
-
- // Location Infomation
- if (localInfo.locationInfo) {
- ComprehensionTlvHelper.writeLocationInfoTlv(localInfo.locationInfo);
- }
-
- // IMEI
- if (localInfo.imei != null) {
- let imei = localInfo.imei;
- if (imei.length == 15) {
- imei = imei + "0";
- }
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_IMEI);
- GsmPDUHelper.writeHexOctet(8);
- for (let i = 0; i < imei.length / 2; i++) {
- GsmPDUHelper.writeHexOctet(parseInt(imei.substr(i * 2, 2), 16));
- }
- }
-
- // Date and Time Zone
- if (localInfo.date != null) {
- ComprehensionTlvHelper.writeDateTimeZoneTlv(localInfo.date);
- }
-
- // Language
- if (localInfo.language) {
- ComprehensionTlvHelper.writeLanguageTlv(localInfo.language);
- }
- }
-
- // Timer
- if (response.timer) {
- let timer = response.timer;
-
- if (timer.timerId) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(timer.timerId);
- }
-
- if (timer.timerValue) {
- ComprehensionTlvHelper.writeTimerValueTlv(timer.timerValue, false);
- }
- }
-
- // Calculate and write Parcel size to 1st mark
- Buf.stopCalOutgoingSize();
-
- Buf.writeInt32(0);
- Buf.sendParcel();
- },
-
- /**
- * Send STK Envelope(Menu Selection) command.
- *
- * @param itemIdentifier
- * @param helpRequested
- */
- sendStkMenuSelection: function(command) {
- command.tag = BER_MENU_SELECTION_TAG;
- command.deviceId = {
- sourceId :STK_DEVICE_ID_KEYPAD,
- destinationId: STK_DEVICE_ID_SIM
- };
- this.sendICCEnvelopeCommand(command);
- },
-
- /**
- * Send STK Envelope(Timer Expiration) command.
- *
- * @param timer
- */
- sendStkTimerExpiration: function(command) {
- command.tag = BER_TIMER_EXPIRATION_TAG;
- command.deviceId = {
- sourceId: STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.timerId = command.timer.timerId;
- command.timerValue = command.timer.timerValue;
- this.sendICCEnvelopeCommand(command);
- },
-
- /**
- * Send STK Envelope(Event Download) command.
- * @param event
- */
- sendStkEventDownload: function(command) {
- command.tag = BER_EVENT_DOWNLOAD_TAG;
- command.eventList = command.event.eventType;
- switch (command.eventList) {
- case STK_EVENT_TYPE_LOCATION_STATUS:
- command.deviceId = {
- sourceId :STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.locationStatus = command.event.locationStatus;
- // Location info should only be provided when locationStatus is normal.
- if (command.locationStatus == STK_SERVICE_STATE_NORMAL) {
- command.locationInfo = command.event.locationInfo;
- }
- break;
- case STK_EVENT_TYPE_MT_CALL:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_NETWORK,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.transactionId = 0;
- command.address = command.event.number;
- break;
- case STK_EVENT_TYPE_CALL_DISCONNECTED:
- command.cause = command.event.error;
- // Fall through.
- case STK_EVENT_TYPE_CALL_CONNECTED:
- command.deviceId = {
- sourceId: (command.event.isIssuedByRemote ?
- STK_DEVICE_ID_NETWORK : STK_DEVICE_ID_ME),
- destinationId: STK_DEVICE_ID_SIM
- };
- command.transactionId = 0;
- break;
- case STK_EVENT_TYPE_USER_ACTIVITY:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- break;
- case STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_DISPLAY,
- destinationId: STK_DEVICE_ID_SIM
- };
- break;
- case STK_EVENT_TYPE_LANGUAGE_SELECTION:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.language = command.event.language;
- break;
- case STK_EVENT_TYPE_BROWSER_TERMINATION:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.terminationCause = command.event.terminationCause;
- break;
- }
- this.sendICCEnvelopeCommand(command);
- },
-
- /**
- * Send REQUEST_STK_SEND_ENVELOPE_COMMAND to ICC.
- *
- * @param tag
- * @patam deviceId
- * @param [optioanl] itemIdentifier
- * @param [optional] helpRequested
- * @param [optional] eventList
- * @param [optional] locationStatus
- * @param [optional] locationInfo
- * @param [optional] address
- * @param [optional] transactionId
- * @param [optional] cause
- * @param [optional] timerId
- * @param [optional] timerValue
- * @param [optional] terminationCause
- */
- sendICCEnvelopeCommand: function(options) {
- if (DEBUG) {
- this.context.debug("Stk Envelope " + JSON.stringify(options));
- }
-
- let Buf = this.context.Buf;
- let ComprehensionTlvHelper = this.context.ComprehensionTlvHelper;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // 1st mark for Parcel size
- Buf.startCalOutgoingSize(function(size) {
- // Parcel size is in string length, which costs 2 uint8 per char.
- Buf.writeInt32(size / 2);
- });
-
- // Write a BER-TLV
- GsmPDUHelper.writeHexOctet(options.tag);
- // 2nd mark for BER length
- Buf.startCalOutgoingSize(function(size) {
- // BER length is in number of hexOctets, which costs 4 uint8 per hexOctet.
- GsmPDUHelper.writeHexOctet(size / 4);
- });
-
- // Event List
- if (options.eventList != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.eventList);
- }
-
- // Device Identifies
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(2);
- GsmPDUHelper.writeHexOctet(options.deviceId.sourceId);
- GsmPDUHelper.writeHexOctet(options.deviceId.destinationId);
-
- // Item Identifier
- if (options.itemIdentifier != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ITEM_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.itemIdentifier);
- }
-
- // Help Request
- if (options.helpRequested) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_HELP_REQUEST |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(0);
- // Help Request doesn't have value
- }
-
- // Location Status
- if (options.locationStatus != null) {
- let len = options.locationStatus.length;
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LOCATION_STATUS |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.locationStatus);
- }
-
- // Location Info
- if (options.locationInfo) {
- ComprehensionTlvHelper.writeLocationInfoTlv(options.locationInfo);
- }
-
- // Transaction Id
- if (options.transactionId != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TRANSACTION_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.transactionId);
- }
-
- // Address
- if (options.address) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ADDRESS |
- COMPREHENSIONTLV_FLAG_CR);
- let addressLength = options.address[0] == '+' ? options.address.length - 1
- : options.address.length;
- ComprehensionTlvHelper.writeLength(
- Math.ceil(addressLength / 2) + 1 // address BCD + TON
- );
- this.context.ICCPDUHelper.writeDiallingNumber(options.address);
- }
-
- // Cause of disconnection.
- if (options.cause != null) {
- ComprehensionTlvHelper.writeCauseTlv(options.cause);
- }
-
- // Timer Identifier
- if (options.timerId != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.timerId);
- }
-
- // Timer Value
- if (options.timerValue != null) {
- ComprehensionTlvHelper.writeTimerValueTlv(options.timerValue, true);
- }
-
- // Language
- if (options.language) {
- ComprehensionTlvHelper.writeLanguageTlv(options.language);
- }
-
- // Browser Termination
- if (options.terminationCause != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_BROWSER_TERMINATION_CAUSE |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.terminationCause);
- }
-
- // Calculate and write BER length to 2nd mark
- Buf.stopCalOutgoingSize();
-
- // Calculate and write Parcel size to 1st mark
- Buf.stopCalOutgoingSize();
-
- Buf.writeInt32(0);
- Buf.sendParcel();
- },
-
- /**
- * Report STK Service is running.
- */
- reportStkServiceIsRunning: function() {
- this.context.Buf.simpleRequest(REQUEST_REPORT_STK_SERVICE_IS_RUNNING);
- },
-
- /**
- * Process ICC status.
- */
- _processICCStatus: function(iccStatus) {
- // If |_waitingRadioTech| is true, we should not get app information because
- // the |_isCdma| flag is not ready yet. Otherwise we may use wrong index to
- // get app information, especially for the case that icc card has both cdma
- // and gsm subscription.
- if (this._waitingRadioTech) {
- return;
- }
-
- // When |iccStatus.cardState| is not CARD_STATE_PRESENT, set cardState to
- // undetected.
- if (iccStatus.cardState !== CARD_STATE_PRESENT) {
- if (this.cardState !== GECKO_CARDSTATE_UNDETECTED) {
- this.operator = null;
- // We should send |cardstatechange| before |iccinfochange|, otherwise we
- // may lost cardstatechange event when icc card becomes undetected.
- this.cardState = GECKO_CARDSTATE_UNDETECTED;
- this.sendChromeMessage({rilMessageType: "cardstatechange",
- cardState: this.cardState});
-
- this.iccInfo = {iccType: null};
- this.context.ICCUtilsHelper.handleICCInfoChange();
- }
- return;
- }
-
- if (RILQUIRKS_SUBSCRIPTION_CONTROL) {
- // All appIndex is -1 means the subscription is not activated yet.
- // Note that we don't support "ims" for now, so we don't take it into
- // account.
- let neetToActivate = iccStatus.cdmaSubscriptionAppIndex === -1 &&
- iccStatus.gsmUmtsSubscriptionAppIndex === -1;
- if (neetToActivate &&
- // Note: setUiccSubscription works abnormally when RADIO is OFF,
- // which causes SMS function broken in Flame.
- // See bug 1008557 for detailed info.
- this.radioState === GECKO_RADIOSTATE_ENABLED) {
- for (let i = 0; i < iccStatus.apps.length; i++) {
- this.setUiccSubscription({appIndex: i, enabled: true});
- }
- }
- }
-
- let newCardState;
- let index = this._isCdma ? iccStatus.cdmaSubscriptionAppIndex
- : iccStatus.gsmUmtsSubscriptionAppIndex;
- let app = iccStatus.apps[index];
- if (app) {
- // fetchICCRecords will need to read aid, so read aid here.
- this.aid = app.aid;
- this.appType = app.app_type;
- this.iccInfo.iccType = GECKO_CARD_TYPE[this.appType];
-
- switch (app.app_state) {
- case CARD_APPSTATE_ILLEGAL:
- newCardState = GECKO_CARDSTATE_ILLEGAL;
- break;
- case CARD_APPSTATE_PIN:
- newCardState = GECKO_CARDSTATE_PIN_REQUIRED;
- break;
- case CARD_APPSTATE_PUK:
- newCardState = GECKO_CARDSTATE_PUK_REQUIRED;
- break;
- case CARD_APPSTATE_SUBSCRIPTION_PERSO:
- newCardState = PERSONSUBSTATE[app.perso_substate];
- break;
- case CARD_APPSTATE_READY:
- newCardState = GECKO_CARDSTATE_READY;
- break;
- case CARD_APPSTATE_UNKNOWN:
- case CARD_APPSTATE_DETECTED:
- // Fall through.
- default:
- newCardState = GECKO_CARDSTATE_UNKNOWN;
- }
-
- let pin1State = app.pin1_replaced ? iccStatus.universalPINState :
- app.pin1;
- if (pin1State === CARD_PINSTATE_ENABLED_PERM_BLOCKED) {
- newCardState = GECKO_CARDSTATE_PERMANENT_BLOCKED;
- }
- } else {
- // Having incorrect app information, set card state to unknown.
- newCardState = GECKO_CARDSTATE_UNKNOWN;
- }
-
- let ICCRecordHelper = this.context.ICCRecordHelper;
- // Try to get iccId only when cardState left GECKO_CARDSTATE_UNDETECTED.
- if (iccStatus.cardState === CARD_STATE_PRESENT &&
- (this.cardState === GECKO_CARDSTATE_UNINITIALIZED ||
- this.cardState === GECKO_CARDSTATE_UNDETECTED)) {
- ICCRecordHelper.readICCID();
- }
-
- if (this.cardState == newCardState) {
- return;
- }
-
- // This was moved down from CARD_APPSTATE_READY
- this.requestNetworkInfo();
- if (newCardState == GECKO_CARDSTATE_READY) {
- // For type SIM, we need to check EF_phase first.
- // Other types of ICC we can send Terminal_Profile immediately.
- if (this.appType == CARD_APPTYPE_SIM) {
- this.context.SimRecordHelper.readSimPhase();
- } else if (RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD) {
- this.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
- }
-
- ICCRecordHelper.fetchICCRecords();
- }
-
- this.cardState = newCardState;
- this.sendChromeMessage({rilMessageType: "cardstatechange",
- cardState: this.cardState});
- },
-
- /**
- * Helper for processing responses of functions such as enterICC* and changeICC*.
- */
- _processEnterAndChangeICCResponses: function(length, options) {
- options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
- this.sendChromeMessage(options);
- },
-
- // We combine all of the NETWORK_INFO_MESSAGE_TYPES into one "networkinfochange"
- // message to the RadioInterfaceLayer, so we can avoid sending multiple
- // VoiceInfoChanged events for both operator / voice_data_registration
- //
- // State management here is a little tricky. We need to know both:
- // 1. Whether or not a response was received for each of the
- // NETWORK_INFO_MESSAGE_TYPES
- // 2. The outbound message that corresponds with that response -- but this
- // only happens when internal state changes (i.e. it isn't guaranteed)
- //
- // To collect this state, each message response function first calls
- // _receivedNetworkInfo, to mark the response as received. When the
- // final response is received, a call to _sendPendingNetworkInfo is placed
- // on the next tick of the worker thread.
- //
- // Since the original call to _receivedNetworkInfo happens at the top
- // of the response handler, this gives the final handler a chance to
- // queue up it's "changed" message by calling _sendNetworkInfoMessage if/when
- // the internal state has actually changed.
- _sendNetworkInfoMessage: function(type, message) {
- if (!this._processingNetworkInfo) {
- // We only combine these messages in the case of the combined request
- // in requestNetworkInfo()
- this.sendChromeMessage(message);
- return;
- }
-
- if (DEBUG) {
- this.context.debug("Queuing " + type + " network info message: " +
- JSON.stringify(message));
- }
- this._pendingNetworkInfo[type] = message;
- },
-
- _receivedNetworkInfo: function(type) {
- if (DEBUG) this.context.debug("Received " + type + " network info.");
- if (!this._processingNetworkInfo) {
- return;
- }
-
- let pending = this._pendingNetworkInfo;
-
- // We still need to track states for events that aren't fired.
- if (!(type in pending)) {
- pending[type] = this.pendingNetworkType;
- }
-
- // Pending network info is ready to be sent when no more messages
- // are waiting for responses, but the combined payload hasn't been sent.
- for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
- let msgType = NETWORK_INFO_MESSAGE_TYPES[i];
- if (!(msgType in pending)) {
- if (DEBUG) {
- this.context.debug("Still missing some more network info, not " +
- "notifying main thread.");
- }
- return;
- }
- }
-
- // Do a pass to clean up the processed messages that didn't create
- // a response message, so we don't have unused keys in the outbound
- // networkinfochanged message.
- for (let key in pending) {
- if (pending[key] == this.pendingNetworkType) {
- delete pending[key];
- }
- }
-
- if (DEBUG) {
- this.context.debug("All pending network info has been received: " +
- JSON.stringify(pending));
- }
-
- // Send the message on the next tick of the worker's loop, so we give the
- // last message a chance to call _sendNetworkInfoMessage first.
- setTimeout(this._sendPendingNetworkInfo.bind(this), 0);
- },
-
- _sendPendingNetworkInfo: function() {
- this.sendChromeMessage(this._pendingNetworkInfo);
-
- this._processingNetworkInfo = false;
- for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
- delete this._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]];
- }
-
- if (this._needRepollNetworkInfo) {
- this._needRepollNetworkInfo = false;
- this.requestNetworkInfo();
- }
- },
-
- /**
- * Normalize the signal strength in dBm to the signal level from 0 to 100.
- *
- * @param signal
- * The signal strength in dBm to normalize.
- * @param min
- * The signal strength in dBm maps to level 0.
- * @param max
- * The signal strength in dBm maps to level 100.
- *
- * @return level
- * The signal level from 0 to 100.
- */
- _processSignalLevel: function(signal, min, max) {
- if (signal <= min) {
- return 0;
- }
-
- if (signal >= max) {
- return 100;
- }
-
- return Math.floor((signal - min) * 100 / (max - min));
- },
-
- /**
- * Process LTE signal strength to the signal info object.
- *
- * @param signal
- * The signal object reported from RIL/modem.
- *
- * @return The object of signal strength info.
- * Or null if invalid signal input.
- *
- * TODO: Bug 982013: reconsider the format of signal strength APIs for
- * GSM/CDMA/LTE to expose details, such as rsrp and rsnnr,
- * individually.
- */
- _processLteSignal: function(signal) {
- let info = {
- voice: {
- signalStrength: null,
- relSignalStrength: null
- },
- data: {
- signalStrength: null,
- relSignalStrength: null
- }
- };
-
- // Referring to AOSP, use lteRSRP for signalStrength in dBm.
- let signalStrength = (signal.lteRSRP === undefined || signal.lteRSRP === 0x7FFFFFFF) ?
- null : signal.lteRSRP;
- info.voice.signalStrength = info.data.signalStrength = signalStrength;
-
- // Referring to AOSP, first determine signalLevel based on RSRP and RSSNR,
- // then on lteSignalStrength if RSRP and RSSNR are invalid.
- let rsrpLevel = -1;
- let rssnrLevel = -1;
- if (signal.lteRSRP !== undefined &&
- signal.lteRSRP !== 0x7FFFFFFF &&
- signal.lteRSRP >= 44 &&
- signal.lteRSRP <= 140) {
- rsrpLevel = this._processSignalLevel(signal.lteRSRP * -1, -115, -85);
- }
-
- if (signal.lteRSSNR !== undefined &&
- signal.lteRSSNR !== 0x7FFFFFFF &&
- signal.lteRSSNR >= -200 &&
- signal.lteRSSNR <= 300) {
- rssnrLevel = this._processSignalLevel(signal.lteRSSNR, -30, 130);
- }
-
- if (rsrpLevel !== -1 && rssnrLevel !== -1) {
- info.voice.relSignalStrength = info.data.relSignalStrength =
- Math.min(rsrpLevel, rssnrLevel);
- return info;
- }
-
- let level = Math.max(rsrpLevel, rssnrLevel);
- if (level !== -1) {
- info.voice.relSignalStrength = info.data.relSignalStrength = level;
- return info;
- }
-
- // Valid values are 0-63 as defined in TS 27.007 clause 8.69.
- if (signal.lteSignalStrength !== undefined &&
- signal.lteSignalStrength >= 0 &&
- signal.lteSignalStrength <= 63) {
- level = this._processSignalLevel(signal.lteSignalStrength, 0, 12);
- info.voice.relSignalStrength = info.data.relSignalStrength = level;
- return info;
- }
-
- return null;
- },
-
- _processSignalStrength: function(signal) {
- let info = {
- voice: {
- signalStrength: null,
- relSignalStrength: null
- },
- data: {
- signalStrength: null,
- relSignalStrength: null
- }
- };
-
- // During startup, |radioTech| is not yet defined, so we need to
- // check it separately.
- if (("radioTech" in this.voiceRegistrationState) &&
- !this._isGsmTechGroup(this.voiceRegistrationState.radioTech)) {
- // CDMA RSSI.
- // Valid values are positive integers. This value is the actual RSSI value
- // multiplied by -1. Example: If the actual RSSI is -75, then this
- // response value will be 75.
- if (signal.cdmaDBM && signal.cdmaDBM > 0) {
- let signalStrength = -1 * signal.cdmaDBM;
- info.voice.signalStrength = signalStrength;
-
- // -105 and -70 are referred to AOSP's implementation. These values are
- // not constants and can be customized based on different requirement.
- let signalLevel = this._processSignalLevel(signalStrength, -105, -70);
- info.voice.relSignalStrength = signalLevel;
- }
-
- // EVDO RSSI.
- // Valid values are positive integers. This value is the actual RSSI value
- // multiplied by -1. Example: If the actual RSSI is -75, then this
- // response value will be 75.
- if (signal.evdoDBM && signal.evdoDBM > 0) {
- let signalStrength = -1 * signal.evdoDBM;
- info.data.signalStrength = signalStrength;
-
- // -105 and -70 are referred to AOSP's implementation. These values are
- // not constants and can be customized based on different requirement.
- let signalLevel = this._processSignalLevel(signalStrength, -105, -70);
- info.data.relSignalStrength = signalLevel;
- }
- } else {
- // Check LTE level first, and check GSM/UMTS level next if LTE one is not
- // valid.
- let lteInfo = this._processLteSignal(signal);
- if (lteInfo) {
- info = lteInfo;
- } else {
- // GSM signal strength.
- // Valid values are 0-31 as defined in TS 27.007 8.5.
- // 0 : -113 dBm or less
- // 1 : -111 dBm
- // 2...30: -109...-53 dBm
- // 31 : -51 dBm
- if (signal.gsmSignalStrength &&
- signal.gsmSignalStrength >= 0 &&
- signal.gsmSignalStrength <= 31) {
- let signalStrength = -113 + 2 * signal.gsmSignalStrength;
- info.voice.signalStrength = info.data.signalStrength = signalStrength;
-
- // -115 and -85 are referred to AOSP's implementation. These values are
- // not constants and can be customized based on different requirement.
- let signalLevel = this._processSignalLevel(signalStrength, -110, -85);
- info.voice.relSignalStrength = info.data.relSignalStrength = signalLevel;
- }
- }
- }
-
- info.rilMessageType = "signalstrengthchange";
- this._sendNetworkInfoMessage(NETWORK_INFO_SIGNAL, info);
- },
-
- /**
- * Process the network registration flags.
- *
- * @return true if the state changed, false otherwise.
- */
- _processCREG: function(curState, newState) {
- let changed = false;
-
- let regState = this.parseInt(newState[0], NETWORK_CREG_STATE_UNKNOWN);
- if (curState.regState === undefined || curState.regState !== regState) {
- changed = true;
- curState.regState = regState;
-
- curState.state = NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[regState];
- curState.connected = regState == NETWORK_CREG_STATE_REGISTERED_HOME ||
- regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
- curState.roaming = regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
- curState.emergencyCallsOnly = !curState.connected;
- }
-
- if (!curState.cell) {
- curState.cell = {};
- }
-
- // From TS 23.003, 0000 and 0xfffe are indicated that no valid LAI exists
- // in MS. So we still need to report the '0000' as well.
- let lac = this.parseInt(newState[1], -1, 16);
- if (curState.cell.gsmLocationAreaCode === undefined ||
- curState.cell.gsmLocationAreaCode !== lac) {
- curState.cell.gsmLocationAreaCode = lac;
- changed = true;
- }
-
- let cid = this.parseInt(newState[2], -1, 16);
- if (curState.cell.gsmCellId === undefined ||
- curState.cell.gsmCellId !== cid) {
- curState.cell.gsmCellId = cid;
- changed = true;
- }
-
- let radioTech = (newState[3] === undefined ?
- NETWORK_CREG_TECH_UNKNOWN :
- this.parseInt(newState[3], NETWORK_CREG_TECH_UNKNOWN));
- if (curState.radioTech === undefined || curState.radioTech !== radioTech) {
- changed = true;
- curState.radioTech = radioTech;
- curState.type = GECKO_RADIO_TECH[radioTech] || null;
- }
- return changed;
- },
-
- _processVoiceRegistrationState: function(state) {
- let rs = this.voiceRegistrationState;
- let stateChanged = this._processCREG(rs, state);
- if (stateChanged && rs.connected) {
- this.getSmscAddress();
- }
-
- let cell = rs.cell;
- if (this._isCdma) {
- // Some variables below are not used. Comment them instead of removing to
- // keep the information about state[x].
- let cdmaBaseStationId = this.parseInt(state[4], -1);
- let cdmaBaseStationLatitude = this.parseInt(state[5], -2147483648);
- let cdmaBaseStationLongitude = this.parseInt(state[6], -2147483648);
- // let cssIndicator = this.parseInt(state[7]);
- let cdmaSystemId = this.parseInt(state[8], -1);
- let cdmaNetworkId = this.parseInt(state[9], -1);
- // let roamingIndicator = this.parseInt(state[10]);
- // let systemIsInPRL = this.parseInt(state[11]);
- // let defaultRoamingIndicator = this.parseInt(state[12]);
- // let reasonForDenial = this.parseInt(state[13]);
-
- if (cell.cdmaBaseStationId !== cdmaBaseStationId ||
- cell.cdmaBaseStationLatitude !== cdmaBaseStationLatitude ||
- cell.cdmaBaseStationLongitude !== cdmaBaseStationLongitude ||
- cell.cdmaSystemId !== cdmaSystemId ||
- cell.cdmaNetworkId !== cdmaNetworkId) {
- stateChanged = true;
- cell.cdmaBaseStationId = cdmaBaseStationId;
- cell.cdmaBaseStationLatitude = cdmaBaseStationLatitude;
- cell.cdmaBaseStationLongitude = cdmaBaseStationLongitude;
- cell.cdmaSystemId = cdmaSystemId;
- cell.cdmaNetworkId = cdmaNetworkId;
- }
- }
-
- if (stateChanged) {
- rs.rilMessageType = "voiceregistrationstatechange";
- this._sendNetworkInfoMessage(NETWORK_INFO_VOICE_REGISTRATION_STATE, rs);
- }
- },
-
- _processDataRegistrationState: function(state) {
- let rs = this.dataRegistrationState;
- let stateChanged = this._processCREG(rs, state);
- if (stateChanged) {
- rs.rilMessageType = "dataregistrationstatechange";
- this._sendNetworkInfoMessage(NETWORK_INFO_DATA_REGISTRATION_STATE, rs);
- }
- },
-
- _processOperator: function(operatorData) {
- if (operatorData.length < 3) {
- if (DEBUG) {
- this.context.debug("Expected at least 3 strings for operator.");
- }
- }
-
- if (!this.operator) {
- this.operator = {
- rilMessageType: "operatorchange",
- longName: null,
- shortName: null
- };
- }
-
- let [longName, shortName, networkTuple] = operatorData;
- let thisTuple = (this.operator.mcc || "") + (this.operator.mnc || "");
-
- if (this.operator.longName !== longName ||
- this.operator.shortName !== shortName ||
- thisTuple !== networkTuple) {
-
- this.operator.mcc = null;
- this.operator.mnc = null;
-
- if (networkTuple) {
- try {
- this._processNetworkTuple(networkTuple, this.operator);
- } catch (e) {
- if (DEBUG) this.context.debug("Error processing operator tuple: " + e);
- }
- } else {
- // According to ril.h, the operator fields will be NULL when the operator
- // is not currently registered. We can avoid trying to parse the numeric
- // tuple in that case.
- if (DEBUG) {
- this.context.debug("Operator is currently unregistered");
- }
- }
-
- this.operator.longName = longName;
- this.operator.shortName = shortName;
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- if (ICCUtilsHelper.updateDisplayCondition()) {
- ICCUtilsHelper.handleICCInfoChange();
- }
-
- // NETWORK_INFO_OPERATOR message will be sent out by overrideICCNetworkName
- // itself if operator name is overridden after checking, or we have to
- // do it by ourself.
- if (!this.overrideICCNetworkName()) {
- this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator);
- }
- }
- },
-
- _processSuppSvcNotification: function(info) {
- if (DEBUG) {
- this.context.debug("handle supp svc notification: " + JSON.stringify(info));
- }
-
- if (info.notificationType !== 1) {
- // We haven't supported MO intermediate result code, i.e.
- // info.notificationType === 0, which refers to code1 defined in 3GPP
- // 27.007 7.17. We only support partial MT unsolicited result code,
- // referring to code2, for now.
- return;
- }
-
- let notification = null;
-
- switch (info.code) {
- case SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD:
- case SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED:
- notification = GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2[info.code];
- break;
- default:
- // Notification type not supported.
- return;
- }
-
- let message = {rilMessageType: "suppSvcNotification",
- number: info.number, // could be empty.
- notification: notification};
- this.sendChromeMessage(message);
- },
-
- _cancelEmergencyCbModeTimeout: function() {
- if (this._exitEmergencyCbModeTimeoutID) {
- clearTimeout(this._exitEmergencyCbModeTimeoutID);
- this._exitEmergencyCbModeTimeoutID = null;
- }
- },
-
- _handleChangedEmergencyCbMode: function(active) {
- this._isInEmergencyCbMode = active;
-
- // Clear the existed timeout event.
- this._cancelEmergencyCbModeTimeout();
-
- // Start a new timeout event when entering the mode.
- if (active) {
- this._exitEmergencyCbModeTimeoutID = setTimeout(
- this.exitEmergencyCbMode.bind(this), EMERGENCY_CB_MODE_TIMEOUT_MS);
- }
-
- let message = {rilMessageType: "emergencyCbModeChange",
- active: active,
- timeoutMs: EMERGENCY_CB_MODE_TIMEOUT_MS};
- this.sendChromeMessage(message);
- },
-
- _updateNetworkSelectionMode: function(mode) {
- if (this.networkSelectionMode === mode) {
- return;
- }
-
- let options = {
- rilMessageType: "networkselectionmodechange",
- mode: mode
- };
- this.networkSelectionMode = mode;
- this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options);
- },
-
- _processNetworks: function() {
- let strings = this.context.Buf.readStringList();
- let networks = [];
-
- for (let i = 0; i < strings.length;
- i += RILQUIRKS_AVAILABLE_NETWORKS_EXTRA_STRING ? 5 : 4) {
- let network = {
- longName: strings[i],
- shortName: strings[i + 1],
- mcc: null,
- mnc: null,
- state: null
- };
-
- let networkTuple = strings[i + 2];
- try {
- this._processNetworkTuple(networkTuple, network);
- } catch (e) {
- if (DEBUG) this.context.debug("Error processing operator tuple: " + e);
- }
-
- let state = strings[i + 3];
- network.state = RIL_QAN_STATE_TO_GECKO_STATE[state];
-
- networks.push(network);
- }
- return networks;
- },
-
- /**
- * The "numeric" portion of the operator info is a tuple
- * containing MCC (country code) and MNC (network code).
- * AFAICT, MCC should always be 3 digits, making the remaining
- * portion the MNC.
- */
- _processNetworkTuple: function(networkTuple, network) {
- let tupleLen = networkTuple.length;
-
- if (tupleLen == 5 || tupleLen == 6) {
- network.mcc = networkTuple.substr(0, 3);
- network.mnc = networkTuple.substr(3);
- } else {
- network.mcc = null;
- network.mnc = null;
-
- throw new Error("Invalid network tuple (should be 5 or 6 digits): " + networkTuple);
- }
- },
-
- /**
- * Check if GSM radio access technology group.
- */
- _isGsmTechGroup: function(radioTech) {
- if (!radioTech) {
- return true;
- }
-
- switch(radioTech) {
- case NETWORK_CREG_TECH_GPRS:
- case NETWORK_CREG_TECH_EDGE:
- case NETWORK_CREG_TECH_UMTS:
- case NETWORK_CREG_TECH_HSDPA:
- case NETWORK_CREG_TECH_HSUPA:
- case NETWORK_CREG_TECH_HSPA:
- case NETWORK_CREG_TECH_LTE:
- case NETWORK_CREG_TECH_HSPAP:
- case NETWORK_CREG_TECH_GSM:
- case NETWORK_CREG_TECH_DCHSPAP_1:
- case NETWORK_CREG_TECH_DCHSPAP_2:
- return true;
- }
-
- return false;
- },
-
- /**
- * Process radio technology change.
- */
- _processRadioTech: function(radioTech) {
- let isCdma = !this._isGsmTechGroup(radioTech);
- this.radioTech = radioTech;
-
- if (DEBUG) {
- this.context.debug("Radio tech is set to: " + GECKO_RADIO_TECH[radioTech] +
- ", it is a " + (isCdma?"cdma":"gsm") + " technology");
- }
-
- // We should request SIM information when
- // 1. Radio state has been changed, so we are waiting for radioTech or
- // 2. isCdma is different from this._isCdma.
- if (this._waitingRadioTech || isCdma != this._isCdma) {
- this._isCdma = isCdma;
- this._waitingRadioTech = false;
- this.getICCStatus();
- }
- },
-
- /**
- * Helper for returning the TOA for the given dial string.
- */
- _toaFromString: function(number) {
- let toa = TOA_UNKNOWN;
- if (number && number.length > 0 && number[0] == '+') {
- toa = TOA_INTERNATIONAL;
- }
- return toa;
- },
-
- /**
- * @param message A decoded SMS-DELIVER message.
- *
- * @see 3GPP TS 31.111 section 7.1.1
- */
- dataDownloadViaSMSPP: function(message) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let options = {
- pid: message.pid,
- dcs: message.dcs,
- encoding: message.encoding,
- };
- Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, options);
-
- Buf.seekIncoming(-1 * (Buf.getCurrentParcelSize() - Buf.getReadAvailable()
- - 2 * Buf.UINT32_SIZE)); // Skip response_type & request_type.
- let messageStringLength = Buf.readInt32(); // In semi-octets
- let smscLength = GsmPDUHelper.readHexOctet(); // In octets, inclusive of TOA
- let tpduLength = (messageStringLength / 2) - (smscLength + 1); // In octets
-
- // Device identities: 4 bytes
- // Address: 0 or (2 + smscLength)
- // SMS TPDU: (2 or 3) + tpduLength
- let berLen = 4 +
- (smscLength ? (2 + smscLength) : 0) +
- (tpduLength <= 127 ? 2 : 3) + tpduLength; // In octets
-
- let parcelLength = (berLen <= 127 ? 2 : 3) + berLen; // In octets
- Buf.writeInt32(parcelLength * 2); // In semi-octets
-
- // Write a BER-TLV
- GsmPDUHelper.writeHexOctet(BER_SMS_PP_DOWNLOAD_TAG);
- if (berLen > 127) {
- GsmPDUHelper.writeHexOctet(0x81);
- }
- GsmPDUHelper.writeHexOctet(berLen);
-
- // Device Identifies-TLV
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(0x02);
- GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_NETWORK);
- GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_SIM);
-
- // Address-TLV
- if (smscLength) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ADDRESS);
- GsmPDUHelper.writeHexOctet(smscLength);
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * smscLength);
- }
-
- // SMS TPDU-TLV
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_SMS_TPDU |
- COMPREHENSIONTLV_FLAG_CR);
- if (tpduLength > 127) {
- GsmPDUHelper.writeHexOctet(0x81);
- }
- GsmPDUHelper.writeHexOctet(tpduLength);
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * tpduLength);
-
- // Write 2 string delimitors for the total string length must be even.
- Buf.writeStringDelimiter(0);
-
- Buf.sendParcel();
- },
-
- /**
- * @param success A boolean value indicating the result of previous
- * SMS-DELIVER message handling.
- * @param responsePduLen ICC IO response PDU length in octets.
- * @param options An object that contains four attributes: `pid`, `dcs`,
- * `encoding` and `responsePduLen`.
- *
- * @see 3GPP TS 23.040 section 9.2.2.1a
- */
- acknowledgeIncomingGsmSmsWithPDU: function(success, responsePduLen, options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- Buf.newParcel(REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU);
-
- // Two strings.
- Buf.writeInt32(2);
-
- // String 1: Success
- Buf.writeString(success ? "1" : "0");
-
- // String 2: RP-ACK/RP-ERROR PDU
- Buf.writeInt32(2 * (responsePduLen + (success ? 5 : 6))); // In semi-octet
- // 1. TP-MTI & TP-UDHI
- GsmPDUHelper.writeHexOctet(PDU_MTI_SMS_DELIVER);
- if (!success) {
- // 2. TP-FCS
- GsmPDUHelper.writeHexOctet(PDU_FCS_USIM_DATA_DOWNLOAD_ERROR);
- }
- // 3. TP-PI
- GsmPDUHelper.writeHexOctet(PDU_PI_USER_DATA_LENGTH |
- PDU_PI_DATA_CODING_SCHEME |
- PDU_PI_PROTOCOL_IDENTIFIER);
- // 4. TP-PID
- GsmPDUHelper.writeHexOctet(options.pid);
- // 5. TP-DCS
- GsmPDUHelper.writeHexOctet(options.dcs);
- // 6. TP-UDL
- if (options.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- GsmPDUHelper.writeHexOctet(Math.floor(responsePduLen * 8 / 7));
- } else {
- GsmPDUHelper.writeHexOctet(responsePduLen);
- }
- // TP-UD
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * responsePduLen);
- // Write 2 string delimitors for the total string length must be even.
- Buf.writeStringDelimiter(0);
-
- Buf.sendParcel();
- },
-
- /**
- * @param message A decoded SMS-DELIVER message.
- */
- writeSmsToSIM: function(message) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- Buf.newParcel(REQUEST_WRITE_SMS_TO_SIM);
-
- // Write EFsms Status
- Buf.writeInt32(EFSMS_STATUS_FREE);
-
- Buf.seekIncoming(-1 * (Buf.getCurrentParcelSize() - Buf.getReadAvailable()
- - 2 * Buf.UINT32_SIZE)); // Skip response_type & request_type.
- let messageStringLength = Buf.readInt32(); // In semi-octets
- let smscLength = GsmPDUHelper.readHexOctet(); // In octets, inclusive of TOA
- let pduLength = (messageStringLength / 2) - (smscLength + 1); // In octets
-
- // 1. Write PDU first.
- if (smscLength > 0) {
- Buf.seekIncoming(smscLength * Buf.PDU_HEX_OCTET_SIZE);
- }
- // Write EFsms PDU string length
- Buf.writeInt32(2 * pduLength); // In semi-octets
- if (pduLength) {
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * pduLength);
- }
- // Write 2 string delimitors for the total string length must be even.
- Buf.writeStringDelimiter(0);
-
- // 2. Write SMSC
- // Write EFsms SMSC string length
- Buf.writeInt32(2 * (smscLength + 1)); // Plus smscLength itself, in semi-octets
- // Write smscLength
- GsmPDUHelper.writeHexOctet(smscLength);
- // Write TOA & SMSC Address
- if (smscLength) {
- Buf.seekIncoming(-1 * (Buf.getCurrentParcelSize() - Buf.getReadAvailable()
- - 2 * Buf.UINT32_SIZE // Skip response_type, request_type.
- - 2 * Buf.PDU_HEX_OCTET_SIZE)); // Skip messageStringLength & smscLength.
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * smscLength);
- }
- // Write 2 string delimitors for the total string length must be even.
- Buf.writeStringDelimiter(0);
-
- Buf.sendParcel();
- },
-
- /**
- * Helper to delegate the received sms segment to RadioInterface to process.
- *
- * @param message
- * Received sms message.
- *
- * @return MOZ_FCS_WAIT_FOR_EXPLICIT_ACK
- */
- _processSmsMultipart: function(message) {
- message.rilMessageType = "sms-received";
-
- this.sendChromeMessage(message);
-
- return MOZ_FCS_WAIT_FOR_EXPLICIT_ACK;
- },
-
- /**
- * Helper for processing SMS-STATUS-REPORT PDUs.
- *
- * @param length
- * Length of SMS string in the incoming parcel.
- *
- * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
- */
- _processSmsStatusReport: function(length) {
- let [message, result] = this.context.GsmPDUHelper.processReceivedSms(length);
- if (!message) {
- if (DEBUG) this.context.debug("invalid SMS-STATUS-REPORT");
- return PDU_FCS_UNSPECIFIED;
- }
-
- let options = this._pendingSentSmsMap[message.messageRef];
- if (!options) {
- if (DEBUG) this.context.debug("no pending SMS-SUBMIT message");
- return PDU_FCS_OK;
- }
-
- let status = message.status;
-
- // 3GPP TS 23.040 9.2.3.15 `The MS shall interpret any reserved values as
- // "Service Rejected"(01100011) but shall store them exactly as received.`
- if ((status >= 0x80)
- || ((status >= PDU_ST_0_RESERVED_BEGIN)
- && (status < PDU_ST_0_SC_SPECIFIC_BEGIN))
- || ((status >= PDU_ST_1_RESERVED_BEGIN)
- && (status < PDU_ST_1_SC_SPECIFIC_BEGIN))
- || ((status >= PDU_ST_2_RESERVED_BEGIN)
- && (status < PDU_ST_2_SC_SPECIFIC_BEGIN))
- || ((status >= PDU_ST_3_RESERVED_BEGIN)
- && (status < PDU_ST_3_SC_SPECIFIC_BEGIN))
- ) {
- status = PDU_ST_3_SERVICE_REJECTED;
- }
-
- // Pending. Waiting for next status report.
- if ((status >>> 5) == 0x01) {
- if (DEBUG) this.context.debug("SMS-STATUS-REPORT: delivery still pending");
- return PDU_FCS_OK;
- }
-
- delete this._pendingSentSmsMap[message.messageRef];
-
- let deliveryStatus = ((status >>> 5) === 0x00)
- ? GECKO_SMS_DELIVERY_STATUS_SUCCESS
- : GECKO_SMS_DELIVERY_STATUS_ERROR;
- this.sendChromeMessage({
- rilMessageType: options.rilMessageType,
- rilMessageToken: options.rilMessageToken,
- deliveryStatus: deliveryStatus
- });
-
- return PDU_FCS_OK;
- },
-
- /**
- * Helper for processing CDMA SMS Delivery Acknowledgment Message
- *
- * @param message
- * decoded SMS Delivery ACK message from CdmaPDUHelper.
- *
- * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
- */
- _processCdmaSmsStatusReport: function(message) {
- let options = this._pendingSentSmsMap[message.msgId];
- if (!options) {
- if (DEBUG) this.context.debug("no pending SMS-SUBMIT message");
- return PDU_FCS_OK;
- }
-
- if (message.errorClass === 2) {
- if (DEBUG) {
- this.context.debug("SMS-STATUS-REPORT: delivery still pending, " +
- "msgStatus: " + message.msgStatus);
- }
- return PDU_FCS_OK;
- }
-
- delete this._pendingSentSmsMap[message.msgId];
-
- if (message.errorClass === -1 && message.body) {
- // Process as normal incoming SMS, if errorClass is invalid
- // but message body is available.
- return this._processSmsMultipart(message);
- }
-
- let deliveryStatus = (message.errorClass === 0)
- ? GECKO_SMS_DELIVERY_STATUS_SUCCESS
- : GECKO_SMS_DELIVERY_STATUS_ERROR;
- this.sendChromeMessage({
- rilMessageType: options.rilMessageType,
- rilMessageToken: options.rilMessageToken,
- deliveryStatus: deliveryStatus
- });
-
- return PDU_FCS_OK;
- },
-
- /**
- * Helper for processing CDMA SMS WAP Push Message
- *
- * @param message
- * decoded WAP message from CdmaPDUHelper.
- *
- * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
- */
- _processCdmaSmsWapPush: function(message) {
- if (!message.data) {
- if (DEBUG) this.context.debug("no data inside WAP Push message.");
- return PDU_FCS_OK;
- }
-
- // See 6.5. MAPPING OF WDP TO CDMA SMS in WAP-295-WDP.
- //
- // Field | Length (bits)
- // -----------------------------------------
- // MSG_TYPE | 8
- // TOTAL_SEGMENTS | 8
- // SEGMENT_NUMBER | 8
- // DATAGRAM | (NUM_FIELDS - 3) * 8
- let index = 0;
- if (message.data[index++] !== 0) {
- if (DEBUG) this.context.debug("Ignore a WAP Message which is not WDP.");
- return PDU_FCS_OK;
- }
-
- // 1. Originator Address in SMS-TL + Message_Id in SMS-TS are used to identify a unique WDP datagram.
- // 2. TOTAL_SEGMENTS, SEGMENT_NUMBER are used to verify that a complete
- // datagram has been received and is ready to be passed to a higher layer.
- message.header = {
- segmentRef: message.msgId,
- segmentMaxSeq: message.data[index++],
- segmentSeq: message.data[index++] + 1 // It's zero-based in CDMA WAP Push.
- };
-
- if (message.header.segmentSeq > message.header.segmentMaxSeq) {
- if (DEBUG) this.context.debug("Wrong WDP segment info.");
- return PDU_FCS_OK;
- }
-
- // Ports are only specified in 1st segment.
- if (message.header.segmentSeq == 1) {
- message.header.originatorPort = message.data[index++] << 8;
- message.header.originatorPort |= message.data[index++];
- message.header.destinationPort = message.data[index++] << 8;
- message.header.destinationPort |= message.data[index++];
- }
-
- message.data = message.data.subarray(index);
-
- return this._processSmsMultipart(message);
- },
-
- /**
- * Helper for processing sent multipart SMS.
- */
- _processSentSmsSegment: function(options) {
- // Setup attributes for sending next segment
- let next = options.segmentSeq;
- options.body = options.segments[next].body;
- options.encodedBodyLength = options.segments[next].encodedBodyLength;
- options.segmentSeq = next + 1;
-
- this.sendSMS(options);
- },
-
- /**
- * Helper for processing result of send SMS.
- *
- * @param length
- * Length of SMS string in the incoming parcel.
- * @param options
- * Sms information.
- */
- _processSmsSendResult: function(length, options) {
- if (options.errorMsg) {
- if (DEBUG) {
- this.context.debug("_processSmsSendResult: errorMsg = " +
- options.errorMsg);
- }
-
- this.sendChromeMessage({
- rilMessageType: options.rilMessageType,
- rilMessageToken: options.rilMessageToken,
- errorMsg: options.errorMsg,
- });
- return;
- }
-
- let Buf = this.context.Buf;
- options.messageRef = Buf.readInt32();
- options.ackPDU = Buf.readString();
- options.errorCode = Buf.readInt32();
-
- if ((options.segmentMaxSeq > 1)
- && (options.segmentSeq < options.segmentMaxSeq)) {
- // Not last segment
- this._processSentSmsSegment(options);
- } else {
- // Last segment sent with success.
- if (options.requestStatusReport) {
- if (DEBUG) {
- this.context.debug("waiting SMS-STATUS-REPORT for messageRef " +
- options.messageRef);
- }
- this._pendingSentSmsMap[options.messageRef] = options;
- }
-
- this.sendChromeMessage({
- rilMessageType: options.rilMessageType,
- rilMessageToken: options.rilMessageToken,
- });
- }
- },
-
- _processReceivedSmsCbPage: function(original) {
- if (original.numPages <= 1) {
- if (original.body) {
- original.fullBody = original.body;
- delete original.body;
- } else if (original.data) {
- original.fullData = original.data;
- delete original.data;
- }
- return original;
- }
-
- // Hash = <serial>:<mcc>:<mnc>:<lac>:<cid>
- let hash = original.serial + ":" + this.iccInfo.mcc + ":"
- + this.iccInfo.mnc + ":";
- switch (original.geographicalScope) {
- case CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE:
- case CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE:
- hash += this.voiceRegistrationState.cell.gsmLocationAreaCode + ":"
- + this.voiceRegistrationState.cell.gsmCellId;
- break;
- case CB_GSM_GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE:
- hash += this.voiceRegistrationState.cell.gsmLocationAreaCode + ":";
- break;
- default:
- hash += ":";
- break;
- }
-
- let index = original.pageIndex;
-
- let options = this._receivedSmsCbPagesMap[hash];
- if (!options) {
- options = original;
- this._receivedSmsCbPagesMap[hash] = options;
-
- options.receivedPages = 0;
- options.pages = [];
- } else if (options.pages[index]) {
- // Duplicated page?
- if (DEBUG) {
- this.context.debug("Got duplicated page no." + index +
- " of a multipage SMSCB: " + JSON.stringify(original));
- }
- return null;
- }
-
- if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
- options.pages[index] = original.data;
- delete original.data;
- } else {
- options.pages[index] = original.body;
- delete original.body;
- }
- options.receivedPages++;
- if (options.receivedPages < options.numPages) {
- if (DEBUG) {
- this.context.debug("Got page no." + index + " of a multipage SMSCB: " +
- JSON.stringify(options));
- }
- return null;
- }
-
- // Remove from map
- delete this._receivedSmsCbPagesMap[hash];
-
- // Rebuild full body
- if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
- // Uint8Array doesn't have `concat`, so we have to merge all pages by hand.
- let fullDataLen = 0;
- for (let i = 1; i <= options.numPages; i++) {
- fullDataLen += options.pages[i].length;
- }
-
- options.fullData = new Uint8Array(fullDataLen);
- for (let d= 0, i = 1; i <= options.numPages; i++) {
- let data = options.pages[i];
- for (let j = 0; j < data.length; j++) {
- options.fullData[d++] = data[j];
- }
- }
- } else {
- options.fullBody = options.pages.join("");
- }
-
- if (DEBUG) {
- this.context.debug("Got full multipage SMSCB: " + JSON.stringify(options));
- }
-
- return options;
- },
-
- _mergeCellBroadcastConfigs: function(list, from, to) {
- if (!list) {
- return [from, to];
- }
-
- for (let i = 0, f1, t1; i < list.length;) {
- f1 = list[i++];
- t1 = list[i++];
- if (to == f1) {
- // ...[from]...[to|f1]...(t1)
- list[i - 2] = from;
- return list;
- }
-
- if (to < f1) {
- // ...[from]...(to)...[f1] or ...[from]...(to)[f1]
- if (i > 2) {
- // Not the first range pair, merge three arrays.
- return list.slice(0, i - 2).concat([from, to]).concat(list.slice(i - 2));
- } else {
- return [from, to].concat(list);
- }
- }
-
- if (from > t1) {
- // ...[f1]...(t1)[from] or ...[f1]...(t1)...[from]
- continue;
- }
-
- // Have overlap or merge-able adjacency with [f1]...(t1). Replace it
- // with [min(from, f1)]...(max(to, t1)).
-
- let changed = false;
- if (from < f1) {
- // [from]...[f1]...(t1) or [from][f1]...(t1)
- // Save minimum from value.
- list[i - 2] = from;
- changed = true;
- }
-
- if (to <= t1) {
- // [from]...[to](t1) or [from]...(to|t1)
- // Can't have further merge-able adjacency. Return.
- return list;
- }
-
- // Try merging possible next adjacent range.
- let j = i;
- for (let f2, t2; j < list.length;) {
- f2 = list[j++];
- t2 = list[j++];
- if (to > t2) {
- // [from]...[f2]...[t2]...(to) or [from]...[f2]...[t2](to)
- // Merge next adjacent range again.
- continue;
- }
-
- if (to < t2) {
- if (to < f2) {
- // [from]...(to)[f2] or [from]...(to)...[f2]
- // Roll back and give up.
- j -= 2;
- } else if (to < t2) {
- // [from]...[to|f2]...(t2), or [from]...[f2]...[to](t2)
- // Merge to [from]...(t2) and give up.
- to = t2;
- }
- }
-
- break;
- }
-
- // Save maximum to value.
- list[i - 1] = to;
-
- if (j != i) {
- // Remove merged adjacent ranges.
- let ret = list.slice(0, i);
- if (j < list.length) {
- ret = ret.concat(list.slice(j));
- }
- return ret;
- }
-
- return list;
- }
-
- // Append to the end.
- list.push(from);
- list.push(to);
-
- return list;
- },
-
- _isCellBroadcastConfigReady: function() {
- if (!("MMI" in this.cellBroadcastConfigs)) {
- return false;
- }
-
- // CBMI should be ready in GSM.
- if (!this._isCdma &&
- (!("CBMI" in this.cellBroadcastConfigs) ||
- !("CBMID" in this.cellBroadcastConfigs) ||
- !("CBMIR" in this.cellBroadcastConfigs))) {
- return false;
- }
-
- return true;
- },
-
- /**
- * Merge all members of cellBroadcastConfigs into mergedCellBroadcastConfig.
- */
- _mergeAllCellBroadcastConfigs: function() {
- if (!this._isCellBroadcastConfigReady()) {
- if (DEBUG) {
- this.context.debug("cell broadcast configs not ready, waiting ...");
- }
- return;
- }
-
- // Prepare cell broadcast config. CBMI* are only used in GSM.
- let usedCellBroadcastConfigs = {MMI: this.cellBroadcastConfigs.MMI};
- if (!this._isCdma) {
- usedCellBroadcastConfigs.CBMI = this.cellBroadcastConfigs.CBMI;
- usedCellBroadcastConfigs.CBMID = this.cellBroadcastConfigs.CBMID;
- usedCellBroadcastConfigs.CBMIR = this.cellBroadcastConfigs.CBMIR;
- }
-
- if (DEBUG) {
- this.context.debug("Cell Broadcast search lists: " +
- JSON.stringify(usedCellBroadcastConfigs));
- }
-
- let list = null;
- for (let key in usedCellBroadcastConfigs) {
- let ll = usedCellBroadcastConfigs[key];
- if (ll == null) {
- continue;
- }
-
- for (let i = 0; i < ll.length; i += 2) {
- list = this._mergeCellBroadcastConfigs(list, ll[i], ll[i + 1]);
- }
- }
-
- if (DEBUG) {
- this.context.debug("Cell Broadcast search lists(merged): " +
- JSON.stringify(list));
- }
- this.mergedCellBroadcastConfig = list;
- this.updateCellBroadcastConfig();
- },
-
- /**
- * Check whether search list from settings is settable by MMI, that is,
- * whether the range is bounded in any entries of CB_NON_MMI_SETTABLE_RANGES.
- */
- _checkCellBroadcastMMISettable: function(from, to) {
- if ((to <= from) || (from >= 65536) || (from < 0)) {
- return false;
- }
-
- if (!this._isCdma) {
- // GSM not settable ranges.
- for (let i = 0, f, t; i < CB_NON_MMI_SETTABLE_RANGES.length;) {
- f = CB_NON_MMI_SETTABLE_RANGES[i++];
- t = CB_NON_MMI_SETTABLE_RANGES[i++];
- if ((from < t) && (to > f)) {
- // Have overlap.
- return false;
- }
- }
- }
-
- return true;
- },
-
- /**
- * Convert Cell Broadcast settings string into search list.
- */
- _convertCellBroadcastSearchList: function(searchListStr) {
- let parts = searchListStr && searchListStr.split(",");
- if (!parts) {
- return null;
- }
-
- let list = null;
- let result, from, to;
- for (let range of parts) {
- // Match "12" or "12-34". The result will be ["12", "12", null] or
- // ["12-34", "12", "34"].
- result = range.match(/^(\d+)(?:-(\d+))?$/);
- if (!result) {
- throw "Invalid format";
- }
-
- from = parseInt(result[1], 10);
- to = (result[2]) ? parseInt(result[2], 10) + 1 : from + 1;
- if (!this._checkCellBroadcastMMISettable(from, to)) {
- throw "Invalid range";
- }
-
- if (list == null) {
- list = [];
- }
- list.push(from);
- list.push(to);
- }
-
- return list;
- },
-
- /**
- * Handle incoming messages from the main UI thread.
- *
- * @param message
- * Object containing the message. Messages are supposed
- */
- handleChromeMessage: function(message) {
- if (DEBUG) {
- this.context.debug("Received chrome message " + JSON.stringify(message));
- }
- let method = this[message.rilMessageType];
- if (typeof method != "function") {
- if (DEBUG) {
- this.context.debug("Don't know what to do with message " +
- JSON.stringify(message));
- }
- return;
- }
- method.call(this, message);
- },
-
- /**
- * Process STK Proactive Command.
- */
- processStkProactiveCommand: function() {
- let Buf = this.context.Buf;
- let length = Buf.readInt32();
- let berTlv;
- try {
- berTlv = this.context.BerTlvHelper.decode(length / 2);
- } catch (e) {
- if (DEBUG) this.context.debug("processStkProactiveCommand : " + e);
- this.sendStkTerminalResponse({
- resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
- return;
- }
-
- Buf.readStringDelimiter(length);
-
- let ctlvs = berTlv.value;
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
- if (!ctlv) {
- this.sendStkTerminalResponse({
- resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
- throw new Error("Can't find COMMAND_DETAILS ComprehensionTlv");
- }
-
- let cmdDetails = ctlv.value;
- if (DEBUG) {
- this.context.debug("commandNumber = " + cmdDetails.commandNumber +
- " typeOfCommand = " + cmdDetails.typeOfCommand.toString(16) +
- " commandQualifier = " + cmdDetails.commandQualifier);
- }
-
- // STK_CMD_MORE_TIME need not to propagate event to chrome.
- if (cmdDetails.typeOfCommand == STK_CMD_MORE_TIME) {
- this.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_OK});
- return;
- }
-
- this.context.StkCommandParamsFactory.createParam(cmdDetails,
- ctlvs,
- (aResult) => {
- cmdDetails.options = aResult;
- cmdDetails.rilMessageType = "stkcommand";
- this.sendChromeMessage(cmdDetails);
- });
- },
-
- sendDefaultResponse: function(options) {
- if (!options.rilMessageType) {
- return;
- }
-
- this.sendChromeMessage(options);
- },
-
- /**
- * Send messages to the main thread.
- */
- sendChromeMessage: function(message) {
- message.rilMessageClientId = this.context.clientId;
- postMessage(message);
- },
-
- /**
- * Handle incoming requests from the RIL. We find the method that
- * corresponds to the request type. Incidentally, the request type
- * _is_ the method name, so that's easy.
- */
-
- handleParcel: function(request_type, length, options) {
- let method = this[request_type];
- if (typeof method == "function") {
- if (DEBUG) this.context.debug("Handling parcel as " + method.name);
- method.call(this, length, options);
- }
-
- if (this.telephonyRequestQueue.isValidRequest(request_type)) {
- this.telephonyRequestQueue.pop(request_type);
- }
- }
-};
-
-RilObject.prototype[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
- if (options.errorMsg) {
- return;
- }
-
- let iccStatus = {};
- let Buf = this.context.Buf;
- iccStatus.cardState = Buf.readInt32(); // CARD_STATE_*
- iccStatus.universalPINState = Buf.readInt32(); // CARD_PINSTATE_*
- iccStatus.gsmUmtsSubscriptionAppIndex = Buf.readInt32();
- iccStatus.cdmaSubscriptionAppIndex = Buf.readInt32();
- iccStatus.imsSubscriptionAppIndex = Buf.readInt32();
-
- let apps_length = Buf.readInt32();
- if (apps_length > CARD_MAX_APPS) {
- apps_length = CARD_MAX_APPS;
- }
-
- iccStatus.apps = [];
- for (let i = 0 ; i < apps_length ; i++) {
- iccStatus.apps.push({
- app_type: Buf.readInt32(), // CARD_APPTYPE_*
- app_state: Buf.readInt32(), // CARD_APPSTATE_*
- perso_substate: Buf.readInt32(), // CARD_PERSOSUBSTATE_*
- aid: Buf.readString(),
- app_label: Buf.readString(),
- pin1_replaced: Buf.readInt32(),
- pin1: Buf.readInt32(),
- pin2: Buf.readInt32()
- });
- if (RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS) {
- Buf.readInt32();
- Buf.readInt32();
- Buf.readInt32();
- Buf.readInt32();
- }
- }
-
- if (DEBUG) this.context.debug("iccStatus: " + JSON.stringify(iccStatus));
- this._processICCStatus(iccStatus);
-};
-RilObject.prototype[REQUEST_ENTER_SIM_PIN] = function REQUEST_ENTER_SIM_PIN(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_ENTER_SIM_PUK] = function REQUEST_ENTER_SIM_PUK(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_ENTER_SIM_PIN2] = function REQUEST_ENTER_SIM_PIN2(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_ENTER_SIM_PUK2] = function REQUEST_ENTER_SIM_PUK(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_CHANGE_SIM_PIN2] = function REQUEST_CHANGE_SIM_PIN2(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE] =
- function REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, options) {
- // Retry getCurrentCalls several times when error occurs.
- if (options.errorMsg) {
- if (this._getCurrentCallsRetryCount < GET_CURRENT_CALLS_RETRY_MAX) {
- this._getCurrentCallsRetryCount++;
- this.getCurrentCalls(options);
- } else {
- this.sendDefaultResponse(options);
- }
- return;
- }
-
- this._getCurrentCallsRetryCount = 0;
-
- let Buf = this.context.Buf;
- let calls_length = 0;
- // The RIL won't even send us the length integer if there are no active calls.
- // So only read this integer if the parcel actually has it.
- if (length) {
- calls_length = Buf.readInt32();
- }
-
- let calls = {};
- for (let i = 0; i < calls_length; i++) {
- let call = {};
-
- // Extra uint32 field to get correct callIndex and rest of call data for
- // call waiting feature.
- if (RILQUIRKS_EXTRA_UINT32_2ND_CALL && i > 0) {
- Buf.readInt32();
- }
-
- call.state = Buf.readInt32(); // CALL_STATE_*
- call.callIndex = Buf.readInt32(); // GSM index (1-based)
- call.toa = Buf.readInt32();
- call.isMpty = Boolean(Buf.readInt32());
- call.isMT = Boolean(Buf.readInt32());
- call.als = Buf.readInt32();
- call.isVoice = Boolean(Buf.readInt32());
- call.isVoicePrivacy = Boolean(Buf.readInt32());
- if (RILQUIRKS_CALLSTATE_EXTRA_UINT32) {
- Buf.readInt32();
- }
- call.number = Buf.readString();
- call.numberPresentation = Buf.readInt32(); // CALL_PRESENTATION_*
- call.name = Buf.readString();
- call.namePresentation = Buf.readInt32();
-
- call.uusInfo = null;
- let uusInfoPresent = Buf.readInt32();
- if (uusInfoPresent == 1) {
- call.uusInfo = {
- type: Buf.readInt32(),
- dcs: Buf.readInt32(),
- userData: null //XXX TODO byte array?!?
- };
- }
-
- if (call.isVoice) {
- calls[call.callIndex] = call;
- }
- }
-
- options.calls = calls;
- options.rilMessageType = options.rilMessageType || "currentCalls";
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_DIAL] = function REQUEST_DIAL(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_DIAL_EMERGENCY_CALL] = function REQUEST_DIAL_EMERGENCY_CALL(length, options) {
- RilObject.prototype[REQUEST_DIAL].call(this, length, options);
-};
-RilObject.prototype[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
- if (options.errorMsg) {
- return;
- }
-
- this.iccInfoPrivate.imsi = this.context.Buf.readString();
- if (DEBUG) {
- this.context.debug("IMSI: " + this.iccInfoPrivate.imsi);
- }
-
- options.rilMessageType = "iccimsi";
- options.imsi = this.iccInfoPrivate.imsi;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_HANGUP_WAITING_OR_BACKGROUND] = function REQUEST_HANGUP_WAITING_OR_BACKGROUND(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = function REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_UDUB] = function REQUEST_UDUB(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
- // Treat it as CALL_FAIL_ERROR_UNSPECIFIED if the request failed.
- let failCause = CALL_FAIL_ERROR_UNSPECIFIED;
-
- if (!options.errorMsg) {
- let Buf = this.context.Buf;
- let num = length ? Buf.readInt32() : 0;
-
- if (num) {
- let causeNum = Buf.readInt32();
- failCause = RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[causeNum] || failCause;
- }
- if (DEBUG) this.context.debug("Last call fail cause: " + failCause);
- }
-
- options.failCause = failCause;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_SIGNAL);
-
- if (options.errorMsg) {
- return;
- }
-
- let Buf = this.context.Buf;
- let signal = {};
-
- signal.gsmSignalStrength = Buf.readInt32();
- signal.gsmBitErrorRate = Buf.readInt32();
- if (RILQUIRKS_SIGNAL_EXTRA_INT32) {
- Buf.readInt32();
- }
- signal.cdmaDBM = Buf.readInt32();
- signal.cdmaECIO = Buf.readInt32();
- signal.evdoDBM = Buf.readInt32();
- signal.evdoECIO = Buf.readInt32();
- signal.evdoSNR = Buf.readInt32();
-
- signal.lteSignalStrength = Buf.readInt32();
- signal.lteRSRP = Buf.readInt32();
- signal.lteRSRQ = Buf.readInt32();
- signal.lteRSSNR = Buf.readInt32();
- signal.lteCQI = Buf.readInt32();
-
- if (DEBUG) this.context.debug("signal strength: " + JSON.stringify(signal));
-
- this._processSignalStrength(signal);
-};
-RilObject.prototype[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_VOICE_REGISTRATION_STATE);
-
- if (options.errorMsg) {
- return;
- }
-
- let state = this.context.Buf.readStringList();
- if (DEBUG) this.context.debug("voice registration state: " + state);
-
- this._processVoiceRegistrationState(state);
-};
-RilObject.prototype[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_DATA_REGISTRATION_STATE);
-
- if (options.errorMsg) {
- return;
- }
-
- let state = this.context.Buf.readStringList();
- this._processDataRegistrationState(state);
-};
-RilObject.prototype[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_OPERATOR);
-
- if (options.errorMsg) {
- return;
- }
-
- let operatorData = this.context.Buf.readStringList();
- if (DEBUG) this.context.debug("Operator: " + operatorData);
- this._processOperator(operatorData);
-};
-RilObject.prototype[REQUEST_RADIO_POWER] = function REQUEST_RADIO_POWER(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_DTMF] = null;
-RilObject.prototype[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) {
- this._processSmsSendResult(length, options);
-};
-RilObject.prototype[REQUEST_SEND_SMS_EXPECT_MORE] = null;
-
-RilObject.prototype[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let version = Buf.readInt32();
- // Skip number of data calls.
- Buf.readInt32();
-
- this.readDataCall(options, version);
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
- if (options.errorMsg) {
- if (options.onerror) {
- options.onerror(options.errorMsg);
- }
- return;
- }
-
- let Buf = this.context.Buf;
- options.sw1 = Buf.readInt32();
- options.sw2 = Buf.readInt32();
-
- // See 3GPP TS 11.11, clause 9.4.1 for operation success results.
- if (options.sw1 !== ICC_STATUS_NORMAL_ENDING &&
- options.sw1 !== ICC_STATUS_NORMAL_ENDING_WITH_EXTRA &&
- options.sw1 !== ICC_STATUS_WITH_SIM_DATA &&
- options.sw1 !== ICC_STATUS_WITH_RESPONSE_DATA) {
- if (DEBUG) {
- this.context.debug("ICC I/O Error EF id = 0x" + options.fileId.toString(16) +
- ", command = 0x" + options.command.toString(16) +
- ", sw1 = 0x" + options.sw1.toString(16) +
- ", sw2 = 0x" + options.sw2.toString(16));
- }
- if (options.onerror) {
- // We can get fail cause from sw1/sw2 (See TS 11.11 clause 9.4.1 and
- // ISO 7816-4 clause 6). But currently no one needs this information,
- // so simply reports "GenericFailure" for now.
- options.onerror(GECKO_ERROR_GENERIC_FAILURE);
- }
- return;
- }
- this.context.ICCIOHelper.processICCIO(options);
-};
-RilObject.prototype[REQUEST_SEND_USSD] = function REQUEST_SEND_USSD(length, options) {
- if (DEBUG) {
- this.context.debug("REQUEST_SEND_USSD " + JSON.stringify(options));
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) {
- if (DEBUG) {
- this.context.debug("REQUEST_CANCEL_USSD" + JSON.stringify(options));
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_CLIR] = function REQUEST_GET_CLIR(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let bufLength = Buf.readInt32();
- if (!bufLength || bufLength < 2) {
- options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
- this.sendChromeMessage(options);
- return;
- }
-
- options.n = Buf.readInt32(); // Will be TS 27.007 +CLIR parameter 'n'.
- options.m = Buf.readInt32(); // Will be TS 27.007 +CLIR parameter 'm'.
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_CLIR] = function REQUEST_SET_CLIR(length, options) {
- if (options.rilMessageType == null) {
- // The request was made by ril_worker itself automatically. Don't report.
- return;
- }
-
- this.sendChromeMessage(options);
-};
-
-RilObject.prototype[REQUEST_QUERY_CALL_FORWARD_STATUS] =
- function REQUEST_QUERY_CALL_FORWARD_STATUS(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let rulesLength = 0;
- if (length) {
- rulesLength = Buf.readInt32();
- }
- if (!rulesLength) {
- options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
- this.sendChromeMessage(options);
- return;
- }
- let rules = new Array(rulesLength);
- for (let i = 0; i < rulesLength; i++) {
- let rule = {};
- rule.active = Buf.readInt32() == 1; // CALL_FORWARD_STATUS_*
- rule.reason = Buf.readInt32(); // CALL_FORWARD_REASON_*
- rule.serviceClass = Buf.readInt32();
- rule.toa = Buf.readInt32();
- rule.number = Buf.readString();
- rule.timeSeconds = Buf.readInt32();
- rules[i] = rule;
- }
- options.rules = rules;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_CALL_FORWARD] =
- function REQUEST_SET_CALL_FORWARD(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_QUERY_CALL_WAITING] =
- function REQUEST_QUERY_CALL_WAITING(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let results = Buf.readInt32List();
- let enabled = (results[0] === 1);
- options.serviceClass = enabled ? results[1] : ICC_SERVICE_CLASS_NONE;
- this.sendChromeMessage(options);
-};
-
-RilObject.prototype[REQUEST_SET_CALL_WAITING] = function REQUEST_SET_CALL_WAITING(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SMS_ACKNOWLEDGE] = null;
-RilObject.prototype[REQUEST_GET_IMEI] = null;
-RilObject.prototype[REQUEST_GET_IMEISV] = null;
-RilObject.prototype[REQUEST_ANSWER] = function REQUEST_ANSWER(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- if (!length) {
- options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
- this.sendChromeMessage(options);
- return;
- }
-
- // Buf.readInt32List()[0] for Call Barring is a bit vector of services.
- options.serviceClass = this.context.Buf.readInt32List()[0];
- if (options.queryServiceClass) {
- options.enabled = (options.serviceClass & options.queryServiceClass) ? true : false;
- options.serviceClass = options.queryServiceClass;
- } else {
- options.enabled = options.serviceClass ? true : false;
- }
-
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_FACILITY_LOCK] = function REQUEST_SET_FACILITY_LOCK(length, options) {
- options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CHANGE_BARRING_PASSWORD] =
- function REQUEST_CHANGE_BARRING_PASSWORD(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELECTION_MODE(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_NETWORK_SELECTION_MODE);
-
- if (options.errorMsg) {
- return;
- }
-
- let mode = this.context.Buf.readInt32List();
- let selectionMode;
-
- switch (mode[0]) {
- case NETWORK_SELECTION_MODE_AUTOMATIC:
- selectionMode = GECKO_NETWORK_SELECTION_AUTOMATIC;
- break;
- case NETWORK_SELECTION_MODE_MANUAL:
- selectionMode = GECKO_NETWORK_SELECTION_MANUAL;
- break;
- default:
- selectionMode = GECKO_NETWORK_SELECTION_UNKNOWN;
- break;
- }
-
- this._updateNetworkSelectionMode(selectionMode);
-};
-RilObject.prototype[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = function REQUEST_SET_NETWORK_SELECTION_AUTOMATIC(length, options) {
- if (!options.errorMsg) {
- this._updateNetworkSelectionMode(GECKO_NETWORK_SELECTION_AUTOMATIC);
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_NETWORK_SELECTION_MANUAL] = function REQUEST_SET_NETWORK_SELECTION_MANUAL(length, options) {
- if (!options.errorMsg) {
- this._updateNetworkSelectionMode(GECKO_NETWORK_SELECTION_MANUAL);
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_QUERY_AVAILABLE_NETWORKS] = function REQUEST_QUERY_AVAILABLE_NETWORKS(length, options) {
- if (!options.errorMsg) {
- options.networks = this._processNetworks();
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_DTMF_START] = function REQUEST_DTMF_START(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_DTMF_STOP] = null;
-RilObject.prototype[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSION(length, options) {
- if (options.errorMsg) {
- return;
- }
-
- this.basebandVersion = this.context.Buf.readString();
- if (DEBUG) this.context.debug("Baseband version: " + this.basebandVersion);
-};
-RilObject.prototype[REQUEST_SEPARATE_CONNECTION] = function REQUEST_SEPARATE_CONNECTION(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_SET_MUTE] = null;
-RilObject.prototype[REQUEST_GET_MUTE] = null;
-RilObject.prototype[REQUEST_QUERY_CLIP] = function REQUEST_QUERY_CLIP(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let bufLength = Buf.readInt32();
- if (!bufLength) {
- options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
- this.sendChromeMessage(options);
- return;
- }
-
- options.provisioned = Buf.readInt32();
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
-
-/**
- * V6:
- * # addresses - A space-delimited list of addresses with optional "/" prefix
- * length.
- * # dnses - A space-delimited list of DNS server addresses.
- * # gateways - A space-delimited list of default gateway addresses.
- *
- * V10:
- * # pcscf - A space-delimited list of Proxy Call State Control Function
- * addresses.
- */
-
-RilObject.prototype.readDataCall = function(options, version) {
- if (!options) {
- options = {};
- }
- let Buf = this.context.Buf;
- options.failCause = Buf.readInt32(); // DATACALL_FAIL_*
- options.suggestedRetryTime = Buf.readInt32();
- options.cid = Buf.readInt32().toString();
- options.active = Buf.readInt32(); // DATACALL_ACTIVE_*
- options.type = Buf.readString();
- options.ifname = Buf.readString();
- options.addresses = Buf.readString();
- options.dnses = Buf.readString();
- options.gateways = Buf.readString();
-
- if (version >= 10) {
- options.pcscf = Buf.readString();
- }
-
- if (version >= 11) {
- let mtu = Buf.readInt32();
- options.mtu = (mtu > 0) ? mtu : -1 ;
- }
-
- return options;
-};
-
-RilObject.prototype[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length, options) {
- if (options.errorMsg) {
- if (options.rilMessageType) {
- this.sendChromeMessage(options);
- }
- return;
- }
-
- if (!options.rilMessageType) {
- // This is an unsolicited data call list changed.
- options.rilMessageType = "datacalllistchanged";
- }
-
- if (!length) {
- options.datacalls = [];
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let version = Buf.readInt32();
- let num = Buf.readInt32();
- let datacalls = [];
- for (let i = 0; i < num; i++) {
- let datacall;
- datacall = this.readDataCall({}, version);
- datacalls.push(datacall);
- }
-
- options.datacalls = datacalls;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_RESET_RADIO] = null;
-RilObject.prototype[REQUEST_OEM_HOOK_RAW] = null;
-RilObject.prototype[REQUEST_OEM_HOOK_STRINGS] = null;
-RilObject.prototype[REQUEST_SCREEN_STATE] = null;
-RilObject.prototype[REQUEST_SET_SUPP_SVC_NOTIFICATION] = null;
-RilObject.prototype[REQUEST_WRITE_SMS_TO_SIM] = function REQUEST_WRITE_SMS_TO_SIM(length, options) {
- if (options.errorMsg) {
- // `The MS shall return a "protocol error, unspecified" error message if
- // the short message cannot be stored in the (U)SIM, and there is other
- // message storage available at the MS` ~ 3GPP TS 23.038 section 4. Here
- // we assume we always have indexed db as another storage.
- this.acknowledgeGsmSms(false, PDU_FCS_PROTOCOL_ERROR);
- } else {
- this.acknowledgeGsmSms(true, PDU_FCS_OK);
- }
-};
-RilObject.prototype[REQUEST_DELETE_SMS_ON_SIM] = null;
-RilObject.prototype[REQUEST_SET_BAND_MODE] = null;
-RilObject.prototype[REQUEST_QUERY_AVAILABLE_BAND_MODE] = null;
-RilObject.prototype[REQUEST_STK_GET_PROFILE] = null;
-RilObject.prototype[REQUEST_STK_SET_PROFILE] = null;
-RilObject.prototype[REQUEST_STK_SEND_ENVELOPE_COMMAND] = null;
-RilObject.prototype[REQUEST_STK_SEND_TERMINAL_RESPONSE] = null;
-RilObject.prototype[REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM] = null;
-RilObject.prototype[REQUEST_EXPLICIT_CALL_TRANSFER] = null;
-RilObject.prototype[REQUEST_SET_PREFERRED_NETWORK_TYPE] = function REQUEST_SET_PREFERRED_NETWORK_TYPE(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_PREFERRED_NETWORK_TYPE] = function REQUEST_GET_PREFERRED_NETWORK_TYPE(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- options.type = this.context.Buf.readInt32List()[0];
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_NEIGHBORING_CELL_IDS] = function REQUEST_GET_NEIGHBORING_CELL_IDS(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let radioTech = this.voiceRegistrationState.radioTech;
- if (radioTech == undefined || radioTech == NETWORK_CREG_TECH_UNKNOWN) {
- options.errorMsg = "RadioTechUnavailable";
- this.sendChromeMessage(options);
- return;
- }
- if (!this._isGsmTechGroup(radioTech) || radioTech == NETWORK_CREG_TECH_LTE) {
- options.errorMsg = "UnsupportedRadioTech";
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let neighboringCellIds = [];
- let num = Buf.readInt32();
-
- for (let i = 0; i < num; i++) {
- let cellId = {};
- cellId.networkType = GECKO_RADIO_TECH[radioTech];
- cellId.signalStrength = Buf.readInt32();
-
- let cid = Buf.readString();
- // pad cid string with leading "0"
- let length = cid.length;
- if (length > 8) {
- continue;
- }
- if (length < 8) {
- for (let j = 0; j < (8-length); j++) {
- cid = "0" + cid;
- }
- }
-
- switch (radioTech) {
- case NETWORK_CREG_TECH_GPRS:
- case NETWORK_CREG_TECH_EDGE:
- case NETWORK_CREG_TECH_GSM:
- cellId.gsmCellId = this.parseInt(cid.substring(4), -1, 16);
- cellId.gsmLocationAreaCode = this.parseInt(cid.substring(0, 4), -1, 16);
- break;
- case NETWORK_CREG_TECH_UMTS:
- case NETWORK_CREG_TECH_HSDPA:
- case NETWORK_CREG_TECH_HSUPA:
- case NETWORK_CREG_TECH_HSPA:
- case NETWORK_CREG_TECH_HSPAP:
- case NETWORK_CREG_TECH_DCHSPAP_1:
- case NETWORK_CREG_TECH_DCHSPAP_2:
- cellId.wcdmaPsc = this.parseInt(cid, -1, 16);
- break;
- }
-
- neighboringCellIds.push(cellId);
- }
-
- options.result = neighboringCellIds;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_CELL_INFO_LIST] = function REQUEST_GET_CELL_INFO_LIST(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let cellInfoList = [];
- let num = Buf.readInt32();
- for (let i = 0; i < num; i++) {
- let cellInfo = {};
- cellInfo.type = Buf.readInt32();
- cellInfo.registered = Buf.readInt32() ? true : false;
- cellInfo.timestampType = Buf.readInt32();
- cellInfo.timestamp = Buf.readInt64();
-
- switch(cellInfo.type) {
- case CELL_INFO_TYPE_GSM:
- case CELL_INFO_TYPE_WCDMA:
- cellInfo.mcc = Buf.readInt32();
- cellInfo.mnc = Buf.readInt32();
- cellInfo.lac = Buf.readInt32();
- cellInfo.cid = Buf.readInt32();
- if (cellInfo.type == CELL_INFO_TYPE_WCDMA) {
- cellInfo.psc = Buf.readInt32();
- }
- cellInfo.signalStrength = Buf.readInt32();
- cellInfo.bitErrorRate = Buf.readInt32();
- break;
- case CELL_INFO_TYPE_CDMA:
- cellInfo.networkId = Buf.readInt32();
- cellInfo.systemId = Buf.readInt32();
- cellInfo.basestationId = Buf.readInt32();
- cellInfo.longitude = Buf.readInt32();
- cellInfo.latitude = Buf.readInt32();
- cellInfo.cdmaDbm = Buf.readInt32();
- cellInfo.cdmaEcio = Buf.readInt32();
- cellInfo.evdoDbm = Buf.readInt32();
- cellInfo.evdoEcio = Buf.readInt32();
- cellInfo.evdoSnr = Buf.readInt32();
- break;
- case CELL_INFO_TYPE_LTE:
- cellInfo.mcc = Buf.readInt32();
- cellInfo.mnc = Buf.readInt32();
- cellInfo.cid = Buf.readInt32();
- cellInfo.pcid = Buf.readInt32();
- cellInfo.tac = Buf.readInt32();
- cellInfo.signalStrength = Buf.readInt32();
- cellInfo.rsrp = Buf.readInt32();
- cellInfo.rsrq = Buf.readInt32();
- cellInfo.rssnr = Buf.readInt32();
- cellInfo.cqi = Buf.readInt32();
- break;
- }
- cellInfoList.push(cellInfo);
- }
- options.result = cellInfoList;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_LOCATION_UPDATES] = null;
-RilObject.prototype[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null;
-RilObject.prototype[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) {
- if (!options.errorMsg) {
- options.mode = this.context.Buf.readInt32List()[0];
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_TTY_MODE] = null;
-RilObject.prototype[REQUEST_QUERY_TTY_MODE] = null;
-RilObject.prototype[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let enabled = this.context.Buf.readInt32List();
- options.enabled = enabled[0] ? true : false;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CDMA_FLASH] = function REQUEST_CDMA_FLASH(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_CDMA_BURST_DTMF] = null;
-RilObject.prototype[REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY] = null;
-RilObject.prototype[REQUEST_CDMA_SEND_SMS] = function REQUEST_CDMA_SEND_SMS(length, options) {
- this._processSmsSendResult(length, options);
-};
-RilObject.prototype[REQUEST_CDMA_SMS_ACKNOWLEDGE] = null;
-RilObject.prototype[REQUEST_GSM_GET_BROADCAST_SMS_CONFIG] = null;
-RilObject.prototype[REQUEST_GSM_SET_BROADCAST_SMS_CONFIG] = function REQUEST_GSM_SET_BROADCAST_SMS_CONFIG(length, options) {
- if (options.errorMsg) {
- return;
- }
- this.setSmsBroadcastActivation(true);
-};
-RilObject.prototype[REQUEST_GSM_SMS_BROADCAST_ACTIVATION] = null;
-RilObject.prototype[REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG] = null;
-RilObject.prototype[REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG] = function REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG(length, options) {
- if (options.errorMsg) {
- return;
- }
- this.setSmsBroadcastActivation(true);
-};
-RilObject.prototype[REQUEST_CDMA_SMS_BROADCAST_ACTIVATION] = null;
-RilObject.prototype[REQUEST_CDMA_SUBSCRIPTION] = function REQUEST_CDMA_SUBSCRIPTION(length, options) {
- if (options.errorMsg) {
- return;
- }
-
- let result = this.context.Buf.readStringList();
-
- this.iccInfo.mdn = result[0];
- // The result[1] is Home SID. (Already be handled in readCDMAHome())
- // The result[2] is Home NID. (Already be handled in readCDMAHome())
- // The result[3] is MIN.
- this.iccInfo.prlVersion = parseInt(result[4], 10);
-
- this.context.ICCUtilsHelper.handleICCInfoChange();
-};
-RilObject.prototype[REQUEST_CDMA_WRITE_SMS_TO_RUIM] = null;
-RilObject.prototype[REQUEST_CDMA_DELETE_SMS_ON_RUIM] = null;
-RilObject.prototype[REQUEST_DEVICE_IDENTITY] = function REQUEST_DEVICE_IDENTITY(length, options) {
- if (options.errorMsg) {
- this.context.debug("Failed to get device identities:" + options.errorMsg);
- return;
- }
-
- let result = this.context.Buf.readStringList();
- this.deviceIdentities = {
- imei: result[0] || null,
- imeisv: result[1] || null,
- esn: result[2] || null,
- meid: result[3] || null,
- };
-
- this.sendChromeMessage({
- rilMessageType: "deviceidentitieschange",
- deviceIdentities: this.deviceIdentities
- });
-};
-RilObject.prototype[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = function REQUEST_EXIT_EMERGENCY_CALLBACK_MODE(length, options) {
- if (options.internal) {
- return;
- }
-
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRESS(length, options) {
- if (!options.rilMessageType || options.rilMessageType !== "getSmscAddress") {
- return;
- }
-
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let tosca = TOA_UNKNOWN;
- let smsc = "";
- let Buf = this.context.Buf;
- if (RILQUIRKS_SMSC_ADDRESS_FORMAT === "pdu") {
- let pduHelper = this.context.GsmPDUHelper;
- let strlen = Buf.readInt32();
- let length = pduHelper.readHexOctet();
-
- // As defined in |8.2.5.2 Destination address element| of 3GPP TS 24.011,
- // the value of length field can not exceed 11. Since the content might be
- // filled with 12 'F' when SMSC is cleared, we don't parse the TOA and
- // address fields if reported length exceeds 11 here. Instead, keep the
- // default value (TOA_UNKNOWN with an empty address) in this case.
- const MAX_LENGTH = 11
- if (length <= MAX_LENGTH) {
- tosca = pduHelper.readHexOctet();
-
- // Read and covert the decimal values back to special BCD digits defined in
- // |Called party BCD number| of 3GPP TS 24.008 (refer the following table).
- //
- // +=========+=======+=====+
- // | value | digit | hex |
- // +========================
- // | 1 0 1 0 | * | 0xA |
- // | 1 0 1 1 | # | 0xB |
- // | 1 1 0 0 | a | 0xC |
- // | 1 1 0 1 | b | 0xD |
- // | 1 1 1 0 | c | 0xE |
- // +=========+=======+=====+
- smsc = pduHelper.readSwappedNibbleBcdString(length - 1, true)
- .replace(/a/ig, "*")
- .replace(/b/ig, "#")
- .replace(/c/ig, "a")
- .replace(/d/ig, "b")
- .replace(/e/ig, "c");
-
- Buf.readStringDelimiter(strlen);
- }
- } else /* RILQUIRKS_SMSC_ADDRESS_FORMAT === "text" */ {
- let text = Buf.readString();
- let segments = text.split(",", 2);
- // Parse TOA only if it presents since some devices might omit the TOA
- // segment in the reported SMSC address. If TOA does not present, keep the
- // default value TOA_UNKNOWN.
- if (segments.length === 2) {
- tosca = this.parseInt(segments[1], TOA_UNKNOWN, 10);
- }
-
- smsc = segments[0].replace(/\"/g, "");
- }
-
- // Convert the NPI value to the corresponding index of CALLED_PARTY_BCD_NPI
- // array. If the value does not present in the array, use
- // CALLED_PARTY_BCD_NPI_ISDN.
- let npi = CALLED_PARTY_BCD_NPI.indexOf(tosca & 0xf);
- if (npi === -1) {
- npi = CALLED_PARTY_BCD_NPI.indexOf(CALLED_PARTY_BCD_NPI_ISDN);
- }
-
- // Extract TON.
- let ton = (tosca & 0x70) >> 4;
-
- // Ensure + sign if TON is international, and vice versa.
- const TON_INTERNATIONAL = (TOA_INTERNATIONAL & 0x70) >> 4;
- if (ton === TON_INTERNATIONAL && smsc.charAt(0) !== "+") {
- smsc = "+" + smsc;
- } else if (smsc.charAt(0) === "+" && ton !== TON_INTERNATIONAL) {
- if (DEBUG) {
- this.context.debug("SMSC address number begins with '+' while the TON is not international. Change TON to international.");
- }
- ton = TON_INTERNATIONAL;
- }
-
- options.smscAddress = smsc;
- options.typeOfNumber = ton;
- options.numberPlanIdentification = npi;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_SMSC_ADDRESS] = function REQUEST_SET_SMSC_ADDRESS(length, options) {
- if (!options.rilMessageType || options.rilMessageType !== "setSmscAddress") {
- return;
- }
-
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_REPORT_SMS_MEMORY_STATUS] = function REQUEST_REPORT_SMS_MEMORY_STATUS(length, options) {
- this.pendingToReportSmsMemoryStatus = !!options.errorMsg;
-};
-RilObject.prototype[REQUEST_REPORT_STK_SERVICE_IS_RUNNING] = null;
-RilObject.prototype[REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE] = null;
-RilObject.prototype[REQUEST_ISIM_AUTHENTICATION] = null;
-RilObject.prototype[REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU] = null;
-RilObject.prototype[REQUEST_STK_SEND_ENVELOPE_WITH_STATUS] = function REQUEST_STK_SEND_ENVELOPE_WITH_STATUS(length, options) {
- if (options.errorMsg) {
- this.acknowledgeGsmSms(false, PDU_FCS_UNSPECIFIED);
- return;
- }
-
- let Buf = this.context.Buf;
- let sw1 = Buf.readInt32();
- let sw2 = Buf.readInt32();
- if ((sw1 == ICC_STATUS_SAT_BUSY) && (sw2 === 0x00)) {
- this.acknowledgeGsmSms(false, PDU_FCS_USAT_BUSY);
- return;
- }
-
- let success = ((sw1 == ICC_STATUS_NORMAL_ENDING) && (sw2 === 0x00))
- || (sw1 == ICC_STATUS_NORMAL_ENDING_WITH_EXTRA);
-
- let messageStringLength = Buf.readInt32(); // In semi-octets
- let responsePduLen = messageStringLength / 2; // In octets
- if (!responsePduLen) {
- this.acknowledgeGsmSms(success, success ? PDU_FCS_OK
- : PDU_FCS_USIM_DATA_DOWNLOAD_ERROR);
- return;
- }
-
- this.acknowledgeIncomingGsmSmsWithPDU(success, responsePduLen, options);
-};
-RilObject.prototype[REQUEST_VOICE_RADIO_TECH] = function REQUEST_VOICE_RADIO_TECH(length, options) {
- if (options.errorMsg) {
- if (DEBUG) {
- this.context.debug("Error when getting voice radio tech: " +
- options.errorMsg);
- }
- return;
- }
- let radioTech = this.context.Buf.readInt32List();
- this._processRadioTech(radioTech[0]);
-};
-RilObject.prototype[REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE] = null;
-RilObject.prototype[REQUEST_SET_INITIAL_ATTACH_APN] = null;
-RilObject.prototype[REQUEST_IMS_REGISTRATION_STATE] = null;
-RilObject.prototype[REQUEST_IMS_SEND_SMS] = null;
-RilObject.prototype[REQUEST_SIM_TRANSMIT_APDU_BASIC] = null;
-RilObject.prototype[REQUEST_SIM_OPEN_CHANNEL] = function REQUEST_SIM_OPEN_CHANNEL(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- options.channel = this.context.Buf.readInt32List()[0];
- // onwards may optionally contain the select response for the open channel
- // command with one byte per integer.
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SIM_CLOSE_CHANNEL] = function REQUEST_SIM_CLOSE_CHANNEL(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_SIM_TRANSMIT_APDU_CHANNEL] = function REQUEST_SIM_TRANSMIT_APDU_CHANNEL(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- options.sw1 = Buf.readInt32();
- options.sw2 = Buf.readInt32();
- options.simResponse = Buf.readString();
- if (DEBUG) {
- this.context.debug("Setting return values for RIL[REQUEST_SIM_TRANSMIT_APDU_CHANNEL]: [" +
- options.sw1 + "," +
- options.sw2 + ", " +
- options.simResponse + "]");
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_NV_READ_ITEM] = null;
-RilObject.prototype[REQUEST_NV_WRITE_ITEM] = null;
-RilObject.prototype[REQUEST_NV_WRITE_CDMA_PRL] = null;
-RilObject.prototype[REQUEST_NV_RESET_CONFIG] = null;
-RilObject.prototype[REQUEST_SET_UICC_SUBSCRIPTION] = function REQUEST_SET_UICC_SUBSCRIPTION(length, options) {
- // Resend data subscription after uicc subscription.
- if (this._attachDataRegistration) {
- this.setDataRegistration({attach: true});
- }
-};
-RilObject.prototype[REQUEST_ALLOW_DATA] = null;
-RilObject.prototype[REQUEST_GET_HARDWARE_CONFIG] = null;
-RilObject.prototype[REQUEST_SIM_AUTHENTICATION] = null;
-RilObject.prototype[REQUEST_GET_DC_RT_INFO] = null;
-RilObject.prototype[REQUEST_SET_DC_RT_INFO_RATE] = null;
-RilObject.prototype[REQUEST_SET_DATA_PROFILE] = null;
-RilObject.prototype[REQUEST_SHUTDOWN] = null;
-RilObject.prototype[REQUEST_SET_DATA_SUBSCRIPTION] = function REQUEST_SET_DATA_SUBSCRIPTION(length, options) {
- if (!options.rilMessageType) {
- // The request was made by ril_worker itself. Don't report.
- return;
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_UNLOCK_RETRY_COUNT] = function REQUEST_GET_UNLOCK_RETRY_COUNT(length, options) {
- options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[RIL_REQUEST_GPRS_ATTACH] = function RIL_REQUEST_GPRS_ATTACH(length, options) {
- if (!options.rilMessageType) {
- // The request was made by ril_worker itself. Don't report.
- return;
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[RIL_REQUEST_GPRS_DETACH] = function RIL_REQUEST_GPRS_DETACH(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED() {
- let radioState = this.context.Buf.readInt32();
- let newState;
- switch (radioState) {
- case RADIO_STATE_UNAVAILABLE:
- newState = GECKO_RADIOSTATE_UNKNOWN;
- break;
- case RADIO_STATE_OFF:
- newState = GECKO_RADIOSTATE_DISABLED;
- break;
- default:
- newState = GECKO_RADIOSTATE_ENABLED;
- }
-
- if (DEBUG) {
- this.context.debug("Radio state changed from '" + this.radioState +
- "' to '" + newState + "'");
- }
- if (this.radioState == newState) {
- return;
- }
-
- if (radioState !== RADIO_STATE_UNAVAILABLE) {
- // Retrieve device identities once radio is available.
- this.getDeviceIdentity();
- }
-
- if (radioState == RADIO_STATE_ON) {
- // This value is defined in RIL v7, we will retrieve radio tech by another
- // request. We leave _isCdma untouched, and it will be set once we get the
- // radio technology.
- this._waitingRadioTech = true;
- this.getVoiceRadioTechnology();
- }
-
- if ((this.radioState == GECKO_RADIOSTATE_UNKNOWN ||
- this.radioState == GECKO_RADIOSTATE_DISABLED) &&
- newState == GECKO_RADIOSTATE_ENABLED) {
- // The radio became available, let's get its info.
- this.getBasebandVersion();
- this.updateCellBroadcastConfig();
- if ((RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
- RILQUIRKS_SUBSCRIPTION_CONTROL) &&
- this._attachDataRegistration) {
- this.setDataRegistration({attach: true});
- }
-
- if (this.pendingToReportSmsMemoryStatus) {
- this._updateSmsMemoryStatus();
- }
- }
-
- this.radioState = newState;
- this.sendChromeMessage({
- rilMessageType: "radiostatechange",
- radioState: newState
- });
-
- // If the radio is up and on, so let's query the card state.
- // On older RILs only if the card is actually ready, though.
- // If _waitingRadioTech is set, we don't need to get icc status now.
- if (radioState == RADIO_STATE_UNAVAILABLE ||
- radioState == RADIO_STATE_OFF ||
- this._waitingRadioTech) {
- return;
- }
- this.getICCStatus();
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_CALL_STATE_CHANGED] = function UNSOLICITED_RESPONSE_CALL_STATE_CHANGED() {
- this.getCurrentCalls();
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED] = function UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED() {
- if (DEBUG) {
- this.context.debug("Network state changed, re-requesting phone state and " +
- "ICC status");
- }
- this.getICCStatus();
- this.requestNetworkInfo();
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS] = function UNSOLICITED_RESPONSE_NEW_SMS(length) {
- let [message, result] = this.context.GsmPDUHelper.processReceivedSms(length);
-
- if (message) {
- result = this._processSmsMultipart(message);
- }
-
- if (result == PDU_FCS_RESERVED || result == MOZ_FCS_WAIT_FOR_EXPLICIT_ACK) {
- return;
- }
-
- // Not reserved FCS values, send ACK now.
- this.acknowledgeGsmSms(result == PDU_FCS_OK, result);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT] = function UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT(length) {
- let result = this._processSmsStatusReport(length);
- this.acknowledgeGsmSms(result == PDU_FCS_OK, result);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM] = function UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM(length) {
- let recordNumber = this.context.Buf.readInt32List()[0];
-
- this.context.SimRecordHelper.readSMS(
- recordNumber,
- function onsuccess(message) {
- if (message && message.simStatus === 3) { //New Unread SMS
- this._processSmsMultipart(message);
- }
- }.bind(this),
- function onerror(errorMsg) {
- if (DEBUG) {
- this.context.debug("Failed to Read NEW SMS on SIM #" + recordNumber +
- ", errorMsg: " + errorMsg);
- }
- });
-};
-RilObject.prototype[UNSOLICITED_ON_USSD] = function UNSOLICITED_ON_USSD() {
- let [typeCode, message] = this.context.Buf.readStringList();
- if (DEBUG) {
- this.context.debug("On USSD. Type Code: " + typeCode + " Message: " + message);
- }
-
- this.sendChromeMessage({rilMessageType: "ussdreceived",
- message: message,
- // Per ril.h the USSD session is assumed to persist if
- // the type code is "1", otherwise the current session
- // (if any) is assumed to have terminated.
- sessionEnded: typeCode !== "1"});
-};
-RilObject.prototype[UNSOLICITED_ON_USSD_REQUEST] = null;
-RilObject.prototype[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() {
- let dateString = this.context.Buf.readString();
-
- // The data contained in the NITZ message is
- // in the form "yy/mm/dd,hh:mm:ss(+/-)tz,dt"
- // for example: 12/02/16,03:36:08-20,00,310410
- // See also bug 714352 - Listen for NITZ updates from rild.
-
- if (DEBUG) this.context.debug("DateTimeZone string " + dateString);
-
- let now = Date.now();
-
- let year = parseInt(dateString.substr(0, 2), 10);
- let month = parseInt(dateString.substr(3, 2), 10);
- let day = parseInt(dateString.substr(6, 2), 10);
- let hours = parseInt(dateString.substr(9, 2), 10);
- let minutes = parseInt(dateString.substr(12, 2), 10);
- let seconds = parseInt(dateString.substr(15, 2), 10);
- // Note that |tz| is in 15-min units.
- let tz = parseInt(dateString.substr(17, 3), 10);
- // Note that |dst| is in 1-hour units and is already applied in |tz|.
- let dst = parseInt(dateString.substr(21, 2), 10);
-
- let timeInMS = Date.UTC(year + PDU_TIMESTAMP_YEAR_OFFSET, month - 1, day,
- hours, minutes, seconds);
-
- if (isNaN(timeInMS)) {
- if (DEBUG) this.context.debug("NITZ failed to convert date");
- return;
- }
-
- this.sendChromeMessage({rilMessageType: "nitzTime",
- networkTimeInMS: timeInMS,
- networkTimeZoneInMinutes: -(tz * 15),
- networkDSTInMinutes: -(dst * 60),
- receiveTimeInMS: now});
-};
-
-RilObject.prototype[UNSOLICITED_SIGNAL_STRENGTH] = function UNSOLICITED_SIGNAL_STRENGTH(length) {
- this[REQUEST_SIGNAL_STRENGTH](length, {});
-};
-RilObject.prototype[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function UNSOLICITED_DATA_CALL_LIST_CHANGED(length) {
- this[REQUEST_DATA_CALL_LIST](length, {});
-};
-RilObject.prototype[UNSOLICITED_SUPP_SVC_NOTIFICATION] = function UNSOLICITED_SUPP_SVC_NOTIFICATION(length) {
- let Buf = this.context.Buf;
- let info = {};
- info.notificationType = Buf.readInt32();
- info.code = Buf.readInt32();
- info.index = Buf.readInt32();
- info.type = Buf.readInt32();
- info.number = Buf.readString();
-
- this._processSuppSvcNotification(info);
-};
-
-RilObject.prototype[UNSOLICITED_STK_SESSION_END] = function UNSOLICITED_STK_SESSION_END() {
- this.sendChromeMessage({rilMessageType: "stksessionend"});
-};
-RilObject.prototype[UNSOLICITED_STK_PROACTIVE_COMMAND] = function UNSOLICITED_STK_PROACTIVE_COMMAND() {
- this.processStkProactiveCommand();
-};
-RilObject.prototype[UNSOLICITED_STK_EVENT_NOTIFY] = function UNSOLICITED_STK_EVENT_NOTIFY() {
- this.processStkProactiveCommand();
-};
-RilObject.prototype[UNSOLICITED_STK_CALL_SETUP] = null;
-RilObject.prototype[UNSOLICITED_SIM_SMS_STORAGE_FULL] = null;
-RilObject.prototype[UNSOLICITED_SIM_REFRESH] = null;
-RilObject.prototype[UNSOLICITED_CALL_RING] = function UNSOLICITED_CALL_RING() {
- let Buf = this.context.Buf;
- let info = {rilMessageType: "callRing"};
- let isCDMA = false; //XXX TODO hard-code this for now
- if (isCDMA) {
- info.isPresent = Buf.readInt32();
- info.signalType = Buf.readInt32();
- info.alertPitch = Buf.readInt32();
- info.signal = Buf.readInt32();
- }
- // At this point we don't know much other than the fact there's an incoming
- // call, but that's enough to bring up the Phone app already. We'll know
- // details once we get a call state changed notification and can then
- // dispatch DOM events etc.
- this.sendChromeMessage(info);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED] = function UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED() {
- this.getICCStatus();
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] = function UNSOLICITED_RESPONSE_CDMA_NEW_SMS(length) {
- let [message, result] = this.context.CdmaPDUHelper.processReceivedSms(length);
-
- if (message) {
- if (message.teleservice === PDU_CDMA_MSG_TELESERIVCIE_ID_WAP) {
- result = this._processCdmaSmsWapPush(message);
- } else if (message.subMsgType === PDU_CDMA_MSG_TYPE_DELIVER_ACK) {
- result = this._processCdmaSmsStatusReport(message);
- } else {
- result = this._processSmsMultipart(message);
- }
- }
-
- if (result == PDU_FCS_RESERVED || result == MOZ_FCS_WAIT_FOR_EXPLICIT_ACK) {
- return;
- }
-
- // Not reserved FCS values, send ACK now.
- this.acknowledgeCdmaSms(result == PDU_FCS_OK, result);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS] = function UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS(length) {
- let message;
- try {
- message =
- this.context.GsmPDUHelper.readCbMessage(this.context.Buf.readInt32());
-
- // "Data-Download" message is expected to be handled by the modem.
- // Ignore it here to prevent any garbage messages to be displayed.
- // See 9.4.1.2.2 Message Identifier of TS 32.041 for the range of
- // Message-identifier of the Data-Download CB messages.
- if (message.messageId >= 0x1000 && message.messageId <= 0x10FF) {
- if (DEBUG) {
- this.context.debug("Ignore a Data-Download message, messageId: " +
- message.messageId);
- }
- return;
- }
- } catch (e) {
- if (DEBUG) {
- this.context.debug("Failed to parse Cell Broadcast message: " + e);
- }
- return;
- }
-
- message = this._processReceivedSmsCbPage(message);
- if (!message) {
- return;
- }
-
- // Bug 1235697, failed to deactivate CBS in some modem.
- // Workaround it according to the settings.
- // Note: ETWS/CMAS/PWS can be received even disabled.
- // It will be displayed according to the setting in application layer.
- if (this.cellBroadcastDisabled && (
- !(message.messageId >= 0x1100 && message.messageId <= 0x1107) && // ETWS
- !(message.messageId >= 0x1112 && message.messageId <= 0x112F) && // CMAS
- !(message.messageId >= 0x1130 && message.messageId <= 0x18FF) // PWS
- )) {
- if (DEBUG) {
- this.context.debug("Ignore a CB message when disabled, messageId: " +
- message.messageId);
- }
- return;
- }
-
- message.rilMessageType = "cellbroadcast-received";
- this.sendChromeMessage(message);
-};
-RilObject.prototype[UNSOLICITED_CDMA_RUIM_SMS_STORAGE_FULL] = null;
-RilObject.prototype[UNSOLICITED_RESTRICTED_STATE_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE() {
- this._handleChangedEmergencyCbMode(true);
-};
-RilObject.prototype[UNSOLICITED_CDMA_CALL_WAITING] = function UNSOLICITED_CDMA_CALL_WAITING(length) {
- let Buf = this.context.Buf;
- let call = {};
- call.number = Buf.readString();
- call.numberPresentation = Buf.readInt32();
- call.name = Buf.readString();
- call.namePresentation = Buf.readInt32();
- call.isPresent = Buf.readInt32();
- call.signalType = Buf.readInt32();
- call.alertPitch = Buf.readInt32();
- call.signal = Buf.readInt32();
- this.sendChromeMessage({rilMessageType: "cdmaCallWaiting",
- waitingCall: call});
-};
-RilObject.prototype[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = function UNSOLICITED_CDMA_OTA_PROVISION_STATUS() {
- let status =
- CDMA_OTA_PROVISION_STATUS_TO_GECKO[this.context.Buf.readInt32List()[0]];
- if (!status) {
- return;
- }
- this.sendChromeMessage({rilMessageType: "otastatuschange",
- status: status});
-};
-RilObject.prototype[UNSOLICITED_CDMA_INFO_REC] = function UNSOLICITED_CDMA_INFO_REC(length) {
- this.sendChromeMessage({
- rilMessageType: "cdma-info-rec-received",
- records: this.context.CdmaPDUHelper.decodeInformationRecord()
- });
-};
-RilObject.prototype[UNSOLICITED_OEM_HOOK_RAW] = null;
-RilObject.prototype[UNSOLICITED_RINGBACK_TONE] = null;
-RilObject.prototype[UNSOLICITED_RESEND_INCALL_MUTE] = null;
-RilObject.prototype[UNSOLICITED_CDMA_SUBSCRIPTION_SOURCE_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_CDMA_PRL_CHANGED] = function UNSOLICITED_CDMA_PRL_CHANGED(length) {
- let version = this.context.Buf.readInt32List()[0];
- if (version !== this.iccInfo.prlVersion) {
- this.iccInfo.prlVersion = version;
- this.context.ICCUtilsHelper.handleICCInfoChange();
- }
-};
-RilObject.prototype[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE() {
- this._handleChangedEmergencyCbMode(false);
-};
-RilObject.prototype[UNSOLICITED_RIL_CONNECTED] = function UNSOLICITED_RIL_CONNECTED(length) {
- // Prevent response id collision between UNSOLICITED_RIL_CONNECTED and
- // UNSOLICITED_VOICE_RADIO_TECH_CHANGED for Akami on gingerbread branch.
- if (!length) {
- return;
- }
-
- this.version = this.context.Buf.readInt32List()[0];
- if (DEBUG) {
- this.context.debug("Detected RIL version " + this.version);
- }
-
- this.initRILState();
- // rild might have restarted, ensure data call list.
- this.getDataCallList();
- // Always ensure that we are not in emergency callback mode when init.
- this.exitEmergencyCbMode();
- // Reset radio in the case that b2g restart (or crash).
- this.setRadioEnabled({enabled: false});
-};
-RilObject.prototype[UNSOLICITED_VOICE_RADIO_TECH_CHANGED] = function UNSOLICITED_VOICE_RADIO_TECH_CHANGED(length) {
- // This unsolicited response will be sent when the technology of a multi-tech
- // modem is changed, ex. switch between gsm and cdma.
- // TODO: We may need to do more on updating data when switching between gsm
- // and cdma mode, e.g. IMEI, ESN, iccInfo, iccType ... etc.
- // See Bug 866038.
- this._processRadioTech(this.context.Buf.readInt32List()[0]);
-};
-RilObject.prototype[UNSOLICITED_CELL_INFO_LIST] = null;
-RilObject.prototype[UNSOLICITED_RESPONSE_IMS_NETWORK_STATE_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_UICC_SUBSCRIPTION_STATUS_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_SRVCC_STATE_NOTIFY] = null;
-RilObject.prototype[UNSOLICITED_HARDWARE_CONFIG_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_DC_RT_INFO_CHANGED] = null;
-
-/**
- * This object exposes the functionality to parse and serialize PDU strings
- *
- * A PDU is a string containing a series of hexadecimally encoded octets
- * or nibble-swapped binary-coded decimals (BCDs). It contains not only the
- * message text but information about the sender, the SMS service center,
- * timestamp, etc.
- */
-function GsmPDUHelperObject(aContext) {
- this.context = aContext;
-}
-GsmPDUHelperObject.prototype = {
- context: null,
-
- /**
- * Read one character (2 bytes) from a RIL string and decode as hex.
- *
- * @return the nibble as a number.
- */
- readHexNibble: function() {
- let nibble = this.context.Buf.readUint16();
- if (nibble >= 48 && nibble <= 57) {
- nibble -= 48; // ASCII '0'..'9'
- } else if (nibble >= 65 && nibble <= 70) {
- nibble -= 55; // ASCII 'A'..'F'
- } else if (nibble >= 97 && nibble <= 102) {
- nibble -= 87; // ASCII 'a'..'f'
- } else {
- throw "Found invalid nibble during PDU parsing: " +
- String.fromCharCode(nibble);
- }
- return nibble;
- },
-
- /**
- * Encode a nibble as one hex character in a RIL string (2 bytes).
- *
- * @param nibble
- * The nibble to encode (represented as a number)
- */
- writeHexNibble: function(nibble) {
- nibble &= 0x0f;
- if (nibble < 10) {
- nibble += 48; // ASCII '0'
- } else {
- nibble += 55; // ASCII 'A'
- }
- this.context.Buf.writeUint16(nibble);
- },
-
- /**
- * Read a hex-encoded octet (two nibbles).
- *
- * @return the octet as a number.
- */
- readHexOctet: function() {
- return (this.readHexNibble() << 4) | this.readHexNibble();
- },
-
- /**
- * Write an octet as two hex-encoded nibbles.
- *
- * @param octet
- * The octet (represented as a number) to encode.
- */
- writeHexOctet: function(octet) {
- this.writeHexNibble(octet >> 4);
- this.writeHexNibble(octet);
- },
-
- /**
- * Read an array of hex-encoded octets.
- */
- readHexOctetArray: function(length) {
- let array = new Uint8Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = this.readHexOctet();
- }
- return array;
- },
-
- /**
- * Helper to write data into a temporary buffer for easier length encoding when
- * the number of octets for the length encoding is varied.
- *
- * @param writeFunction
- * Function of how the data to be written into temporary buffer.
- *
- * @return array of written octets.
- **/
- writeWithBuffer: function(writeFunction) {
- let buf = [];
- let writeHexOctet = this.writeHexOctet;
- this.writeHexOctet = function(octet) {
- buf.push(octet);
- }
-
- try {
- writeFunction();
- } catch (e) {
- if (DEBUG) {
- debug("Error when writeWithBuffer: " + e);
- }
- buf = [];
- } finally {
- this.writeHexOctet = writeHexOctet;
- }
-
- return buf;
- },
-
- /**
- * Convert an octet (number) to a BCD number.
- *
- * Any nibbles that are not in the BCD range count as 0.
- *
- * @param octet
- * The octet (a number, as returned by getOctet())
- *
- * @return the corresponding BCD number.
- */
- octetToBCD: function(octet) {
- return ((octet & 0xf0) <= 0x90) * ((octet >> 4) & 0x0f) +
- ((octet & 0x0f) <= 0x09) * (octet & 0x0f) * 10;
- },
-
- /**
- * Convert a BCD number to an octet (number)
- *
- * Only take two digits with absolute value.
- *
- * @param bcd
- *
- * @return the corresponding octet.
- */
- BCDToOctet: function(bcd) {
- bcd = Math.abs(bcd);
- return ((bcd % 10) << 4) + (Math.floor(bcd / 10) % 10);
- },
-
- /**
- * Convert a semi-octet (number) to a GSM BCD char, or return empty
- * string if invalid semiOctet and suppressException is set to true.
- *
- * @param semiOctet
- * Nibble to be converted to.
- * @param suppressException [optional]
- * Suppress exception if invalid semiOctet and suppressException is set
- * to true.
- *
- * @return GSM BCD char, or empty string.
- */
- bcdChars: "0123456789",
- semiOctetToBcdChar: function(semiOctet, suppressException) {
- if (semiOctet >= this.bcdChars.length) {
- if (suppressException) {
- return "";
- } else {
- throw new RangeError();
- }
- }
-
- return this.bcdChars.charAt(semiOctet);
- },
-
- /**
- * Convert a semi-octet (number) to a GSM extended BCD char, or return empty
- * string if invalid semiOctet and suppressException is set to true.
- *
- * @param semiOctet
- * Nibble to be converted to.
- * @param suppressException [optional]
- * Suppress exception if invalid semiOctet and suppressException is set
- * to true.
- *
- * @return GSM extended BCD char, or empty string.
- */
- extendedBcdChars: "0123456789*#,;",
- semiOctetToExtendedBcdChar: function(semiOctet, suppressException) {
- if (semiOctet >= this.extendedBcdChars.length) {
- if (suppressException) {
- return "";
- } else {
- throw new RangeError();
- }
- }
-
- return this.extendedBcdChars.charAt(semiOctet);
- },
-
- /**
- * Convert string to a GSM extended BCD string
- */
- stringToExtendedBcd: function(string) {
- return string.replace(/[^0-9*#,]/g, "")
- .replace(/\*/g, "a")
- .replace(/\#/g, "b")
- .replace(/\,/g, "c");
- },
-
- /**
- * Read a *swapped nibble* binary coded decimal (BCD)
- *
- * @param pairs
- * Number of nibble *pairs* to read.
- *
- * @return the decimal as a number.
- */
- readSwappedNibbleBcdNum: function(pairs) {
- let number = 0;
- for (let i = 0; i < pairs; i++) {
- let octet = this.readHexOctet();
- // Ignore 'ff' octets as they're often used as filler.
- if (octet == 0xff) {
- continue;
- }
- // If the first nibble is an "F" , only the second nibble is to be taken
- // into account.
- if ((octet & 0xf0) == 0xf0) {
- number *= 10;
- number += octet & 0x0f;
- continue;
- }
- number *= 100;
- number += this.octetToBCD(octet);
- }
- return number;
- },
-
- /**
- * Read a *swapped nibble* binary coded decimal (BCD) string
- *
- * @param pairs
- * Number of nibble *pairs* to read.
- * @param suppressException [optional]
- * Suppress exception if invalid semiOctet and suppressException is set
- * to true.
- *
- * @return The BCD string.
- */
- readSwappedNibbleBcdString: function(pairs, suppressException) {
- let str = "";
- for (let i = 0; i < pairs; i++) {
- let nibbleH = this.readHexNibble();
- let nibbleL = this.readHexNibble();
- if (nibbleL == 0x0F) {
- break;
- }
-
- str += this.semiOctetToBcdChar(nibbleL, suppressException);
- if (nibbleH != 0x0F) {
- str += this.semiOctetToBcdChar(nibbleH, suppressException);
- }
- }
-
- return str;
- },
-
- /**
- * Read a *swapped nibble* extended binary coded decimal (BCD) string
- *
- * @param pairs
- * Number of nibble *pairs* to read.
- * @param suppressException [optional]
- * Suppress exception if invalid semiOctet and suppressException is set
- * to true.
- *
- * @return The BCD string.
- */
- readSwappedNibbleExtendedBcdString: function(pairs, suppressException) {
- let str = "";
- for (let i = 0; i < pairs; i++) {
- let nibbleH = this.readHexNibble();
- let nibbleL = this.readHexNibble();
- if (nibbleL == 0x0F) {
- break;
- }
-
- str += this.semiOctetToExtendedBcdChar(nibbleL, suppressException);
- if (nibbleH != 0x0F) {
- str += this.semiOctetToExtendedBcdChar(nibbleH, suppressException);
- }
- }
-
- return str;
- },
-
- /**
- * Write numerical data as swapped nibble BCD.
- *
- * @param data
- * Data to write (as a string or a number)
- */
- writeSwappedNibbleBCD: function(data) {
- data = data.toString();
- if (data.length % 2) {
- data += "F";
- }
- let Buf = this.context.Buf;
- for (let i = 0; i < data.length; i += 2) {
- Buf.writeUint16(data.charCodeAt(i + 1));
- Buf.writeUint16(data.charCodeAt(i));
- }
- },
-
- /**
- * Write numerical data as swapped nibble BCD.
- * If the number of digit of data is even, add '0' at the beginning.
- *
- * @param data
- * Data to write (as a string or a number)
- */
- writeSwappedNibbleBCDNum: function(data) {
- data = data.toString();
- if (data.length % 2) {
- data = "0" + data;
- }
- let Buf = this.context.Buf;
- for (let i = 0; i < data.length; i += 2) {
- Buf.writeUint16(data.charCodeAt(i + 1));
- Buf.writeUint16(data.charCodeAt(i));
- }
- },
-
- /**
- * Read user data, convert to septets, look up relevant characters in a
- * 7-bit alphabet, and construct string.
- *
- * @param length
- * Number of septets to read (*not* octets)
- * @param paddingBits
- * Number of padding bits in the first byte of user data.
- * @param langIndex
- * Table index used for normal 7-bit encoded character lookup.
- * @param langShiftIndex
- * Table index used for escaped 7-bit encoded character lookup.
- *
- * @return a string.
- */
- readSeptetsToString: function(length, paddingBits, langIndex, langShiftIndex) {
- let ret = "";
- let byteLength = Math.ceil((length * 7 + paddingBits) / 8);
-
- /**
- * |<- last byte in header ->|
- * |<- incompleteBits ->|<- last header septet->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- *
- * |<- 1st byte in user data ->|
- * |<- data septet 1 ->|<-paddingBits->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- *
- * |<- 2nd byte in user data ->|
- * |<- data spetet 2 ->|<-ds1->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- */
- let data = 0;
- let dataBits = 0;
- if (paddingBits) {
- data = this.readHexOctet() >> paddingBits;
- dataBits = 8 - paddingBits;
- --byteLength;
- }
-
- let escapeFound = false;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
- do {
- // Read as much as fits in 32bit word
- let bytesToRead = Math.min(byteLength, dataBits ? 3 : 4);
- for (let i = 0; i < bytesToRead; i++) {
- data |= this.readHexOctet() << dataBits;
- dataBits += 8;
- --byteLength;
- }
-
- // Consume available full septets
- for (; dataBits >= 7; dataBits -= 7) {
- let septet = data & 0x7F;
- data >>>= 7;
-
- if (escapeFound) {
- escapeFound = false;
- if (septet == PDU_NL_EXTENDED_ESCAPE) {
- // According to 3GPP TS 23.038, section 6.2.1.1, NOTE 1, "On
- // receipt of this code, a receiving entity shall display a space
- // until another extensiion table is defined."
- ret += " ";
- } else if (septet == PDU_NL_RESERVED_CONTROL) {
- // According to 3GPP TS 23.038 B.2, "This code represents a control
- // character and therefore must not be used for language specific
- // characters."
- ret += " ";
- } else {
- ret += langShiftTable[septet];
- }
- } else if (septet == PDU_NL_EXTENDED_ESCAPE) {
- escapeFound = true;
-
- // <escape> is not an effective character
- --length;
- } else {
- ret += langTable[septet];
- }
- }
- } while (byteLength);
-
- if (ret.length != length) {
- /**
- * If num of effective characters does not equal to the length of read
- * string, cut the tail off. This happens when the last octet of user
- * data has following layout:
- *
- * |<- penultimate octet in user data ->|
- * |<- data septet N ->|<- dsN-1 ->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- *
- * |<- last octet in user data ->|
- * |<- fill bits ->|<-dsN->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- *
- * The fill bits in the last octet may happen to form a full septet and
- * be appended at the end of result string.
- */
- ret = ret.slice(0, length);
- }
- return ret;
- },
-
- writeStringAsSeptets: function(message, paddingBits, langIndex, langShiftIndex) {
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
-
- let dataBits = paddingBits;
- let data = 0;
- for (let i = 0; i < message.length; i++) {
- let c = message.charAt(i);
- let septet = langTable.indexOf(c);
- if (septet == PDU_NL_EXTENDED_ESCAPE) {
- continue;
- }
-
- if (septet >= 0) {
- data |= septet << dataBits;
- dataBits += 7;
- } else {
- septet = langShiftTable.indexOf(c);
- if (septet == -1) {
- throw new Error("'" + c + "' is not in 7 bit alphabet "
- + langIndex + ":" + langShiftIndex + "!");
- }
-
- if (septet == PDU_NL_RESERVED_CONTROL) {
- continue;
- }
-
- data |= PDU_NL_EXTENDED_ESCAPE << dataBits;
- dataBits += 7;
- data |= septet << dataBits;
- dataBits += 7;
- }
-
- for (; dataBits >= 8; dataBits -= 8) {
- this.writeHexOctet(data & 0xFF);
- data >>>= 8;
- }
- }
-
- if (dataBits !== 0) {
- this.writeHexOctet(data & 0xFF);
- }
- },
-
- writeStringAs8BitUnpacked: function(text) {
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- let len = text ? text.length : 0;
- for (let i = 0; i < len; i++) {
- let c = text.charAt(i);
- let octet = langTable.indexOf(c);
-
- if (octet == -1) {
- octet = langShiftTable.indexOf(c);
- if (octet == -1) {
- // Fallback to ASCII space.
- octet = langTable.indexOf(' ');
- } else {
- this.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
- }
- }
- this.writeHexOctet(octet);
- }
- },
-
- /**
- * Read user data and decode as a UCS2 string.
- *
- * @param numOctets
- * Number of octets to be read as UCS2 string.
- *
- * @return a string.
- */
- readUCS2String: function(numOctets) {
- let str = "";
- let length = numOctets / 2;
- for (let i = 0; i < length; ++i) {
- let code = (this.readHexOctet() << 8) | this.readHexOctet();
- str += String.fromCharCode(code);
- }
-
- if (DEBUG) this.context.debug("Read UCS2 string: " + str);
-
- return str;
- },
-
- /**
- * Write user data as a UCS2 string.
- *
- * @param message
- * Message string to encode as UCS2 in hex-encoded octets.
- */
- writeUCS2String: function(message) {
- for (let i = 0; i < message.length; ++i) {
- let code = message.charCodeAt(i);
- this.writeHexOctet((code >> 8) & 0xFF);
- this.writeHexOctet(code & 0xFF);
- }
- },
-
- /**
- * Read 1 + UDHL octets and construct user data header.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.040 9.2.3.24
- */
- readUserDataHeader: function(msg) {
- /**
- * A header object with properties contained in received message.
- * The properties set include:
- *
- * length: totoal length of the header, default 0.
- * langIndex: used locking shift table index, default
- * PDU_NL_IDENTIFIER_DEFAULT.
- * langShiftIndex: used locking shift table index, default
- * PDU_NL_IDENTIFIER_DEFAULT.
- *
- */
- let header = {
- length: 0,
- langIndex: PDU_NL_IDENTIFIER_DEFAULT,
- langShiftIndex: PDU_NL_IDENTIFIER_DEFAULT
- };
-
- header.length = this.readHexOctet();
- if (DEBUG) this.context.debug("Read UDH length: " + header.length);
-
- let dataAvailable = header.length;
- while (dataAvailable >= 2) {
- let id = this.readHexOctet();
- let length = this.readHexOctet();
- if (DEBUG) this.context.debug("Read UDH id: " + id + ", length: " + length);
-
- dataAvailable -= 2;
-
- switch (id) {
- case PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT: {
- let ref = this.readHexOctet();
- let max = this.readHexOctet();
- let seq = this.readHexOctet();
- dataAvailable -= 3;
- if (max && seq && (seq <= max)) {
- header.segmentRef = ref;
- header.segmentMaxSeq = max;
- header.segmentSeq = seq;
- }
- break;
- }
- case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT: {
- let dstp = this.readHexOctet();
- let orip = this.readHexOctet();
- dataAvailable -= 2;
- if ((dstp < PDU_APA_RESERVED_8BIT_PORTS)
- || (orip < PDU_APA_RESERVED_8BIT_PORTS)) {
- // 3GPP TS 23.040 clause 9.2.3.24.3: "A receiving entity shall
- // ignore any information element where the value of the
- // Information-Element-Data is Reserved or not supported"
- break;
- }
- header.destinationPort = dstp;
- header.originatorPort = orip;
- break;
- }
- case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT: {
- let dstp = (this.readHexOctet() << 8) | this.readHexOctet();
- let orip = (this.readHexOctet() << 8) | this.readHexOctet();
- dataAvailable -= 4;
- if ((dstp >= PDU_APA_VALID_16BIT_PORTS) ||
- (orip >= PDU_APA_VALID_16BIT_PORTS)) {
- // 3GPP TS 23.040 clause 9.2.3.24.4: "A receiving entity shall
- // ignore any information element where the value of the
- // Information-Element-Data is Reserved or not supported"
- // Bug 1130292, some carriers set originatorPort to reserved port
- // numbers for wap push. We rise this as a warning in debug message
- // instead of ingoring this IEI to allow user to receive Wap Push
- // under these carriers.
- this.context.debug("Warning: Invalid port numbers [dstp, orip]: " +
- JSON.stringify([dstp, orip]));
- }
- header.destinationPort = dstp;
- header.originatorPort = orip;
- break;
- }
- case PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT: {
- let ref = (this.readHexOctet() << 8) | this.readHexOctet();
- let max = this.readHexOctet();
- let seq = this.readHexOctet();
- dataAvailable -= 4;
- if (max && seq && (seq <= max)) {
- header.segmentRef = ref;
- header.segmentMaxSeq = max;
- header.segmentSeq = seq;
- }
- break;
- }
- case PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT:
- let langShiftIndex = this.readHexOctet();
- --dataAvailable;
- if (langShiftIndex < PDU_NL_SINGLE_SHIFT_TABLES.length) {
- header.langShiftIndex = langShiftIndex;
- }
- break;
- case PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT:
- let langIndex = this.readHexOctet();
- --dataAvailable;
- if (langIndex < PDU_NL_LOCKING_SHIFT_TABLES.length) {
- header.langIndex = langIndex;
- }
- break;
- case PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION:
- let msgInd = this.readHexOctet() & 0xFF;
- let msgCount = this.readHexOctet();
- dataAvailable -= 2;
-
-
- /*
- * TS 23.040 V6.8.1 Sec 9.2.3.24.2
- * bits 1 0 : basic message indication type
- * bits 4 3 2 : extended message indication type
- * bits 6 5 : Profile id
- * bit 7 : storage type
- */
- let storeType = msgInd & PDU_MWI_STORE_TYPE_BIT;
- let mwi = msg.mwi;
- if (!mwi) {
- mwi = msg.mwi = {};
- }
-
- if (storeType == PDU_MWI_STORE_TYPE_STORE) {
- // Store message because TP_UDH indicates so, note this may override
- // the setting in DCS, but that is expected
- mwi.discard = false;
- } else if (mwi.discard === undefined) {
- // storeType == PDU_MWI_STORE_TYPE_DISCARD
- // only override mwi.discard here if it hasn't already been set
- mwi.discard = true;
- }
-
- mwi.msgCount = msgCount & 0xFF;
- mwi.active = mwi.msgCount > 0;
-
- if (DEBUG) {
- this.context.debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
- }
-
- break;
- default:
- if (DEBUG) {
- this.context.debug("readUserDataHeader: unsupported IEI(" + id +
- "), " + length + " bytes.");
- }
-
- // Read out unsupported data
- if (length) {
- let octets;
- if (DEBUG) octets = new Uint8Array(length);
-
- for (let i = 0; i < length; i++) {
- let octet = this.readHexOctet();
- if (DEBUG) octets[i] = octet;
- }
- dataAvailable -= length;
-
- if (DEBUG) {
- this.context.debug("readUserDataHeader: " + Array.slice(octets));
- }
- }
- break;
- }
- }
-
- if (dataAvailable !== 0) {
- throw new Error("Illegal user data header found!");
- }
-
- msg.header = header;
- },
-
- /**
- * Write out user data header.
- *
- * @param options
- * Options containing information for user data header write-out. The
- * `userDataHeaderLength` property must be correctly pre-calculated.
- */
- writeUserDataHeader: function(options) {
- this.writeHexOctet(options.userDataHeaderLength);
-
- if (options.segmentMaxSeq > 1) {
- if (options.segmentRef16Bit) {
- this.writeHexOctet(PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT);
- this.writeHexOctet(4);
- this.writeHexOctet((options.segmentRef >> 8) & 0xFF);
- } else {
- this.writeHexOctet(PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT);
- this.writeHexOctet(3);
- }
- this.writeHexOctet(options.segmentRef & 0xFF);
- this.writeHexOctet(options.segmentMaxSeq & 0xFF);
- this.writeHexOctet(options.segmentSeq & 0xFF);
- }
-
- if (options.dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- if (options.langIndex != PDU_NL_IDENTIFIER_DEFAULT) {
- this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT);
- this.writeHexOctet(1);
- this.writeHexOctet(options.langIndex);
- }
-
- if (options.langShiftIndex != PDU_NL_IDENTIFIER_DEFAULT) {
- this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT);
- this.writeHexOctet(1);
- this.writeHexOctet(options.langShiftIndex);
- }
- }
- },
-
- /**
- * Read SM-TL Address.
- *
- * @param len
- * Length of useful semi-octets within the Address-Value field. For
- * example, the lenth of "12345" should be 5, and 4 for "1234".
- *
- * @see 3GPP TS 23.040 9.1.2.5
- */
- readAddress: function(len) {
- // Address Length
- if (!len || (len < 0)) {
- if (DEBUG) {
- this.context.debug("PDU error: invalid sender address length: " + len);
- }
- return null;
- }
- if (len % 2 == 1) {
- len += 1;
- }
- if (DEBUG) this.context.debug("PDU: Going to read address: " + len);
-
- // Type-of-Address
- let toa = this.readHexOctet();
- let addr = "";
-
- if ((toa & 0xF0) == PDU_TOA_ALPHANUMERIC) {
- addr = this.readSeptetsToString(Math.floor(len * 4 / 7), 0,
- PDU_NL_IDENTIFIER_DEFAULT , PDU_NL_IDENTIFIER_DEFAULT );
- return addr;
- }
- addr = this.readSwappedNibbleExtendedBcdString(len / 2);
- if (addr.length <= 0) {
- if (DEBUG) this.context.debug("PDU error: no number provided");
- return null;
- }
- if ((toa & 0xF0) == (PDU_TOA_INTERNATIONAL)) {
- addr = '+' + addr;
- }
-
- return addr;
- },
-
- /**
- * Read TP-Protocol-Indicator(TP-PID).
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.040 9.2.3.9
- */
- readProtocolIndicator: function(msg) {
- // `The MS shall interpret reserved, obsolete, or unsupported values as the
- // value 00000000 but shall store them exactly as received.`
- msg.pid = this.readHexOctet();
-
- msg.epid = msg.pid;
- switch (msg.epid & 0xC0) {
- case 0x40:
- // Bit 7..0 = 01xxxxxx
- switch (msg.epid) {
- case PDU_PID_SHORT_MESSAGE_TYPE_0:
- case PDU_PID_ANSI_136_R_DATA:
- case PDU_PID_USIM_DATA_DOWNLOAD:
- return;
- }
- break;
- }
-
- msg.epid = PDU_PID_DEFAULT;
- },
-
- /**
- * Read TP-Data-Coding-Scheme(TP-DCS)
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.040 9.2.3.10, 3GPP TS 23.038 4.
- */
- readDataCodingScheme: function(msg) {
- let dcs = this.readHexOctet();
- if (DEBUG) this.context.debug("PDU: read SMS dcs: " + dcs);
-
- // No message class by default.
- let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
- // 7 bit is the default fallback encoding.
- let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
- case 0x40: // bits 7..4 = 01xx
- case 0x50:
- case 0x60:
- case 0x70:
- // Bit 5..0 are coded exactly the same as Group 00xx
- case 0x00: // bits 7..4 = 00xx
- case 0x10:
- case 0x20:
- case 0x30:
- if (dcs & 0x10) {
- messageClass = dcs & PDU_DCS_MSG_CLASS_BITS;
- }
- switch (dcs & 0x0C) {
- case 0x4:
- encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
- break;
- case 0x8:
- encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
- break;
- }
- break;
-
- case 0xE0: // bits 7..4 = 1110
- encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
- // Bit 3..0 are coded exactly the same as Message Waiting Indication
- // Group 1101.
- // Fall through.
- case 0xC0: // bits 7..4 = 1100
- case 0xD0: // bits 7..4 = 1101
- // Indiciates voicemail indicator set or clear
- let active = (dcs & PDU_DCS_MWI_ACTIVE_BITS) == PDU_DCS_MWI_ACTIVE_VALUE;
-
- // If TP-UDH is present, these values will be overwritten
- switch (dcs & PDU_DCS_MWI_TYPE_BITS) {
- case PDU_DCS_MWI_TYPE_VOICEMAIL:
- let mwi = msg.mwi;
- if (!mwi) {
- mwi = msg.mwi = {};
- }
-
- mwi.active = active;
- mwi.discard = (dcs & PDU_DCS_CODING_GROUP_BITS) == 0xC0;
- mwi.msgCount = active ? GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN : 0;
-
- if (DEBUG) {
- this.context.debug("MWI in DCS received for voicemail: " +
- JSON.stringify(mwi));
- }
- break;
- case PDU_DCS_MWI_TYPE_FAX:
- if (DEBUG) this.context.debug("MWI in DCS received for fax");
- break;
- case PDU_DCS_MWI_TYPE_EMAIL:
- if (DEBUG) this.context.debug("MWI in DCS received for email");
- break;
- default:
- if (DEBUG) this.context.debug("MWI in DCS received for \"other\"");
- break;
- }
- break;
-
- case 0xF0: // bits 7..4 = 1111
- if (dcs & 0x04) {
- encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
- }
- messageClass = dcs & PDU_DCS_MSG_CLASS_BITS;
- break;
-
- default:
- // Falling back to default encoding.
- break;
- }
-
- msg.dcs = dcs;
- msg.encoding = encoding;
- msg.messageClass = GECKO_SMS_MESSAGE_CLASSES[messageClass];
-
- if (DEBUG) this.context.debug("PDU: message encoding is " + encoding + " bit.");
- },
-
- /**
- * Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
- *
- * @see 3GPP TS 23.040 9.2.3.11
- */
- readTimestamp: function() {
- let year = this.readSwappedNibbleBcdNum(1) + PDU_TIMESTAMP_YEAR_OFFSET;
- let month = this.readSwappedNibbleBcdNum(1) - 1;
- let day = this.readSwappedNibbleBcdNum(1);
- let hour = this.readSwappedNibbleBcdNum(1);
- let minute = this.readSwappedNibbleBcdNum(1);
- let second = this.readSwappedNibbleBcdNum(1);
- let timestamp = Date.UTC(year, month, day, hour, minute, second);
-
- // If the most significant bit of the least significant nibble is 1,
- // the timezone offset is negative (fourth bit from the right => 0x08):
- // localtime = UTC + tzOffset
- // therefore
- // UTC = localtime - tzOffset
- let tzOctet = this.readHexOctet();
- let tzOffset = this.octetToBCD(tzOctet & ~0x08) * 15 * 60 * 1000;
- tzOffset = (tzOctet & 0x08) ? -tzOffset : tzOffset;
- timestamp -= tzOffset;
-
- return timestamp;
- },
-
- /**
- * Write GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
- *
- * @see 3GPP TS 23.040 9.2.3.11
- */
- writeTimestamp: function(date) {
- this.writeSwappedNibbleBCDNum(date.getFullYear() - PDU_TIMESTAMP_YEAR_OFFSET);
-
- // The value returned by getMonth() is an integer between 0 and 11.
- // 0 is corresponds to January, 1 to February, and so on.
- this.writeSwappedNibbleBCDNum(date.getMonth() + 1);
- this.writeSwappedNibbleBCDNum(date.getDate());
- this.writeSwappedNibbleBCDNum(date.getHours());
- this.writeSwappedNibbleBCDNum(date.getMinutes());
- this.writeSwappedNibbleBCDNum(date.getSeconds());
-
- // the value returned by getTimezoneOffset() is the difference,
- // in minutes, between UTC and local time.
- // For example, if your time zone is UTC+10 (Australian Eastern Standard Time),
- // -600 will be returned.
- // In TS 23.040 9.2.3.11, the Time Zone field of TP-SCTS indicates
- // the different between the local time and GMT.
- // And expressed in quarters of an hours. (so need to divid by 15)
- let zone = date.getTimezoneOffset() / 15;
- let octet = this.BCDToOctet(zone);
-
- // the bit3 of the Time Zone field represents the algebraic sign.
- // (0: positive, 1: negative).
- // For example, if the time zone is -0800 GMT,
- // 480 will be returned by getTimezoneOffset().
- // In this case, need to mark sign bit as 1. => 0x08
- if (zone > 0) {
- octet = octet | 0x08;
- }
- this.writeHexOctet(octet);
- },
-
- /**
- * User data can be 7 bit (default alphabet) data, 8 bit data, or 16 bit
- * (UCS2) data.
- *
- * @param msg
- * message object for output.
- * @param length
- * length of user data to read in octets.
- */
- readUserData: function(msg, length) {
- if (DEBUG) {
- this.context.debug("Reading " + length + " bytes of user data.");
- }
-
- let paddingBits = 0;
- if (msg.udhi) {
- this.readUserDataHeader(msg);
-
- if (msg.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- let headerBits = (msg.header.length + 1) * 8;
- let headerSeptets = Math.ceil(headerBits / 7);
-
- length -= headerSeptets;
- paddingBits = headerSeptets * 7 - headerBits;
- } else {
- length -= (msg.header.length + 1);
- }
- }
-
- if (DEBUG) {
- this.context.debug("After header, " + length + " septets left of user data");
- }
-
- msg.body = null;
- msg.data = null;
-
- if (length <= 0) {
- // No data to read.
- return;
- }
-
- switch (msg.encoding) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- // 7 bit encoding allows 140 octets, which means 160 characters
- // ((140x8) / 7 = 160 chars)
- if (length > PDU_MAX_USER_DATA_7BIT) {
- if (DEBUG) {
- this.context.debug("PDU error: user data is too long: " + length);
- }
- break;
- }
-
- let langIndex = msg.udhi ? msg.header.langIndex : PDU_NL_IDENTIFIER_DEFAULT;
- let langShiftIndex = msg.udhi ? msg.header.langShiftIndex : PDU_NL_IDENTIFIER_DEFAULT;
- msg.body = this.readSeptetsToString(length, paddingBits, langIndex,
- langShiftIndex);
- break;
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- msg.data = this.readHexOctetArray(length);
- break;
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- msg.body = this.readUCS2String(length);
- break;
- }
- },
-
- /**
- * Read extra parameters if TP-PI is set.
- *
- * @param msg
- * message object for output.
- */
- readExtraParams: function(msg) {
- // Because each PDU octet is converted to two UCS2 char2, we should always
- // get even messageStringLength in this#_processReceivedSms(). So, we'll
- // always need two delimitors at the end.
- if (this.context.Buf.getReadAvailable() <= 4) {
- return;
- }
-
- // TP-Parameter-Indicator
- let pi;
- do {
- // `The most significant bit in octet 1 and any other TP-PI octets which
- // may be added later is reserved as an extension bit which when set to a
- // 1 shall indicate that another TP-PI octet follows immediately
- // afterwards.` ~ 3GPP TS 23.040 9.2.3.27
- pi = this.readHexOctet();
- } while (pi & PDU_PI_EXTENSION);
-
- // `If the TP-UDL bit is set to "1" but the TP-DCS bit is set to "0" then
- // the receiving entity shall for TP-DCS assume a value of 0x00, i.e. the
- // 7bit default alphabet.` ~ 3GPP 23.040 9.2.3.27
- msg.dcs = 0;
- msg.encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
-
- // TP-Protocol-Identifier
- if (pi & PDU_PI_PROTOCOL_IDENTIFIER) {
- this.readProtocolIndicator(msg);
- }
- // TP-Data-Coding-Scheme
- if (pi & PDU_PI_DATA_CODING_SCHEME) {
- this.readDataCodingScheme(msg);
- }
- // TP-User-Data-Length
- if (pi & PDU_PI_USER_DATA_LENGTH) {
- let userDataLength = this.readHexOctet();
- this.readUserData(msg, userDataLength);
- }
- },
-
- /**
- * Read and decode a PDU-encoded message from the stream.
- *
- * TODO: add some basic sanity checks like:
- * - do we have the minimum number of chars available
- */
- readMessage: function() {
- // An empty message object. This gets filled below and then returned.
- let msg = {
- // D:DELIVER, DR:DELIVER-REPORT, S:SUBMIT, SR:SUBMIT-REPORT,
- // ST:STATUS-REPORT, C:COMMAND
- // M:Mandatory, O:Optional, X:Unavailable
- // D DR S SR ST C
- SMSC: null, // M M M M M M
- mti: null, // M M M M M M
- udhi: null, // M M O M M M
- sender: null, // M X X X X X
- recipient: null, // X X M X M M
- pid: null, // M O M O O M
- epid: null, // M O M O O M
- dcs: null, // M O M O O X
- mwi: null, // O O O O O O
- replace: false, // O O O O O O
- header: null, // M M O M M M
- body: null, // M O M O O O
- data: null, // M O M O O O
- sentTimestamp: null, // M X X X X X
- status: null, // X X X X M X
- scts: null, // X X X M M X
- dt: null, // X X X X M X
- };
-
- // SMSC info
- let smscLength = this.readHexOctet();
- if (smscLength > 0) {
- let smscTypeOfAddress = this.readHexOctet();
- // Subtract the type-of-address octet we just read from the length.
- msg.SMSC = this.readSwappedNibbleExtendedBcdString(smscLength - 1);
- if ((smscTypeOfAddress >> 4) == (PDU_TOA_INTERNATIONAL >> 4)) {
- msg.SMSC = '+' + msg.SMSC;
- }
- }
-
- // First octet of this SMS-DELIVER or SMS-SUBMIT message
- let firstOctet = this.readHexOctet();
- // Message Type Indicator
- msg.mti = firstOctet & 0x03;
- // User data header indicator
- msg.udhi = firstOctet & PDU_UDHI;
-
- switch (msg.mti) {
- case PDU_MTI_SMS_RESERVED:
- // `If an MS receives a TPDU with a "Reserved" value in the TP-MTI it
- // shall process the message as if it were an "SMS-DELIVER" but store
- // the message exactly as received.` ~ 3GPP TS 23.040 9.2.3.1
- case PDU_MTI_SMS_DELIVER:
- return this.readDeliverMessage(msg);
- case PDU_MTI_SMS_STATUS_REPORT:
- return this.readStatusReportMessage(msg);
- default:
- return null;
- }
- },
-
- /**
- * Helper for processing received SMS parcel data.
- *
- * @param length
- * Length of SMS string in the incoming parcel.
- *
- * @return Message parsed or null for invalid message.
- */
- processReceivedSms: function(length) {
- if (!length) {
- if (DEBUG) this.context.debug("Received empty SMS!");
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- let Buf = this.context.Buf;
-
- // An SMS is a string, but we won't read it as such, so let's read the
- // string length and then defer to PDU parsing helper.
- let messageStringLength = Buf.readInt32();
- if (DEBUG) this.context.debug("Got new SMS, length " + messageStringLength);
- let message = this.readMessage();
- if (DEBUG) this.context.debug("Got new SMS: " + JSON.stringify(message));
-
- // Read string delimiters. See Buf.readString().
- Buf.readStringDelimiter(length);
-
- // Determine result
- if (!message) {
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- if (message.epid == PDU_PID_SHORT_MESSAGE_TYPE_0) {
- // `A short message type 0 indicates that the ME must acknowledge receipt
- // of the short message but shall discard its contents.` ~ 3GPP TS 23.040
- // 9.2.3.9
- return [null, PDU_FCS_OK];
- }
-
- if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
- let RIL = this.context.RIL;
- switch (message.epid) {
- case PDU_PID_ANSI_136_R_DATA:
- case PDU_PID_USIM_DATA_DOWNLOAD:
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- if (ICCUtilsHelper.isICCServiceAvailable("DATA_DOWNLOAD_SMS_PP")) {
- // `If the service "data download via SMS Point-to-Point" is
- // allocated and activated in the (U)SIM Service Table, ... then the
- // ME shall pass the message transparently to the UICC using the
- // ENVELOPE (SMS-PP DOWNLOAD).` ~ 3GPP TS 31.111 7.1.1.1
- RIL.dataDownloadViaSMSPP(message);
-
- // `the ME shall not display the message, or alert the user of a
- // short message waiting.` ~ 3GPP TS 31.111 7.1.1.1
- return [null, PDU_FCS_RESERVED];
- }
-
- // If the service "data download via SMS-PP" is not available in the
- // (U)SIM Service Table, ..., then the ME shall store the message in
- // EFsms in accordance with TS 31.102` ~ 3GPP TS 31.111 7.1.1.1
-
- // Fall through.
- default:
- RIL.writeSmsToSIM(message);
- break;
- }
- }
-
- // TODO: Bug 739143: B2G SMS: Support SMS Storage Full event
- if ((message.messageClass != GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]) && !true) {
- // `When a mobile terminated message is class 0..., the MS shall display
- // the message immediately and send a ACK to the SC ..., irrespective of
- // whether there is memory available in the (U)SIM or ME.` ~ 3GPP 23.038
- // clause 4.
-
- if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
- // `If all the short message storage at the MS is already in use, the
- // MS shall return "memory capacity exceeded".` ~ 3GPP 23.038 clause 4.
- return [null, PDU_FCS_MEMORY_CAPACITY_EXCEEDED];
- }
-
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- return [message, PDU_FCS_OK];
- },
-
- /**
- * Read and decode a SMS-DELIVER PDU.
- *
- * @param msg
- * message object for output.
- */
- readDeliverMessage: function(msg) {
- // - Sender Address info -
- let senderAddressLength = this.readHexOctet();
- msg.sender = this.readAddress(senderAddressLength);
- // - TP-Protocolo-Identifier -
- this.readProtocolIndicator(msg);
- // - TP-Data-Coding-Scheme -
- this.readDataCodingScheme(msg);
- // - TP-Service-Center-Time-Stamp -
- msg.sentTimestamp = this.readTimestamp();
- // - TP-User-Data-Length -
- let userDataLength = this.readHexOctet();
-
- // - TP-User-Data -
- if (userDataLength > 0) {
- this.readUserData(msg, userDataLength);
- }
-
- return msg;
- },
-
- /**
- * Read and decode a SMS-STATUS-REPORT PDU.
- *
- * @param msg
- * message object for output.
- */
- readStatusReportMessage: function(msg) {
- // TP-Message-Reference
- msg.messageRef = this.readHexOctet();
- // TP-Recipient-Address
- let recipientAddressLength = this.readHexOctet();
- msg.recipient = this.readAddress(recipientAddressLength);
- // TP-Service-Centre-Time-Stamp
- msg.scts = this.readTimestamp();
- // TP-Discharge-Time
- msg.dt = this.readTimestamp();
- // TP-Status
- msg.status = this.readHexOctet();
-
- this.readExtraParams(msg);
-
- return msg;
- },
-
- /**
- * Serialize a SMS-SUBMIT PDU message and write it to the output stream.
- *
- * This method expects that a data coding scheme has been chosen already
- * and that the length of the user data payload in that encoding is known,
- * too. Both go hand in hand together anyway.
- *
- * @param address
- * String containing the address (number) of the SMS receiver
- * @param userData
- * String containing the message to be sent as user data
- * @param dcs
- * Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET
- * constants.
- * @param userDataHeaderLength
- * Length of embedded user data header, in bytes. The whole header
- * size will be userDataHeaderLength + 1; 0 for no header.
- * @param encodedBodyLength
- * Length of the user data when encoded with the given DCS. For UCS2,
- * in bytes; for 7-bit, in septets.
- * @param langIndex
- * Table index used for normal 7-bit encoded character lookup.
- * @param langShiftIndex
- * Table index used for escaped 7-bit encoded character lookup.
- * @param requestStatusReport
- * Request status report.
- */
- writeMessage: function(options) {
- if (DEBUG) {
- this.context.debug("writeMessage: " + JSON.stringify(options));
- }
- let Buf = this.context.Buf;
- let address = options.number;
- let body = options.body;
- let dcs = options.dcs;
- let userDataHeaderLength = options.userDataHeaderLength;
- let encodedBodyLength = options.encodedBodyLength;
- let langIndex = options.langIndex;
- let langShiftIndex = options.langShiftIndex;
-
- // SMS-SUBMIT Format:
- //
- // PDU Type - 1 octet
- // Message Reference - 1 octet
- // DA - Destination Address - 2 to 12 octets
- // PID - Protocol Identifier - 1 octet
- // DCS - Data Coding Scheme - 1 octet
- // VP - Validity Period - 0, 1 or 7 octets
- // UDL - User Data Length - 1 octet
- // UD - User Data - 140 octets
-
- let addressFormat = PDU_TOA_ISDN; // 81
- if (address[0] == '+') {
- addressFormat = PDU_TOA_INTERNATIONAL | PDU_TOA_ISDN; // 91
- address = address.substring(1);
- }
- //TODO validity is unsupported for now
- let validity = 0;
-
- let headerOctets = (userDataHeaderLength ? userDataHeaderLength + 1 : 0);
- let paddingBits;
- let userDataLengthInSeptets;
- let userDataLengthInOctets;
- if (dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- let headerSeptets = Math.ceil(headerOctets * 8 / 7);
- userDataLengthInSeptets = headerSeptets + encodedBodyLength;
- userDataLengthInOctets = Math.ceil(userDataLengthInSeptets * 7 / 8);
- paddingBits = headerSeptets * 7 - headerOctets * 8;
- } else {
- userDataLengthInOctets = headerOctets + encodedBodyLength;
- paddingBits = 0;
- }
-
- let pduOctetLength = 4 + // PDU Type, Message Ref, address length + format
- Math.ceil(address.length / 2) +
- 3 + // PID, DCS, UDL
- userDataLengthInOctets;
- if (validity) {
- //TODO: add more to pduOctetLength
- }
-
- // Start the string. Since octets are represented in hex, we will need
- // twice as many characters as octets.
- Buf.writeInt32(pduOctetLength * 2);
-
- // - PDU-TYPE-
-
- // +--------+----------+---------+---------+--------+---------+
- // | RP (1) | UDHI (1) | SRR (1) | VPF (2) | RD (1) | MTI (2) |
- // +--------+----------+---------+---------+--------+---------+
- // RP: 0 Reply path parameter is not set
- // 1 Reply path parameter is set
- // UDHI: 0 The UD Field contains only the short message
- // 1 The beginning of the UD field contains a header in addition
- // of the short message
- // SRR: 0 A status report is not requested
- // 1 A status report is requested
- // VPF: bit4 bit3
- // 0 0 VP field is not present
- // 0 1 Reserved
- // 1 0 VP field present an integer represented (relative)
- // 1 1 VP field present a semi-octet represented (absolute)
- // RD: Instruct the SMSC to accept(0) or reject(1) an SMS-SUBMIT
- // for a short message still held in the SMSC which has the same
- // MR and DA as a previously submitted short message from the
- // same OA
- // MTI: bit1 bit0 Message Type
- // 0 0 SMS-DELIVER (SMSC ==> MS)
- // 0 1 SMS-SUBMIT (MS ==> SMSC)
-
- // PDU type. MTI is set to SMS-SUBMIT
- let firstOctet = PDU_MTI_SMS_SUBMIT;
-
- // Status-Report-Request
- if (options.requestStatusReport) {
- firstOctet |= PDU_SRI_SRR;
- }
-
- // Validity period
- if (validity) {
- //TODO: not supported yet, OR with one of PDU_VPF_*
- }
- // User data header indicator
- if (headerOctets) {
- firstOctet |= PDU_UDHI;
- }
- this.writeHexOctet(firstOctet);
-
- // Message reference 00
- this.writeHexOctet(0x00);
-
- // - Destination Address -
- this.writeHexOctet(address.length);
- this.writeHexOctet(addressFormat);
- this.writeSwappedNibbleBCD(address);
-
- // - Protocol Identifier -
- this.writeHexOctet(0x00);
-
- // - Data coding scheme -
- // For now it assumes bits 7..4 = 1111 except for the 16 bits use case
- this.writeHexOctet(dcs);
-
- // - Validity Period -
- if (validity) {
- this.writeHexOctet(validity);
- }
-
- // - User Data -
- if (dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- this.writeHexOctet(userDataLengthInSeptets);
- } else {
- this.writeHexOctet(userDataLengthInOctets);
- }
-
- if (headerOctets) {
- this.writeUserDataHeader(options);
- }
-
- switch (dcs) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- this.writeStringAsSeptets(body, paddingBits, langIndex, langShiftIndex);
- break;
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- // Unsupported.
- break;
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- this.writeUCS2String(body);
- break;
- }
-
- // End of the string. The string length is always even by definition, so
- // we write two \0 delimiters.
- Buf.writeUint16(0);
- Buf.writeUint16(0);
- },
-
- /**
- * Read GSM CBS message serial number.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.1
- */
- readCbSerialNumber: function(msg) {
- let Buf = this.context.Buf;
- msg.serial = Buf.readUint8() << 8 | Buf.readUint8();
- msg.geographicalScope = (msg.serial >>> 14) & 0x03;
- msg.messageCode = (msg.serial >>> 4) & 0x03FF;
- msg.updateNumber = msg.serial & 0x0F;
- },
-
- /**
- * Read GSM CBS message message identifier.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.2
- */
- readCbMessageIdentifier: function(msg) {
- let Buf = this.context.Buf;
- msg.messageId = Buf.readUint8() << 8 | Buf.readUint8();
- },
-
- /**
- * Read ETWS information from message identifier and serial Number
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.1 & 9.4.1.2.2
- */
- readCbEtwsInfo: function(msg) {
- if ((msg.format != CB_FORMAT_ETWS)
- && (msg.messageId >= CB_GSM_MESSAGEID_ETWS_BEGIN)
- && (msg.messageId <= CB_GSM_MESSAGEID_ETWS_END)) {
- // `In the case of transmitting CBS message for ETWS, a part of
- // Message Code can be used to command mobile terminals to activate
- // emergency user alert and message popup in order to alert the users.`
- msg.etws = {
- emergencyUserAlert: msg.messageCode & 0x0200 ? true : false,
- popup: msg.messageCode & 0x0100 ? true : false
- };
-
- let warningType = msg.messageId - CB_GSM_MESSAGEID_ETWS_BEGIN;
- if (warningType < CB_ETWS_WARNING_TYPE_NAMES.length) {
- msg.etws.warningType = warningType;
- }
- }
- },
-
- /**
- * Read CBS Data Coding Scheme.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.038 section 5.
- */
- readCbDataCodingScheme: function(msg) {
- let dcs = this.context.Buf.readUint8();
- if (DEBUG) this.context.debug("PDU: read CBS dcs: " + dcs);
-
- let language = null, hasLanguageIndicator = false;
- // `Any reserved codings shall be assumed to be the GSM 7bit default
- // alphabet.`
- let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
-
- switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
- case 0x00: // 0000
- language = CB_DCS_LANG_GROUP_1[dcs & 0x0F];
- break;
-
- case 0x10: // 0001
- switch (dcs & 0x0F) {
- case 0x00:
- hasLanguageIndicator = true;
- break;
- case 0x01:
- encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
- hasLanguageIndicator = true;
- break;
- }
- break;
-
- case 0x20: // 0010
- language = CB_DCS_LANG_GROUP_2[dcs & 0x0F];
- break;
-
- case 0x40: // 01xx
- case 0x50:
- //case 0x60: Text Compression, not supported
- //case 0x70: Text Compression, not supported
- case 0x90: // 1001
- encoding = (dcs & 0x0C);
- if (encoding == 0x0C) {
- encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- }
- messageClass = (dcs & PDU_DCS_MSG_CLASS_BITS);
- break;
-
- case 0xF0:
- encoding = (dcs & 0x04) ? PDU_DCS_MSG_CODING_8BITS_ALPHABET
- : PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- switch(dcs & PDU_DCS_MSG_CLASS_BITS) {
- case 0x01: messageClass = PDU_DCS_MSG_CLASS_USER_1; break;
- case 0x02: messageClass = PDU_DCS_MSG_CLASS_USER_2; break;
- case 0x03: messageClass = PDU_DCS_MSG_CLASS_3; break;
- }
- break;
-
- case 0x30: // 0011 (Reserved)
- case 0x80: // 1000 (Reserved)
- case 0xA0: // 1010..1100 (Reserved)
- case 0xB0:
- case 0xC0:
- break;
-
- default:
- throw new Error("Unsupported CBS data coding scheme: " + dcs);
- }
-
- msg.dcs = dcs;
- msg.encoding = encoding;
- msg.language = language;
- msg.messageClass = GECKO_SMS_MESSAGE_CLASSES[messageClass];
- msg.hasLanguageIndicator = hasLanguageIndicator;
- },
-
- /**
- * Read GSM CBS message page parameter.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.4
- */
- readCbPageParameter: function(msg) {
- let octet = this.context.Buf.readUint8();
- msg.pageIndex = (octet >>> 4) & 0x0F;
- msg.numPages = octet & 0x0F;
- if (!msg.pageIndex || !msg.numPages) {
- // `If a mobile receives the code 0000 in either the first field or the
- // second field then it shall treat the CBS message exactly the same as a
- // CBS message with page parameter 0001 0001 (i.e. a single page message).`
- msg.pageIndex = msg.numPages = 1;
- }
- },
-
- /**
- * Read ETWS Primary Notification message warning type.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.3.24
- */
- readCbWarningType: function(msg) {
- let Buf = this.context.Buf;
- let word = Buf.readUint8() << 8 | Buf.readUint8();
- msg.etws = {
- warningType: (word >>> 9) & 0x7F,
- popup: word & 0x80 ? true : false,
- emergencyUserAlert: word & 0x100 ? true : false
- };
- },
-
- /**
- * Read GSM CB Data
- *
- * This parameter is a copy of the 'CBS-Message-Information-Page' as sent
- * from the CBC to the BSC.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.5
- */
- readGsmCbData: function(msg, length) {
- let Buf = this.context.Buf;
- let bufAdapter = {
- context: this.context,
- readHexOctet: function() {
- return Buf.readUint8();
- }
- };
-
- msg.body = null;
- msg.data = null;
- switch (msg.encoding) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- msg.body = this.readSeptetsToString.call(bufAdapter,
- Math.floor(length * 8 / 7), 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- if (msg.hasLanguageIndicator) {
- msg.language = msg.body.substring(0, 2);
- msg.body = msg.body.substring(3);
- }
- break;
-
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- msg.data = Buf.readUint8Array(length);
- break;
-
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- if (msg.hasLanguageIndicator) {
- msg.language = this.readSeptetsToString.call(bufAdapter, 2, 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- length -= 2;
- }
- msg.body = this.readUCS2String.call(bufAdapter, length);
- break;
- }
-
- if (msg.data || !msg.body) {
- return;
- }
-
- // According to 9.3.19 CBS-Message-Information-Page in TS 23.041:
- // "
- // This parameter is of a fixed length of 82 octets and carries up to and
- // including 82 octets of user information. Where the user information is
- // less than 82 octets, the remaining octets must be filled with padding.
- // "
- // According to 6.2.1.1 GSM 7 bit Default Alphabet and 6.2.3 UCS2 in
- // TS 23.038, the padding character is <CR>.
- for (let i = msg.body.length - 1; i >= 0; i--) {
- if (msg.body.charAt(i) !== '\r') {
- msg.body = msg.body.substring(0, i + 1);
- break;
- }
- }
- },
-
- /**
- * Read UMTS CB Data
- *
- * Octet Number(s) Parameter
- * 1 Number-of-Pages
- * 2 - 83 CBS-Message-Information-Page 1
- * 84 CBS-Message-Information-Length 1
- * ...
- * CBS-Message-Information-Page n
- * CBS-Message-Information-Length n
- *
- * @see 3GPP TS 23.041 section 9.4.2.2.5
- */
- readUmtsCbData: function(msg) {
- let Buf = this.context.Buf;
- let numOfPages = Buf.readUint8();
- if (numOfPages < 0 || numOfPages > 15) {
- throw new Error("Invalid numOfPages: " + numOfPages);
- }
-
- let bufAdapter = {
- context: this.context,
- readHexOctet: function() {
- return Buf.readUint8();
- }
- };
-
- let removePaddingCharactors = function (text) {
- for (let i = text.length - 1; i >= 0; i--) {
- if (text.charAt(i) !== '\r') {
- return text.substring(0, i + 1);
- }
- }
- return text;
- };
-
- let totalLength = 0, length, pageLengths = [];
- for (let i = 0; i < numOfPages; i++) {
- Buf.seekIncoming(CB_MSG_PAGE_INFO_SIZE);
- length = Buf.readUint8();
- totalLength += length;
- pageLengths.push(length);
- }
-
- // Seek back to beginning of CB Data.
- Buf.seekIncoming(-numOfPages * (CB_MSG_PAGE_INFO_SIZE + 1));
-
- switch (msg.encoding) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET: {
- let body;
- msg.body = "";
- for (let i = 0; i < numOfPages; i++) {
- body = this.readSeptetsToString.call(bufAdapter,
- Math.floor(pageLengths[i] * 8 / 7),
- 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- if (msg.hasLanguageIndicator) {
- if (!msg.language) {
- msg.language = body.substring(0, 2);
- }
- body = body.substring(3);
- }
-
- msg.body += removePaddingCharactors(body);
-
- // Skip padding octets
- Buf.seekIncoming(CB_MSG_PAGE_INFO_SIZE - pageLengths[i]);
- // Read the octet of CBS-Message-Information-Length
- Buf.readUint8();
- }
-
- break;
- }
-
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET: {
- msg.data = new Uint8Array(totalLength);
- for (let i = 0, j = 0; i < numOfPages; i++) {
- for (let pageLength = pageLengths[i]; pageLength > 0; pageLength--) {
- msg.data[j++] = Buf.readUint8();
- }
-
- // Skip padding octets
- Buf.seekIncoming(CB_MSG_PAGE_INFO_SIZE - pageLengths[i]);
- // Read the octet of CBS-Message-Information-Length
- Buf.readUint8();
- }
-
- break;
- }
-
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET: {
- msg.body = "";
- for (let i = 0; i < numOfPages; i++) {
- let pageLength = pageLengths[i];
- if (msg.hasLanguageIndicator) {
- if (!msg.language) {
- msg.language = this.readSeptetsToString.call(bufAdapter,
- 2,
- 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- } else {
- Buf.readUint16();
- }
-
- pageLength -= 2;
- }
-
- msg.body += removePaddingCharactors(
- this.readUCS2String.call(bufAdapter, pageLength));
-
- // Skip padding octets
- Buf.seekIncoming(CB_MSG_PAGE_INFO_SIZE - pageLengths[i]);
- // Read the octet of CBS-Message-Information-Length
- Buf.readUint8();
- }
-
- break;
- }
- }
- },
-
- /**
- * Read Cell GSM/ETWS/UMTS Broadcast Message.
- *
- * @param pduLength
- * total length of the incoming PDU in octets.
- */
- readCbMessage: function(pduLength) {
- // Validity GSM ETWS UMTS
- let msg = {
- // Internally used in ril_worker:
- serial: null, // O O O
- updateNumber: null, // O O O
- format: null, // O O O
- dcs: 0x0F, // O X O
- encoding: PDU_DCS_MSG_CODING_7BITS_ALPHABET, // O X O
- hasLanguageIndicator: false, // O X O
- data: null, // O X O
- body: null, // O X O
- pageIndex: 1, // O X X
- numPages: 1, // O X X
-
- // DOM attributes:
- geographicalScope: null, // O O O
- messageCode: null, // O O O
- messageId: null, // O O O
- language: null, // O X O
- fullBody: null, // O X O
- fullData: null, // O X O
- messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL], // O x O
- etws: null // ? O ?
- /*{
- warningType: null, // X O X
- popup: false, // X O X
- emergencyUserAlert: false, // X O X
- }*/
- };
-
- if (pduLength <= CB_MESSAGE_SIZE_ETWS) {
- msg.format = CB_FORMAT_ETWS;
- return this.readEtwsCbMessage(msg);
- }
-
- if (pduLength <= CB_MESSAGE_SIZE_GSM) {
- msg.format = CB_FORMAT_GSM;
- return this.readGsmCbMessage(msg, pduLength);
- }
-
- if (pduLength >= CB_MESSAGE_SIZE_UMTS_MIN &&
- pduLength <= CB_MESSAGE_SIZE_UMTS_MAX) {
- msg.format = CB_FORMAT_UMTS;
- return this.readUmtsCbMessage(msg);
- }
-
- throw new Error("Invalid PDU Length: " + pduLength);
- },
-
- /**
- * Read UMTS CBS Message.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.2
- * @see 3GPP TS 25.324 section 10.2
- */
- readUmtsCbMessage: function(msg) {
- let Buf = this.context.Buf;
- let type = Buf.readUint8();
- if (type != CB_UMTS_MESSAGE_TYPE_CBS) {
- throw new Error("Unsupported UMTS Cell Broadcast message type: " + type);
- }
-
- this.readCbMessageIdentifier(msg);
- this.readCbSerialNumber(msg);
- this.readCbEtwsInfo(msg);
- this.readCbDataCodingScheme(msg);
- this.readUmtsCbData(msg);
-
- return msg;
- },
-
- /**
- * Read GSM Cell Broadcast Message.
- *
- * @param msg
- * message object for output.
- * @param pduLength
- * total length of the incomint PDU in octets.
- *
- * @see 3GPP TS 23.041 clause 9.4.1.2
- */
- readGsmCbMessage: function(msg, pduLength) {
- this.readCbSerialNumber(msg);
- this.readCbMessageIdentifier(msg);
- this.readCbEtwsInfo(msg);
- this.readCbDataCodingScheme(msg);
- this.readCbPageParameter(msg);
-
- // GSM CB message header takes 6 octets.
- this.readGsmCbData(msg, pduLength - 6);
-
- return msg;
- },
-
- /**
- * Read ETWS Primary Notification Message.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 clause 9.4.1.3
- */
- readEtwsCbMessage: function(msg) {
- this.readCbSerialNumber(msg);
- this.readCbMessageIdentifier(msg);
- this.readCbWarningType(msg);
-
- // Octet 7..56 is Warning Security Information. However, according to
- // section 9.4.1.3.6, `The UE shall ignore this parameter.` So we just skip
- // processing it here.
-
- return msg;
- },
-
- /**
- * Read network name.
- *
- * @param len Length of the information element.
- * @return
- * {
- * networkName: network name.
- * shouldIncludeCi: Should Country's initials included in text string.
- * }
- * @see TS 24.008 clause 10.5.3.5a.
- */
- readNetworkName: function(len) {
- // According to TS 24.008 Sec. 10.5.3.5a, the first octet is:
- // bit 8: must be 1.
- // bit 5-7: Text encoding.
- // 000 - GSM default alphabet.
- // 001 - UCS2 (16 bit).
- // else - reserved.
- // bit 4: MS should add the letters for Country's Initials and a space
- // to the text string if this bit is true.
- // bit 1-3: number of spare bits in last octet.
-
- let codingInfo = this.readHexOctet();
- if (!(codingInfo & 0x80)) {
- return null;
- }
-
- let textEncoding = (codingInfo & 0x70) >> 4;
- let shouldIncludeCountryInitials = !!(codingInfo & 0x08);
- let spareBits = codingInfo & 0x07;
- let resultString;
-
- switch (textEncoding) {
- case 0:
- // GSM Default alphabet.
- resultString = this.readSeptetsToString(
- Math.floor(((len - 1) * 8 - spareBits) / 7), 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- break;
- case 1:
- // UCS2 encoded.
- resultString = this.context.ICCPDUHelper.readAlphaIdentifier(len - 1);
- break;
- default:
- // Not an available text coding.
- return null;
- }
-
- // TODO - Bug 820286: According to shouldIncludeCountryInitials, add
- // country initials to the resulting string.
- return resultString;
- }
-};
-
-/**
- * Provide buffer with bitwise read/write function so make encoding/decoding easier.
- */
-function BitBufferHelperObject(/* unused */aContext) {
- this.readBuffer = [];
- this.writeBuffer = [];
-}
-BitBufferHelperObject.prototype = {
- readCache: 0,
- readCacheSize: 0,
- readBuffer: null,
- readIndex: 0,
- writeCache: 0,
- writeCacheSize: 0,
- writeBuffer: null,
-
- // Max length is 32 because we use integer as read/write cache.
- // All read/write functions are implemented based on bitwise operation.
- readBits: function(length) {
- if (length <= 0 || length > 32) {
- return null;
- }
-
- if (length > this.readCacheSize) {
- let bytesToRead = Math.ceil((length - this.readCacheSize) / 8);
- for(let i = 0; i < bytesToRead; i++) {
- this.readCache = (this.readCache << 8) | (this.readBuffer[this.readIndex++] & 0xFF);
- this.readCacheSize += 8;
- }
- }
-
- let bitOffset = (this.readCacheSize - length),
- resultMask = (1 << length) - 1,
- result = 0;
-
- result = (this.readCache >> bitOffset) & resultMask;
- this.readCacheSize -= length;
-
- return result;
- },
-
- backwardReadPilot: function(length) {
- if (length <= 0) {
- return;
- }
-
- // Zero-based position.
- let bitIndexToRead = this.readIndex * 8 - this.readCacheSize - length;
-
- if (bitIndexToRead < 0) {
- return;
- }
-
- // Update readIndex, readCache, readCacheSize accordingly.
- let readBits = bitIndexToRead % 8;
- this.readIndex = Math.floor(bitIndexToRead / 8) + ((readBits) ? 1 : 0);
- this.readCache = (readBits) ? this.readBuffer[this.readIndex - 1] : 0;
- this.readCacheSize = (readBits) ? (8 - readBits) : 0;
- },
-
- writeBits: function(value, length) {
- if (length <= 0 || length > 32) {
- return;
- }
-
- let totalLength = length + this.writeCacheSize;
-
- // 8-byte cache not full
- if (totalLength < 8) {
- let valueMask = (1 << length) - 1;
- this.writeCache = (this.writeCache << length) | (value & valueMask);
- this.writeCacheSize += length;
- return;
- }
-
- // Deal with unaligned part
- if (this.writeCacheSize) {
- let mergeLength = 8 - this.writeCacheSize,
- valueMask = (1 << mergeLength) - 1;
-
- this.writeCache = (this.writeCache << mergeLength) | ((value >> (length - mergeLength)) & valueMask);
- this.writeBuffer.push(this.writeCache & 0xFF);
- length -= mergeLength;
- }
-
- // Aligned part, just copy
- while (length >= 8) {
- length -= 8;
- this.writeBuffer.push((value >> length) & 0xFF);
- }
-
- // Rest part is saved into cache
- this.writeCacheSize = length;
- this.writeCache = value & ((1 << length) - 1);
-
- return;
- },
-
- // Drop what still in read cache and goto next 8-byte alignment.
- // There might be a better naming.
- nextOctetAlign: function() {
- this.readCache = 0;
- this.readCacheSize = 0;
- },
-
- // Flush current write cache to Buf with padding 0s.
- // There might be a better naming.
- flushWithPadding: function() {
- if (this.writeCacheSize) {
- this.writeBuffer.push(this.writeCache << (8 - this.writeCacheSize));
- }
- this.writeCache = 0;
- this.writeCacheSize = 0;
- },
-
- startWrite: function(dataBuffer) {
- this.writeBuffer = dataBuffer;
- this.writeCache = 0;
- this.writeCacheSize = 0;
- },
-
- startRead: function(dataBuffer) {
- this.readBuffer = dataBuffer;
- this.readCache = 0;
- this.readCacheSize = 0;
- this.readIndex = 0;
- },
-
- getWriteBufferSize: function() {
- return this.writeBuffer.length;
- },
-
- overwriteWriteBuffer: function(position, data) {
- let writeLength = data.length;
- if (writeLength + position >= this.writeBuffer.length) {
- writeLength = this.writeBuffer.length - position;
- }
- for (let i = 0; i < writeLength; i++) {
- this.writeBuffer[i + position] = data[i];
- }
- }
-};
-
-/**
- * Helper for CDMA PDU
- *
- * Currently, some function are shared with GsmPDUHelper, they should be
- * moved from GsmPDUHelper to a common object shared among GsmPDUHelper and
- * CdmaPDUHelper.
- */
-function CdmaPDUHelperObject(aContext) {
- this.context = aContext;
-}
-CdmaPDUHelperObject.prototype = {
- context: null,
-
- // 1..........C
- // Only "1234567890*#" is defined in C.S0005-D v2.0
- dtmfChars: ".1234567890*#...",
-
- /**
- * Entry point for SMS encoding, the options object is made compatible
- * with existing writeMessage() of GsmPDUHelper, but less key is used.
- *
- * Current used key in options:
- * @param number
- * String containing the address (number) of the SMS receiver
- * @param body
- * String containing the message to be sent, segmented part
- * @param dcs
- * Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET
- * constants.
- * @param encodedBodyLength
- * Length of the user data when encoded with the given DCS. For UCS2,
- * in bytes; for 7-bit, in septets.
- * @param requestStatusReport
- * Request status report.
- * @param segmentRef
- * Reference number of concatenated SMS message
- * @param segmentMaxSeq
- * Total number of concatenated SMS message
- * @param segmentSeq
- * Sequence number of concatenated SMS message
- */
- writeMessage: function(options) {
- if (DEBUG) {
- this.context.debug("cdma_writeMessage: " + JSON.stringify(options));
- }
-
- // Get encoding
- options.encoding = this.gsmDcsToCdmaEncoding(options.dcs);
-
- // Common Header
- if (options.segmentMaxSeq > 1) {
- this.writeInt(PDU_CDMA_MSG_TELESERIVCIE_ID_WEMT);
- } else {
- this.writeInt(PDU_CDMA_MSG_TELESERIVCIE_ID_SMS);
- }
-
- this.writeInt(0);
- this.writeInt(PDU_CDMA_MSG_CATEGORY_UNSPEC);
-
- // Just fill out address info in byte, rild will encap them for us
- let addrInfo = this.encodeAddr(options.number);
- this.writeByte(addrInfo.digitMode);
- this.writeByte(addrInfo.numberMode);
- this.writeByte(addrInfo.numberType);
- this.writeByte(addrInfo.numberPlan);
- this.writeByte(addrInfo.address.length);
- for (let i = 0; i < addrInfo.address.length; i++) {
- this.writeByte(addrInfo.address[i]);
- }
-
- // Subaddress, not supported
- this.writeByte(0); // Subaddress : Type
- this.writeByte(0); // Subaddress : Odd
- this.writeByte(0); // Subaddress : length
-
- // User Data
- let encodeResult = this.encodeUserData(options);
- this.writeByte(encodeResult.length);
- for (let i = 0; i < encodeResult.length; i++) {
- this.writeByte(encodeResult[i]);
- }
-
- encodeResult = null;
- },
-
- /**
- * Data writters
- */
- writeInt: function(value) {
- this.context.Buf.writeInt32(value);
- },
-
- writeByte: function(value) {
- this.context.Buf.writeInt32(value & 0xFF);
- },
-
- /**
- * Transform GSM DCS to CDMA encoding.
- */
- gsmDcsToCdmaEncoding: function(encoding) {
- switch (encoding) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- return PDU_CDMA_MSG_CODING_7BITS_ASCII;
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- return PDU_CDMA_MSG_CODING_OCTET;
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- return PDU_CDMA_MSG_CODING_UNICODE;
- }
- throw new Error("gsmDcsToCdmaEncoding(): Invalid GSM SMS DCS value: " + encoding);
- },
-
- /**
- * Encode address into CDMA address format, as a byte array.
- *
- * @see 3GGP2 C.S0015-B 2.0, 3.4.3.3 Address Parameters
- *
- * @param address
- * String of address to be encoded
- */
- encodeAddr: function(address) {
- let result = {};
-
- result.numberType = PDU_CDMA_MSG_ADDR_NUMBER_TYPE_UNKNOWN;
- result.numberPlan = PDU_CDMA_MSG_ADDR_NUMBER_TYPE_UNKNOWN;
-
- if (address[0] === '+') {
- address = address.substring(1);
- }
-
- // Try encode with DTMF first
- result.digitMode = PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF;
- result.numberMode = PDU_CDMA_MSG_ADDR_NUMBER_MODE_ANSI;
-
- result.address = [];
- for (let i = 0; i < address.length; i++) {
- let addrDigit = this.dtmfChars.indexOf(address.charAt(i));
- if (addrDigit < 0) {
- result.digitMode = PDU_CDMA_MSG_ADDR_DIGIT_MODE_ASCII;
- result.numberMode = PDU_CDMA_MSG_ADDR_NUMBER_MODE_ASCII;
- result.address = [];
- break;
- }
- result.address.push(addrDigit);
- }
-
- // Address can't be encoded with DTMF, then use 7-bit ASCII
- if (result.digitMode !== PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF) {
- if (address.indexOf("@") !== -1) {
- result.numberType = PDU_CDMA_MSG_ADDR_NUMBER_TYPE_NATIONAL;
- }
-
- for (let i = 0; i < address.length; i++) {
- result.address.push(address.charCodeAt(i) & 0x7F);
- }
- }
-
- return result;
- },
-
- /**
- * Encode SMS contents in options into CDMA userData field.
- * Corresponding and required subparameters will be added automatically.
- *
- * @see 3GGP2 C.S0015-B 2.0, 3.4.3.7 Bearer Data
- * 4.5 Bearer Data Parameters
- *
- * Current used key in options:
- * @param body
- * String containing the message to be sent, segmented part
- * @param encoding
- * Encoding method of CDMA, can be transformed from GSM DCS by function
- * cdmaPduHelp.gsmDcsToCdmaEncoding()
- * @param encodedBodyLength
- * Length of the user data when encoded with the given DCS. For UCS2,
- * in bytes; for 7-bit, in septets.
- * @param requestStatusReport
- * Request status report.
- * @param segmentRef
- * Reference number of concatenated SMS message
- * @param segmentMaxSeq
- * Total number of concatenated SMS message
- * @param segmentSeq
- * Sequence number of concatenated SMS message
- */
- encodeUserData: function(options) {
- let userDataBuffer = [];
- this.context.BitBufferHelper.startWrite(userDataBuffer);
-
- // Message Identifier
- this.encodeUserDataMsgId(options);
-
- // User Data
- this.encodeUserDataMsg(options);
-
- // Reply Option
- this.encodeUserDataReplyOption(options);
-
- return userDataBuffer;
- },
-
- /**
- * User data subparameter encoder : Message Identifier
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.1 Message Identifier
- */
- encodeUserDataMsgId: function(options) {
- let BitBufferHelper = this.context.BitBufferHelper;
- BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_MSG_ID, 8);
- BitBufferHelper.writeBits(3, 8);
- BitBufferHelper.writeBits(PDU_CDMA_MSG_TYPE_SUBMIT, 4);
- BitBufferHelper.writeBits(1, 16); // TODO: How to get message ID?
- if (options.segmentMaxSeq > 1) {
- BitBufferHelper.writeBits(1, 1);
- } else {
- BitBufferHelper.writeBits(0, 1);
- }
-
- BitBufferHelper.flushWithPadding();
- },
-
- /**
- * User data subparameter encoder : User Data
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.2 User Data
- */
- encodeUserDataMsg: function(options) {
- let BitBufferHelper = this.context.BitBufferHelper;
- BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_BODY, 8);
- // Reserve space for length
- BitBufferHelper.writeBits(0, 8);
- let lengthPosition = BitBufferHelper.getWriteBufferSize();
-
- BitBufferHelper.writeBits(options.encoding, 5);
-
- // Add user data header for message segement
- let msgBody = options.body,
- msgBodySize = (options.encoding === PDU_CDMA_MSG_CODING_7BITS_ASCII ?
- options.encodedBodyLength :
- msgBody.length);
- if (options.segmentMaxSeq > 1) {
- if (options.encoding === PDU_CDMA_MSG_CODING_7BITS_ASCII) {
- BitBufferHelper.writeBits(msgBodySize + 7, 8); // Required length for user data header, in septet(7-bit)
-
- BitBufferHelper.writeBits(5, 8); // total header length 5 bytes
- BitBufferHelper.writeBits(PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT, 8); // header id 0
- BitBufferHelper.writeBits(3, 8); // length of element for id 0 is 3
- BitBufferHelper.writeBits(options.segmentRef & 0xFF, 8); // Segement reference
- BitBufferHelper.writeBits(options.segmentMaxSeq & 0xFF, 8); // Max segment
- BitBufferHelper.writeBits(options.segmentSeq & 0xFF, 8); // Current segment
- BitBufferHelper.writeBits(0, 1); // Padding to make header data septet(7-bit) aligned
- } else {
- if (options.encoding === PDU_CDMA_MSG_CODING_UNICODE) {
- BitBufferHelper.writeBits(msgBodySize + 3, 8); // Required length for user data header, in 16-bit
- } else {
- BitBufferHelper.writeBits(msgBodySize + 6, 8); // Required length for user data header, in octet(8-bit)
- }
-
- BitBufferHelper.writeBits(5, 8); // total header length 5 bytes
- BitBufferHelper.writeBits(PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT, 8); // header id 0
- BitBufferHelper.writeBits(3, 8); // length of element for id 0 is 3
- BitBufferHelper.writeBits(options.segmentRef & 0xFF, 8); // Segement reference
- BitBufferHelper.writeBits(options.segmentMaxSeq & 0xFF, 8); // Max segment
- BitBufferHelper.writeBits(options.segmentSeq & 0xFF, 8); // Current segment
- }
- } else {
- BitBufferHelper.writeBits(msgBodySize, 8);
- }
-
- // Encode message based on encoding method
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- for (let i = 0; i < msgBody.length; i++) {
- switch (options.encoding) {
- case PDU_CDMA_MSG_CODING_OCTET: {
- let msgDigit = msgBody.charCodeAt(i);
- BitBufferHelper.writeBits(msgDigit, 8);
- break;
- }
- case PDU_CDMA_MSG_CODING_7BITS_ASCII: {
- let msgDigit = msgBody.charCodeAt(i),
- msgDigitChar = msgBody.charAt(i);
-
- if (msgDigit >= 32) {
- BitBufferHelper.writeBits(msgDigit, 7);
- } else {
- msgDigit = langTable.indexOf(msgDigitChar);
-
- if (msgDigit === PDU_NL_EXTENDED_ESCAPE) {
- break;
- }
- if (msgDigit >= 0) {
- BitBufferHelper.writeBits(msgDigit, 7);
- } else {
- msgDigit = langShiftTable.indexOf(msgDigitChar);
- if (msgDigit == -1) {
- throw new Error("'" + msgDigitChar + "' is not in 7 bit alphabet "
- + langIndex + ":" + langShiftIndex + "!");
- }
-
- if (msgDigit === PDU_NL_RESERVED_CONTROL) {
- break;
- }
-
- BitBufferHelper.writeBits(PDU_NL_EXTENDED_ESCAPE, 7);
- BitBufferHelper.writeBits(msgDigit, 7);
- }
- }
- break;
- }
- case PDU_CDMA_MSG_CODING_UNICODE: {
- let msgDigit = msgBody.charCodeAt(i);
- BitBufferHelper.writeBits(msgDigit, 16);
- break;
- }
- }
- }
- BitBufferHelper.flushWithPadding();
-
- // Fill length
- let currentPosition = BitBufferHelper.getWriteBufferSize();
- BitBufferHelper.overwriteWriteBuffer(lengthPosition - 1, [currentPosition - lengthPosition]);
- },
-
- /**
- * User data subparameter encoder : Reply Option
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.11 Reply Option
- */
- encodeUserDataReplyOption: function(options) {
- if (options.requestStatusReport) {
- let BitBufferHelper = this.context.BitBufferHelper;
- BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_REPLY_OPTION, 8);
- BitBufferHelper.writeBits(1, 8);
- BitBufferHelper.writeBits(0, 1); // USER_ACK_REQ
- BitBufferHelper.writeBits(1, 1); // DAK_REQ
- BitBufferHelper.flushWithPadding();
- }
- },
-
- /**
- * Entry point for SMS decoding, the returned object is made compatible
- * with existing readMessage() of GsmPDUHelper
- */
- readMessage: function() {
- let message = {};
-
- // Teleservice Identifier
- message.teleservice = this.readInt();
-
- // Message Type
- let isServicePresent = this.readByte();
- if (isServicePresent) {
- message.messageType = PDU_CDMA_MSG_TYPE_BROADCAST;
- } else {
- if (message.teleservice) {
- message.messageType = PDU_CDMA_MSG_TYPE_P2P;
- } else {
- message.messageType = PDU_CDMA_MSG_TYPE_ACK;
- }
- }
-
- // Service Category
- message.service = this.readInt();
-
- // Originated Address
- let addrInfo = {};
- addrInfo.digitMode = (this.readInt() & 0x01);
- addrInfo.numberMode = (this.readInt() & 0x01);
- addrInfo.numberType = (this.readInt() & 0x01);
- addrInfo.numberPlan = (this.readInt() & 0x01);
- addrInfo.addrLength = this.readByte();
- addrInfo.address = [];
- for (let i = 0; i < addrInfo.addrLength; i++) {
- addrInfo.address.push(this.readByte());
- }
- message.sender = this.decodeAddr(addrInfo);
-
- // Originated Subaddress
- addrInfo.Type = (this.readInt() & 0x07);
- addrInfo.Odd = (this.readByte() & 0x01);
- addrInfo.addrLength = this.readByte();
- for (let i = 0; i < addrInfo.addrLength; i++) {
- let addrDigit = this.readByte();
- message.sender += String.fromCharCode(addrDigit);
- }
-
- // Bearer Data
- this.decodeUserData(message);
-
- // Bearer Data Sub-Parameter: User Data
- let userData = message[PDU_CDMA_MSG_USERDATA_BODY];
- [message.header, message.body, message.encoding, message.data] =
- (userData) ? [userData.header, userData.body, userData.encoding, userData.data]
- : [null, null, null, null];
-
- // Bearer Data Sub-Parameter: Message Status
- // Success Delivery (0) if both Message Status and User Data are absent.
- // Message Status absent (-1) if only User Data is available.
- let msgStatus = message[PDU_CDMA_MSG_USER_DATA_MSG_STATUS];
- [message.errorClass, message.msgStatus] =
- (msgStatus) ? [msgStatus.errorClass, msgStatus.msgStatus]
- : ((message.body) ? [-1, -1] : [0, 0]);
-
- // Transform message to GSM msg
- let msg = {
- SMSC: "",
- mti: 0,
- udhi: 0,
- sender: message.sender,
- recipient: null,
- pid: PDU_PID_DEFAULT,
- epid: PDU_PID_DEFAULT,
- dcs: 0,
- mwi: null,
- replace: false,
- header: message.header,
- body: message.body,
- data: message.data,
- sentTimestamp: message[PDU_CDMA_MSG_USERDATA_TIMESTAMP],
- language: message[PDU_CDMA_LANGUAGE_INDICATOR],
- status: null,
- scts: null,
- dt: null,
- encoding: message.encoding,
- messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- messageType: message.messageType,
- serviceCategory: message.service,
- subMsgType: message[PDU_CDMA_MSG_USERDATA_MSG_ID].msgType,
- msgId: message[PDU_CDMA_MSG_USERDATA_MSG_ID].msgId,
- errorClass: message.errorClass,
- msgStatus: message.msgStatus,
- teleservice: message.teleservice
- };
-
- return msg;
- },
-
- /**
- * Helper for processing received SMS parcel data.
- *
- * @param length
- * Length of SMS string in the incoming parcel.
- *
- * @return Message parsed or null for invalid message.
- */
- processReceivedSms: function(length) {
- if (!length) {
- if (DEBUG) this.context.debug("Received empty SMS!");
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- let message = this.readMessage();
- if (DEBUG) this.context.debug("Got new SMS: " + JSON.stringify(message));
-
- // Determine result
- if (!message) {
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- return [message, PDU_FCS_OK];
- },
-
- /**
- * Data readers
- */
- readInt: function() {
- return this.context.Buf.readInt32();
- },
-
- readByte: function() {
- return (this.context.Buf.readInt32() & 0xFF);
- },
-
- /**
- * Decode CDMA address data into address string
- *
- * @see 3GGP2 C.S0015-B 2.0, 3.4.3.3 Address Parameters
- *
- * Required key in addrInfo
- * @param addrLength
- * Length of address
- * @param digitMode
- * Address encoding method
- * @param address
- * Array of encoded address data
- */
- decodeAddr: function(addrInfo) {
- let result = "";
- for (let i = 0; i < addrInfo.addrLength; i++) {
- if (addrInfo.digitMode === PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF) {
- result += this.dtmfChars.charAt(addrInfo.address[i]);
- } else {
- result += String.fromCharCode(addrInfo.address[i]);
- }
- }
- return result;
- },
-
- /**
- * Read userData in parcel buffer and decode into message object.
- * Each subparameter will be stored in corresponding key.
- *
- * @see 3GGP2 C.S0015-B 2.0, 3.4.3.7 Bearer Data
- * 4.5 Bearer Data Parameters
- */
- decodeUserData: function(message) {
- let userDataLength = this.readInt();
-
- while (userDataLength > 0) {
- let id = this.readByte(),
- length = this.readByte(),
- userDataBuffer = [];
-
- for (let i = 0; i < length; i++) {
- userDataBuffer.push(this.readByte());
- }
-
- this.context.BitBufferHelper.startRead(userDataBuffer);
-
- switch (id) {
- case PDU_CDMA_MSG_USERDATA_MSG_ID:
- message[id] = this.decodeUserDataMsgId();
- break;
- case PDU_CDMA_MSG_USERDATA_BODY:
- message[id] = this.decodeUserDataMsg(message[PDU_CDMA_MSG_USERDATA_MSG_ID].userHeader);
- break;
- case PDU_CDMA_MSG_USERDATA_TIMESTAMP:
- message[id] = this.decodeUserDataTimestamp();
- break;
- case PDU_CDMA_MSG_USERDATA_REPLY_OPTION:
- message[id] = this.decodeUserDataReplyOption();
- break;
- case PDU_CDMA_LANGUAGE_INDICATOR:
- message[id] = this.decodeLanguageIndicator();
- break;
- case PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER:
- message[id] = this.decodeUserDataCallbackNumber();
- break;
- case PDU_CDMA_MSG_USER_DATA_MSG_STATUS:
- message[id] = this.decodeUserDataMsgStatus();
- break;
- }
-
- userDataLength -= (length + 2);
- userDataBuffer = [];
- }
- },
-
- /**
- * User data subparameter decoder: Message Identifier
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.1 Message Identifier
- */
- decodeUserDataMsgId: function() {
- let result = {};
- let BitBufferHelper = this.context.BitBufferHelper;
- result.msgType = BitBufferHelper.readBits(4);
- result.msgId = BitBufferHelper.readBits(16);
- result.userHeader = BitBufferHelper.readBits(1);
-
- return result;
- },
-
- /**
- * Decode user data header, we only care about segment information
- * on CDMA.
- *
- * This function is mostly copied from gsmPduHelper.readUserDataHeader() but
- * change the read function, because CDMA user header decoding is't byte-wise
- * aligned.
- */
- decodeUserDataHeader: function(encoding) {
- let BitBufferHelper = this.context.BitBufferHelper;
- let header = {},
- headerSize = BitBufferHelper.readBits(8),
- userDataHeaderSize = headerSize + 1,
- headerPaddingBits = 0;
-
- // Calculate header size
- if (encoding === PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- // Length is in 7-bit
- header.length = Math.ceil(userDataHeaderSize * 8 / 7);
- // Calulate padding length
- headerPaddingBits = (header.length * 7) - (userDataHeaderSize * 8);
- } else if (encoding === PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
- header.length = userDataHeaderSize;
- } else {
- header.length = userDataHeaderSize / 2;
- }
-
- while (headerSize) {
- let identifier = BitBufferHelper.readBits(8),
- length = BitBufferHelper.readBits(8);
-
- headerSize -= (2 + length);
-
- switch (identifier) {
- case PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT: {
- let ref = BitBufferHelper.readBits(8),
- max = BitBufferHelper.readBits(8),
- seq = BitBufferHelper.readBits(8);
- if (max && seq && (seq <= max)) {
- header.segmentRef = ref;
- header.segmentMaxSeq = max;
- header.segmentSeq = seq;
- }
- break;
- }
- case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT: {
- let dstp = BitBufferHelper.readBits(8),
- orip = BitBufferHelper.readBits(8);
- if ((dstp < PDU_APA_RESERVED_8BIT_PORTS)
- || (orip < PDU_APA_RESERVED_8BIT_PORTS)) {
- // 3GPP TS 23.040 clause 9.2.3.24.3: "A receiving entity shall
- // ignore any information element where the value of the
- // Information-Element-Data is Reserved or not supported"
- break;
- }
- header.destinationPort = dstp;
- header.originatorPort = orip;
- break;
- }
- case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT: {
- let dstp = (BitBufferHelper.readBits(8) << 8) | BitBufferHelper.readBits(8),
- orip = (BitBufferHelper.readBits(8) << 8) | BitBufferHelper.readBits(8);
- // 3GPP TS 23.040 clause 9.2.3.24.4: "A receiving entity shall
- // ignore any information element where the value of the
- // Information-Element-Data is Reserved or not supported"
- if ((dstp < PDU_APA_VALID_16BIT_PORTS)
- && (orip < PDU_APA_VALID_16BIT_PORTS)) {
- header.destinationPort = dstp;
- header.originatorPort = orip;
- }
- break;
- }
- case PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT: {
- let ref = (BitBufferHelper.readBits(8) << 8) | BitBufferHelper.readBits(8),
- max = BitBufferHelper.readBits(8),
- seq = BitBufferHelper.readBits(8);
- if (max && seq && (seq <= max)) {
- header.segmentRef = ref;
- header.segmentMaxSeq = max;
- header.segmentSeq = seq;
- }
- break;
- }
- case PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT: {
- let langShiftIndex = BitBufferHelper.readBits(8);
- if (langShiftIndex < PDU_NL_SINGLE_SHIFT_TABLES.length) {
- header.langShiftIndex = langShiftIndex;
- }
- break;
- }
- case PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT: {
- let langIndex = BitBufferHelper.readBits(8);
- if (langIndex < PDU_NL_LOCKING_SHIFT_TABLES.length) {
- header.langIndex = langIndex;
- }
- break;
- }
- case PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION: {
- let msgInd = BitBufferHelper.readBits(8) & 0xFF,
- msgCount = BitBufferHelper.readBits(8);
- /*
- * TS 23.040 V6.8.1 Sec 9.2.3.24.2
- * bits 1 0 : basic message indication type
- * bits 4 3 2 : extended message indication type
- * bits 6 5 : Profile id
- * bit 7 : storage type
- */
- let storeType = msgInd & PDU_MWI_STORE_TYPE_BIT;
- header.mwi = {};
- mwi = header.mwi;
-
- if (storeType == PDU_MWI_STORE_TYPE_STORE) {
- // Store message because TP_UDH indicates so, note this may override
- // the setting in DCS, but that is expected
- mwi.discard = false;
- } else if (mwi.discard === undefined) {
- // storeType == PDU_MWI_STORE_TYPE_DISCARD
- // only override mwi.discard here if it hasn't already been set
- mwi.discard = true;
- }
-
- mwi.msgCount = msgCount & 0xFF;
- mwi.active = mwi.msgCount > 0;
-
- if (DEBUG) {
- this.context.debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
- }
- break;
- }
- default:
- // Drop unsupported id
- for (let i = 0; i < length; i++) {
- BitBufferHelper.readBits(8);
- }
- }
- }
-
- // Consume padding bits
- if (headerPaddingBits) {
- BitBufferHelper.readBits(headerPaddingBits);
- }
-
- return header;
- },
-
- getCdmaMsgEncoding: function(encoding) {
- // Determine encoding method
- switch (encoding) {
- case PDU_CDMA_MSG_CODING_7BITS_ASCII:
- case PDU_CDMA_MSG_CODING_IA5:
- case PDU_CDMA_MSG_CODING_7BITS_GSM:
- return PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- case PDU_CDMA_MSG_CODING_OCTET:
- case PDU_CDMA_MSG_CODING_IS_91:
- case PDU_CDMA_MSG_CODING_LATIN_HEBREW:
- case PDU_CDMA_MSG_CODING_LATIN:
- return PDU_DCS_MSG_CODING_8BITS_ALPHABET;
- case PDU_CDMA_MSG_CODING_UNICODE:
- case PDU_CDMA_MSG_CODING_SHIFT_JIS:
- case PDU_CDMA_MSG_CODING_KOREAN:
- return PDU_DCS_MSG_CODING_16BITS_ALPHABET;
- }
- return null;
- },
-
- decodeCdmaPDUMsg: function(encoding, msgType, msgBodySize) {
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- let BitBufferHelper = this.context.BitBufferHelper;
- let result = "";
- let msgDigit;
- switch (encoding) {
- case PDU_CDMA_MSG_CODING_OCTET: // TODO : Require Test
- while(msgBodySize > 0) {
- msgDigit = String.fromCharCode(BitBufferHelper.readBits(8));
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_IS_91: // TODO : Require Test
- // Referenced from android code
- switch (msgType) {
- case PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS:
- case PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS_FULL:
- case PDU_CDMA_MSG_CODING_IS_91_TYPE_VOICEMAIL_STATUS:
- while(msgBodySize > 0) {
- msgDigit = String.fromCharCode(BitBufferHelper.readBits(6) + 0x20);
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_IS_91_TYPE_CLI:
- let addrInfo = {};
- addrInfo.digitMode = PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF;
- addrInfo.numberMode = PDU_CDMA_MSG_ADDR_NUMBER_MODE_ANSI;
- addrInfo.numberType = PDU_CDMA_MSG_ADDR_NUMBER_TYPE_UNKNOWN;
- addrInfo.numberPlan = PDU_CDMA_MSG_ADDR_NUMBER_PLAN_UNKNOWN;
- addrInfo.addrLength = msgBodySize;
- addrInfo.address = [];
- for (let i = 0; i < addrInfo.addrLength; i++) {
- addrInfo.address.push(BitBufferHelper.readBits(4));
- }
- result = this.decodeAddr(addrInfo);
- break;
- }
- // Fall through.
- case PDU_CDMA_MSG_CODING_7BITS_ASCII:
- case PDU_CDMA_MSG_CODING_IA5: // TODO : Require Test
- while(msgBodySize > 0) {
- msgDigit = BitBufferHelper.readBits(7);
- if (msgDigit >= 32) {
- msgDigit = String.fromCharCode(msgDigit);
- } else {
- if (msgDigit !== PDU_NL_EXTENDED_ESCAPE) {
- msgDigit = langTable[msgDigit];
- } else {
- msgDigit = BitBufferHelper.readBits(7);
- msgBodySize--;
- msgDigit = langShiftTable[msgDigit];
- }
- }
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_UNICODE:
- while(msgBodySize > 0) {
- msgDigit = String.fromCharCode(BitBufferHelper.readBits(16));
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_7BITS_GSM: // TODO : Require Test
- while(msgBodySize > 0) {
- msgDigit = BitBufferHelper.readBits(7);
- if (msgDigit !== PDU_NL_EXTENDED_ESCAPE) {
- msgDigit = langTable[msgDigit];
- } else {
- msgDigit = BitBufferHelper.readBits(7);
- msgBodySize--;
- msgDigit = langShiftTable[msgDigit];
- }
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_LATIN: // TODO : Require Test
- // Reference : http://en.wikipedia.org/wiki/ISO/IEC_8859-1
- while(msgBodySize > 0) {
- msgDigit = String.fromCharCode(BitBufferHelper.readBits(8));
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_LATIN_HEBREW: // TODO : Require Test
- // Reference : http://en.wikipedia.org/wiki/ISO/IEC_8859-8
- while(msgBodySize > 0) {
- msgDigit = BitBufferHelper.readBits(8);
- if (msgDigit === 0xDF) {
- msgDigit = String.fromCharCode(0x2017);
- } else if (msgDigit === 0xFD) {
- msgDigit = String.fromCharCode(0x200E);
- } else if (msgDigit === 0xFE) {
- msgDigit = String.fromCharCode(0x200F);
- } else if (msgDigit >= 0xE0 && msgDigit <= 0xFA) {
- msgDigit = String.fromCharCode(0x4F0 + msgDigit);
- } else {
- msgDigit = String.fromCharCode(msgDigit);
- }
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_SHIFT_JIS:
- // Reference : http://msdn.microsoft.com/en-US/goglobal/cc305152.aspx
- // http://demo.icu-project.org/icu-bin/convexp?conv=Shift_JIS
- let shift_jis_message = [];
-
- while (msgBodySize > 0) {
- shift_jis_message.push(BitBufferHelper.readBits(8));
- msgBodySize--;
- }
-
- let decoder = new TextDecoder("shift_jis");
- result = decoder.decode(new Uint8Array(shift_jis_message));
- break;
- case PDU_CDMA_MSG_CODING_KOREAN:
- case PDU_CDMA_MSG_CODING_GSM_DCS:
- // Fall through.
- default:
- break;
- }
- return result;
- },
-
- /**
- * User data subparameter decoder : User Data
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.2 User Data
- */
- decodeUserDataMsg: function(hasUserHeader) {
- let BitBufferHelper = this.context.BitBufferHelper;
- let result = {},
- encoding = BitBufferHelper.readBits(5),
- msgType;
-
- if (encoding === PDU_CDMA_MSG_CODING_IS_91) {
- msgType = BitBufferHelper.readBits(8);
- }
- result.encoding = this.getCdmaMsgEncoding(encoding);
-
- let msgBodySize = BitBufferHelper.readBits(8);
-
- // For segmented SMS, a user header is included before sms content
- if (hasUserHeader) {
- result.header = this.decodeUserDataHeader(result.encoding);
- // header size is included in body size, they are decoded
- msgBodySize -= result.header.length;
- }
-
- // Store original payload if enconding is OCTET for further handling of WAP Push, etc.
- if (encoding === PDU_CDMA_MSG_CODING_OCTET && msgBodySize > 0) {
- result.data = new Uint8Array(msgBodySize);
- for (let i = 0; i < msgBodySize; i++) {
- result.data[i] = BitBufferHelper.readBits(8);
- }
- BitBufferHelper.backwardReadPilot(8 * msgBodySize);
- }
-
- // Decode sms content
- result.body = this.decodeCdmaPDUMsg(encoding, msgType, msgBodySize);
-
- return result;
- },
-
- decodeBcd: function(value) {
- return ((value >> 4) & 0xF) * 10 + (value & 0x0F);
- },
-
- /**
- * User data subparameter decoder : Time Stamp
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.4 Message Center Time Stamp
- */
- decodeUserDataTimestamp: function() {
- let BitBufferHelper = this.context.BitBufferHelper;
- let year = this.decodeBcd(BitBufferHelper.readBits(8)),
- month = this.decodeBcd(BitBufferHelper.readBits(8)) - 1,
- date = this.decodeBcd(BitBufferHelper.readBits(8)),
- hour = this.decodeBcd(BitBufferHelper.readBits(8)),
- min = this.decodeBcd(BitBufferHelper.readBits(8)),
- sec = this.decodeBcd(BitBufferHelper.readBits(8));
-
- if (year >= 96 && year <= 99) {
- year += 1900;
- } else {
- year += 2000;
- }
-
- let result = (new Date(year, month, date, hour, min, sec, 0)).valueOf();
-
- return result;
- },
-
- /**
- * User data subparameter decoder : Reply Option
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.11 Reply Option
- */
- decodeUserDataReplyOption: function() {
- let replyAction = this.context.BitBufferHelper.readBits(4),
- result = { userAck: (replyAction & 0x8) ? true : false,
- deliverAck: (replyAction & 0x4) ? true : false,
- readAck: (replyAction & 0x2) ? true : false,
- report: (replyAction & 0x1) ? true : false
- };
-
- return result;
- },
-
- /**
- * User data subparameter decoder : Language Indicator
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.14 Language Indicator
- */
- decodeLanguageIndicator: function() {
- let language = this.context.BitBufferHelper.readBits(8);
- let result = CB_CDMA_LANG_GROUP[language];
- return result;
- },
-
- /**
- * User data subparameter decoder : Call-Back Number
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.15 Call-Back Number
- */
- decodeUserDataCallbackNumber: function() {
- let BitBufferHelper = this.context.BitBufferHelper;
- let digitMode = BitBufferHelper.readBits(1);
- if (digitMode) {
- let numberType = BitBufferHelper.readBits(3),
- numberPlan = BitBufferHelper.readBits(4);
- }
- let numberFields = BitBufferHelper.readBits(8),
- result = "";
- for (let i = 0; i < numberFields; i++) {
- if (digitMode === PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF) {
- let addrDigit = BitBufferHelper.readBits(4);
- result += this.dtmfChars.charAt(addrDigit);
- } else {
- let addrDigit = BitBufferHelper.readBits(8);
- result += String.fromCharCode(addrDigit);
- }
- }
-
- return result;
- },
-
- /**
- * User data subparameter decoder : Message Status
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.21 Message Status
- */
- decodeUserDataMsgStatus: function() {
- let BitBufferHelper = this.context.BitBufferHelper;
- let result = {
- errorClass: BitBufferHelper.readBits(2),
- msgStatus: BitBufferHelper.readBits(6)
- };
-
- return result;
- },
-
- /**
- * Decode information record parcel.
- */
- decodeInformationRecord: function() {
- let Buf = this.context.Buf;
- let records = [];
- let numOfRecords = Buf.readInt32();
-
- let type;
- let record;
- for (let i = 0; i < numOfRecords; i++) {
- record = {};
- type = Buf.readInt32();
-
- switch (type) {
- /*
- * Every type is encaped by ril, except extended display
- */
- case PDU_CDMA_INFO_REC_TYPE_DISPLAY:
- case PDU_CDMA_INFO_REC_TYPE_EXTENDED_DISPLAY:
- record.display = Buf.readString();
- break;
- case PDU_CDMA_INFO_REC_TYPE_CALLED_PARTY_NUMBER:
- record.calledNumber = {};
- record.calledNumber.number = Buf.readString();
- record.calledNumber.type = Buf.readInt32();
- record.calledNumber.plan = Buf.readInt32();
- record.calledNumber.pi = Buf.readInt32();
- record.calledNumber.si = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_CALLING_PARTY_NUMBER:
- record.callingNumber = {};
- record.callingNumber.number = Buf.readString();
- record.callingNumber.type = Buf.readInt32();
- record.callingNumber.plan = Buf.readInt32();
- record.callingNumber.pi = Buf.readInt32();
- record.callingNumber.si = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_CONNECTED_NUMBER:
- record.connectedNumber = {};
- record.connectedNumber.number = Buf.readString();
- record.connectedNumber.type = Buf.readInt32();
- record.connectedNumber.plan = Buf.readInt32();
- record.connectedNumber.pi = Buf.readInt32();
- record.connectedNumber.si = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_SIGNAL:
- record.signal = {};
- if (!Buf.readInt32()) { // Non-zero if signal is present.
- Buf.seekIncoming(3 * Buf.UINT32_SIZE);
- continue;
- }
- record.signal.type = Buf.readInt32();
- record.signal.alertPitch = Buf.readInt32();
- record.signal.signal = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_REDIRECTING_NUMBER:
- record.redirect = {};
- record.redirect.number = Buf.readString();
- record.redirect.type = Buf.readInt32();
- record.redirect.plan = Buf.readInt32();
- record.redirect.pi = Buf.readInt32();
- record.redirect.si = Buf.readInt32();
- record.redirect.reason = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_LINE_CONTROL:
- record.lineControl = {};
- record.lineControl.polarityIncluded = Buf.readInt32();
- record.lineControl.toggle = Buf.readInt32();
- record.lineControl.reverse = Buf.readInt32();
- record.lineControl.powerDenial = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_T53_CLIR:
- record.clirCause = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_T53_AUDIO_CONTROL:
- record.audioControl = {};
- record.audioControl.upLink = Buf.readInt32();
- record.audioControl.downLink = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_T53_RELEASE:
- // Fall through
- default:
- throw new Error("UNSOLICITED_CDMA_INFO_REC(), Unsupported information record type " + type + "\n");
- }
-
- records.push(record);
- }
-
- return records;
- }
-};
-
-/**
- * Helper for processing ICC PDUs.
- */
-function ICCPDUHelperObject(aContext) {
- this.context = aContext;
-}
-ICCPDUHelperObject.prototype = {
- context: null,
-
- /**
- * Read GSM 8-bit unpacked octets,
- * which are default 7-bit alphabets with bit 8 set to 0.
- *
- * @param numOctets
- * Number of octets to be read.
- */
- read8BitUnpackedToString: function(numOctets) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let ret = "";
- let escapeFound = false;
- let i;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- for(i = 0; i < numOctets; i++) {
- let octet = GsmPDUHelper.readHexOctet();
- if (octet == 0xff) {
- i++;
- break;
- }
-
- if (escapeFound) {
- escapeFound = false;
- if (octet == PDU_NL_EXTENDED_ESCAPE) {
- // According to 3GPP TS 23.038, section 6.2.1.1, NOTE 1, "On
- // receipt of this code, a receiving entity shall display a space
- // until another extensiion table is defined."
- ret += " ";
- } else if (octet == PDU_NL_RESERVED_CONTROL) {
- // According to 3GPP TS 23.038 B.2, "This code represents a control
- // character and therefore must not be used for language specific
- // characters."
- ret += " ";
- } else {
- ret += langShiftTable[octet];
- }
- } else if (octet == PDU_NL_EXTENDED_ESCAPE) {
- escapeFound = true;
- } else {
- ret += langTable[octet];
- }
- }
-
- let Buf = this.context.Buf;
- Buf.seekIncoming((numOctets - i) * Buf.PDU_HEX_OCTET_SIZE);
- return ret;
- },
-
- /**
- * Write GSM 8-bit unpacked octets.
- *
- * @param numOctets Number of total octets to be writen, including trailing
- * 0xff.
- * @param str String to be written. Could be null.
- *
- * @return The string has been written into Buf. "" if str is null.
- */
- writeStringTo8BitUnpacked: function(numOctets, str) {
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // If the character is GSM extended alphabet, two octets will be written.
- // So we need to keep track of number of octets to be written.
- let i, j;
- let len = str ? str.length : 0;
- for (i = 0, j = 0; i < len && j < numOctets; i++) {
- let c = str.charAt(i);
- let octet = langTable.indexOf(c);
-
- if (octet == -1) {
- // Make sure we still have enough space to write two octets.
- if (j + 2 > numOctets) {
- break;
- }
-
- octet = langShiftTable.indexOf(c);
- if (octet == -1) {
- // Fallback to ASCII space.
- octet = langTable.indexOf(' ');
- } else {
- GsmPDUHelper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
- j++;
- }
- }
- GsmPDUHelper.writeHexOctet(octet);
- j++;
- }
-
- // trailing 0xff
- while (j++ < numOctets) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
-
- return (str) ? str.substring(0, i) : "";
- },
-
- /**
- * Write UCS2 String on UICC.
- * The default choose 0x81 or 0x82 encode, otherwise use 0x80 encode.
- *
- * @see TS 102.221, Annex A.
- * @param numOctets
- * Total number of octets to be written. This includes the length of
- * alphaId and the length of trailing unused octets(0xff).
- * @param str
- * String to be written.
- *
- * @return The string has been written into Buf.
- */
- writeICCUCS2String: function(numOctets, str) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let scheme = 0x80;
- let basePointer;
-
- if (str.length > 2) {
- let min = 0xFFFF;
- let max = 0;
- for (let i = 0; i < str.length; i++) {
- let code = str.charCodeAt(i);
- // filter out GSM Default Alphabet character
- if (code & 0xFF80) {
- if (min > code) {
- min = code;
- }
- if (max < code) {
- max = code;
- }
- }
- }
-
- // 0x81 and 0x82 only support 'half-page', i.e., 128 characters.
- if ((max - min) >= 0 && (max - min) < 128) {
- // 0x81 base pointer is 0hhh hhhh h000 0000, and bit 16 is set to zero,
- // therefore it can't compute 0x8000~0xFFFF.
- // Since 0x81 only support 128 characters,
- // either XX00~XX7f(bit 8 are 0) or XX80~XXff(bit 8 are 1)
- if (((min & 0x7f80) == (max & 0x7f80)) &&
- ((max & 0x8000) == 0)) {
- scheme = 0x81;
- basePointer = min & 0x7f80;
- } else {
- scheme = 0x82;
- basePointer = min;
- }
- }
- }
-
- switch (scheme) {
- /**
- * +------+---------+---------+---------+---------+------+------+
- * | 0x80 | Ch1_msb | Ch1_lsb | Ch2_msb | Ch2_lsb | 0xff | 0xff |
- * +------+---------+---------+---------+---------+------+------+
- */
- case 0x80: {
- // 0x80 support UCS2 0000~ffff
- GsmPDUHelper.writeHexOctet(0x80);
- numOctets--;
- // Now the str is UCS2 string, each character will take 2 octets.
- if (str.length * 2 > numOctets) {
- str = str.substring(0, Math.floor(numOctets / 2));
- }
- GsmPDUHelper.writeUCS2String(str);
-
- // trailing 0xff
- for (let i = str.length * 2; i < numOctets; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- return str;
- }
- /**
- * +------+-----+--------------+-----+-----+-----+--------+------+
- * | 0x81 | len | base_pointer | Ch1 | Ch2 | ... | Ch_len | 0xff |
- * +------+-----+--------------+-----+-----+-----+--------+------+
- *
- * len: The length of characters.
- * base_pointer: 0hhh hhhh h000 0000
- * Ch_n: bit 8 = 0
- * GSM default alphabets
- * bit 8 = 1
- * UCS2 character whose char code is (Ch_n - base_pointer) | 0x80
- *
- */
- case 0x81: {
- GsmPDUHelper.writeHexOctet(0x81);
-
- if (str.length > (numOctets - 3)) {
- str = str.substring(0, numOctets - 3);
- }
-
- GsmPDUHelper.writeHexOctet(str.length);
- GsmPDUHelper.writeHexOctet((basePointer >> 7) & 0xff);
- numOctets -= 3;
- break;
- }
- /* +------+-----+------------------+------------------+-----+-----+-----+--------+
- * | 0x82 | len | base_pointer_msb | base_pointer_lsb | Ch1 | Ch2 | ... | Ch_len |
- * +------+-----+------------------+------------------+-----+-----+-----+--------+
- *
- * len: The length of characters.
- * base_pointer_msb, base_pointer_lsn: base_pointer
- * Ch_n: bit 8 = 0
- * GSM default alphabets
- * bit 8 = 1
- * UCS2 character whose char code is (Ch_n - base_pointer) | 0x80
- */
- case 0x82: {
- GsmPDUHelper.writeHexOctet(0x82);
-
- if (str.length > (numOctets - 4)) {
- str = str.substring(0, numOctets - 4);
- }
-
- GsmPDUHelper.writeHexOctet(str.length);
- GsmPDUHelper.writeHexOctet((basePointer >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(basePointer & 0xff);
- numOctets -= 4;
- break;
- }
- }
-
- if (scheme == 0x81 || scheme == 0x82) {
- for (let i = 0; i < str.length; i++) {
- let code = str.charCodeAt(i);
-
- // bit 8 = 0,
- // GSM default alphabets
- if (code >> 8 == 0) {
- GsmPDUHelper.writeHexOctet(code & 0x7F);
- } else {
- // bit 8 = 1,
- // UCS2 character whose char code is (code - basePointer) | 0x80
- GsmPDUHelper.writeHexOctet((code - basePointer) | 0x80);
- }
- }
-
- // trailing 0xff
- for (let i = 0; i < numOctets - str.length; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- }
- return str;
- },
-
- /**
- * Read UCS2 String on UICC.
- *
- * @see TS 101.221, Annex A.
- * @param scheme
- * Coding scheme for UCS2 on UICC. One of 0x80, 0x81 or 0x82.
- * @param numOctets
- * Number of octets to be read as UCS2 string.
- */
- readICCUCS2String: function(scheme, numOctets) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let str = "";
- switch (scheme) {
- /**
- * +------+---------+---------+---------+---------+------+------+
- * | 0x80 | Ch1_msb | Ch1_lsb | Ch2_msb | Ch2_lsb | 0xff | 0xff |
- * +------+---------+---------+---------+---------+------+------+
- */
- case 0x80:
- let isOdd = numOctets % 2;
- let i;
- for (i = 0; i < numOctets - isOdd; i += 2) {
- let code = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- if (code == 0xffff) {
- i += 2;
- break;
- }
- str += String.fromCharCode(code);
- }
-
- // Skip trailing 0xff
- Buf.seekIncoming((numOctets - i) * Buf.PDU_HEX_OCTET_SIZE);
- break;
- case 0x81: // Fall through
- case 0x82:
- /**
- * +------+-----+--------+-----+-----+-----+--------+------+
- * | 0x81 | len | offset | Ch1 | Ch2 | ... | Ch_len | 0xff |
- * +------+-----+--------+-----+-----+-----+--------+------+
- *
- * len : The length of characters.
- * offset : 0hhh hhhh h000 0000
- * Ch_n: bit 8 = 0
- * GSM default alphabets
- * bit 8 = 1
- * UCS2 character whose char code is (Ch_n & 0x7f) + offset
- *
- * +------+-----+------------+------------+-----+-----+-----+--------+
- * | 0x82 | len | offset_msb | offset_lsb | Ch1 | Ch2 | ... | Ch_len |
- * +------+-----+------------+------------+-----+-----+-----+--------+
- *
- * len : The length of characters.
- * offset_msb, offset_lsn: offset
- * Ch_n: bit 8 = 0
- * GSM default alphabets
- * bit 8 = 1
- * UCS2 character whose char code is (Ch_n & 0x7f) + offset
- */
- let len = GsmPDUHelper.readHexOctet();
- let offset, headerLen;
- if (scheme == 0x81) {
- offset = GsmPDUHelper.readHexOctet() << 7;
- headerLen = 2;
- } else {
- offset = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- headerLen = 3;
- }
-
- for (let i = 0; i < len; i++) {
- let ch = GsmPDUHelper.readHexOctet();
- if (ch & 0x80) {
- // UCS2
- str += String.fromCharCode((ch & 0x7f) + offset);
- } else {
- // GSM 8bit
- let count = 0, gotUCS2 = 0;
- while ((i + count + 1 < len)) {
- count++;
- if (GsmPDUHelper.readHexOctet() & 0x80) {
- gotUCS2 = 1;
- break;
- }
- }
- // Unread.
- // +1 for the GSM alphabet indexed at i,
- Buf.seekIncoming(-1 * (count + 1) * Buf.PDU_HEX_OCTET_SIZE);
- str += this.read8BitUnpackedToString(count + 1 - gotUCS2);
- i += count - gotUCS2;
- }
- }
-
- // Skipping trailing 0xff
- Buf.seekIncoming((numOctets - len - headerLen) * Buf.PDU_HEX_OCTET_SIZE);
- break;
- }
- return str;
- },
-
- /**
- * Read Alpha Id and Dialling number from TS TS 151.011 clause 10.5.1
- *
- * @param recordSize The size of linear fixed record.
- */
- readAlphaIdDiallingNumber: function(recordSize) {
- let Buf = this.context.Buf;
- let length = Buf.readInt32();
-
- let alphaLen = recordSize - ADN_FOOTER_SIZE_BYTES;
- let alphaId = this.readAlphaIdentifier(alphaLen);
-
- let number = this.readNumberWithLength();
-
- // Skip unused octet, CCP
- Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
-
- let extRecordNumber = this.context.GsmPDUHelper.readHexOctet();
- Buf.readStringDelimiter(length);
-
- let contact = null;
- if (alphaId || number) {
- contact = {alphaId: alphaId,
- number: number,
- extRecordNumber: extRecordNumber};
- }
-
- return contact;
- },
-
- /**
- * Write Alpha Identifier and Dialling number from TS 151.011 clause 10.5.1
- *
- * @param recordSize The size of linear fixed record.
- * @param alphaId Alpha Identifier to be written.
- * @param number Dialling Number to be written.
- * @param extRecordNumber The record identifier of the EXT.
- *
- * @return An object contains the alphaId and number
- * that have been written into Buf.
- */
- writeAlphaIdDiallingNumber: function(recordSize, alphaId, number, extRecordNumber) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // Write String length
- let strLen = recordSize * 2;
- Buf.writeInt32(strLen);
-
- let alphaLen = recordSize - ADN_FOOTER_SIZE_BYTES;
- let writtenAlphaId = this.writeAlphaIdentifier(alphaLen, alphaId);
- let writtenNumber = this.writeNumberWithLength(number);
-
- // Write unused CCP octet 0xff.
- GsmPDUHelper.writeHexOctet(0xff);
- GsmPDUHelper.writeHexOctet((extRecordNumber != null) ? extRecordNumber : 0xff);
-
- Buf.writeStringDelimiter(strLen);
-
- return {alphaId: writtenAlphaId,
- number: writtenNumber};
- },
-
- /**
- * Read Alpha Identifier.
- *
- * @see TS 131.102
- *
- * @param numOctets
- * Number of octets to be read.
- *
- * It uses either
- * 1. SMS default 7-bit alphabet with bit 8 set to 0.
- * 2. UCS2 string.
- *
- * Unused bytes should be set to 0xff.
- */
- readAlphaIdentifier: function(numOctets) {
- if (numOctets === 0) {
- return "";
- }
-
- let temp;
- // Read the 1st octet to determine the encoding.
- if ((temp = this.context.GsmPDUHelper.readHexOctet()) == 0x80 ||
- temp == 0x81 ||
- temp == 0x82) {
- numOctets--;
- return this.readICCUCS2String(temp, numOctets);
- } else {
- let Buf = this.context.Buf;
- Buf.seekIncoming(-1 * Buf.PDU_HEX_OCTET_SIZE);
- return this.read8BitUnpackedToString(numOctets);
- }
- },
-
- /**
- * Write Alpha Identifier.
- *
- * @param numOctets
- * Total number of octets to be written. This includes the length of
- * alphaId and the length of trailing unused octets(0xff).
- * @param alphaId
- * Alpha Identifier to be written.
- *
- * @return The Alpha Identifier has been written into Buf.
- *
- * Unused octets will be written as 0xff.
- */
- writeAlphaIdentifier: function(numOctets, alphaId) {
- if (numOctets === 0) {
- return "";
- }
-
- // If alphaId is empty or it's of GSM 8 bit.
- if (!alphaId || this.context.ICCUtilsHelper.isGsm8BitAlphabet(alphaId)) {
- return this.writeStringTo8BitUnpacked(numOctets, alphaId);
- } else {
- return this.writeICCUCS2String(numOctets, alphaId);
- }
- },
-
- /**
- * Read Dialling number.
- *
- * @see TS 131.102
- *
- * @param len
- * The Length of BCD number.
- *
- * From TS 131.102, in EF_ADN, EF_FDN, the field 'Length of BCD number'
- * means the total bytes should be allocated to store the TON/NPI and
- * the dialing number.
- * For example, if the dialing number is 1234567890,
- * and the TON/NPI is 0x81,
- * The field 'Length of BCD number' should be 06, which is
- * 1 byte to store the TON/NPI, 0x81
- * 5 bytes to store the BCD number 2143658709.
- *
- * Here the definition of the length is different from SMS spec,
- * TS 23.040 9.1.2.5, which the length means
- * "number of useful semi-octets within the Address-Value field".
- */
- readDiallingNumber: function(len) {
- if (DEBUG) this.context.debug("PDU: Going to read Dialling number: " + len);
- if (len === 0) {
- return "";
- }
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // TOA = TON + NPI
- let toa = GsmPDUHelper.readHexOctet();
-
- let number = GsmPDUHelper.readSwappedNibbleExtendedBcdString(len - 1);
- if (number.length <= 0) {
- if (DEBUG) this.context.debug("No number provided");
- return "";
- }
- if ((toa >> 4) == (PDU_TOA_INTERNATIONAL >> 4)) {
- number = '+' + number;
- }
- return number;
- },
-
- /**
- * Write Dialling Number.
- *
- * @param number The Dialling number
- */
- writeDiallingNumber: function(number) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let toa = PDU_TOA_ISDN; // 81
- if (number[0] == '+') {
- toa = PDU_TOA_INTERNATIONAL | PDU_TOA_ISDN; // 91
- number = number.substring(1);
- }
- GsmPDUHelper.writeHexOctet(toa);
- GsmPDUHelper.writeSwappedNibbleBCD(number);
- },
-
- readNumberWithLength: function() {
- let Buf = this.context.Buf;
- let number = "";
- let numLen = this.context.GsmPDUHelper.readHexOctet();
- if (numLen != 0xff) {
- if (numLen > ADN_MAX_BCD_NUMBER_BYTES) {
- if (DEBUG) {
- this.context.debug(
- "Error: invalid length of BCD number/SSC contents - " + numLen);
- }
- Buf.seekIncoming(ADN_MAX_BCD_NUMBER_BYTES * Buf.PDU_HEX_OCTET_SIZE);
- return number;
- }
-
- number = this.readDiallingNumber(numLen);
- Buf.seekIncoming((ADN_MAX_BCD_NUMBER_BYTES - numLen) * Buf.PDU_HEX_OCTET_SIZE);
- } else {
- Buf.seekIncoming(ADN_MAX_BCD_NUMBER_BYTES * Buf.PDU_HEX_OCTET_SIZE);
- }
-
- return number;
- },
-
- /**
- * Write Number with Length
- *
- * @param number The value to be written.
- *
- * @return The number has been written into Buf.
- */
- writeNumberWithLength: function(number) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- if (number) {
- let numStart = number[0] == "+" ? 1 : 0;
- let writtenNumber = number.substring(0, numStart) +
- number.substring(numStart)
- .replace(/[^0-9*#,]/g, "");
- let numDigits = writtenNumber.length - numStart;
-
- if (numDigits > ADN_MAX_NUMBER_DIGITS) {
- writtenNumber = writtenNumber.substring(0, ADN_MAX_NUMBER_DIGITS + numStart);
- numDigits = writtenNumber.length - numStart;
- }
-
- // +1 for TON/NPI
- let numLen = Math.ceil(numDigits / 2) + 1;
- GsmPDUHelper.writeHexOctet(numLen);
- this.writeDiallingNumber(writtenNumber.replace(/\*/g, "a")
- .replace(/\#/g, "b")
- .replace(/\,/g, "c"));
- // Write trailing 0xff of Dialling Number.
- for (let i = 0; i < ADN_MAX_BCD_NUMBER_BYTES - numLen; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- return writtenNumber;
- } else {
- // +1 for numLen
- for (let i = 0; i < ADN_MAX_BCD_NUMBER_BYTES + 1; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- return "";
- }
- }
-};
-
-function StkCommandParamsFactoryObject(aContext) {
- this.context = aContext;
-}
-StkCommandParamsFactoryObject.prototype = {
- context: null,
-
- createParam: function(cmdDetails, ctlvs, onComplete) {
- let method = this[cmdDetails.typeOfCommand];
- if (typeof method != "function") {
- if (DEBUG) {
- this.context.debug("Unknown proactive command " +
- cmdDetails.typeOfCommand.toString(16));
- }
- return;
- }
- method.call(this, cmdDetails, ctlvs, onComplete);
- },
-
- loadIcons: function(iconIdCtlvs, callback) {
- if (!iconIdCtlvs ||
- !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
- callback(null);
- return;
- }
-
- let onerror = (function() {
- callback(null);
- }).bind(this);
-
- let onsuccess = (function(aIcons) {
- callback(aIcons);
- }).bind(this);
-
- this.context.IconLoader.loadIcons(iconIdCtlvs.map(aCtlv => aCtlv.value.identifier),
- onsuccess,
- onerror);
- },
-
- appendIconIfNecessary: function(iconIdCtlvs, result, onComplete) {
- this.loadIcons(iconIdCtlvs, (aIcons) => {
- if (aIcons) {
- result.icons = aIcons[0];
- result.iconSelfExplanatory =
- iconIdCtlvs[0].value.qualifier == 0 ? true : false;
- }
-
- onComplete(result);
- });
- },
-
- /**
- * Construct a param for Refresh.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processRefresh: function(cmdDetails, ctlvs, onComplete) {
- let refreshType = cmdDetails.commandQualifier;
- switch (refreshType) {
- case STK_REFRESH_FILE_CHANGE:
- case STK_REFRESH_NAA_INIT_AND_FILE_CHANGE:
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_FILE_LIST, ctlvs);
- if (ctlv) {
- let list = ctlv.value.fileList;
- if (DEBUG) {
- this.context.debug("Refresh, list = " + list);
- }
- this.context.ICCRecordHelper.fetchICCRecords();
- }
- break;
- }
-
- onComplete(null);
- },
-
- /**
- * Construct a param for Poll Interval.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processPollInterval: function(cmdDetails, ctlvs, onComplete) {
- // Duration is mandatory.
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_DURATION, ctlvs);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Poll Interval: Required value missing : Duration");
- }
-
- onComplete(ctlv.value);
- },
-
- /**
- * Construct a param for Poll Off.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processPollOff: function(cmdDetails, ctlvs, onComplete) {
- onComplete(null);
- },
-
- /**
- * Construct a param for Set Up Event list.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSetUpEventList: function(cmdDetails, ctlvs, onComplete) {
- // Event list is mandatory.
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_EVENT_LIST, ctlvs);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Event List: Required value missing : Event List");
- }
-
- onComplete(ctlv.value || { eventList: null });
- },
-
- /**
- * Construct a param for Setup Menu.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSetupMenu: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let menu = {
- // Help information available.
- isHelpAvailable: !!(cmdDetails.commandQualifier & 0x80)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ITEM,
- COMPREHENSIONTLV_TAG_ITEM_ID,
- COMPREHENSIONTLV_TAG_NEXT_ACTION_IND,
- COMPREHENSIONTLV_TAG_ICON_ID,
- COMPREHENSIONTLV_TAG_ICON_ID_LIST
- ]);
-
- // Alpha identifier is optional.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- menu.title = ctlv.value.identifier;
- }
-
- // Item data object for item 1 is mandatory.
- let menuCtlvs = selectedCtlvs[COMPREHENSIONTLV_TAG_ITEM];
- if (!menuCtlvs) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Menu: Required value missing : items");
- }
- menu.items = menuCtlvs.map(aCtlv => aCtlv.value);
-
- // Item identifier is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ITEM_ID);
- if (ctlv) {
- menu.defaultItem = ctlv.value.identifier - 1;
- }
-
- // Items next action indicator is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_NEXT_ACTION_IND);
- if (ctlv) {
- menu.nextActionList = ctlv.value;
- }
-
- // Icon identifier is optional.
- let iconIdCtlvs = null;
- let menuIconCtlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ICON_ID);
- if (menuIconCtlv) {
- iconIdCtlvs = [menuIconCtlv];
- }
-
- // Item icon identifier list is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ICON_ID_LIST);
- if (ctlv) {
- if (!iconIdCtlvs) {
- iconIdCtlvs = [];
- };
- let iconIdList = ctlv.value;
- iconIdCtlvs = iconIdCtlvs.concat(iconIdList.identifiers.map((aId) => {
- return {
- value: { qualifier: iconIdList.qualifier, identifier: aId }
- };
- }));
- }
-
- this.loadIcons(iconIdCtlvs, (aIcons) => {
- if (aIcons) {
- if (menuIconCtlv) {
- menu.iconSelfExplanatory =
- (iconIdCtlvs.shift().value.qualifier == 0) ? true: false;
- menu.icons = aIcons.shift();
- }
-
- for (let i = 0; i < aIcons.length; i++) {
- menu.items[i].icons = aIcons[i];
- menu.items[i].iconSelfExplanatory =
- (iconIdCtlvs[i].value.qualifier == 0) ? true: false;
- }
- }
-
- onComplete(menu);
- });
- },
-
- /**
- * Construct a param for Select Item.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSelectItem: function(cmdDetails, ctlvs, onComplete) {
- this.processSetupMenu(cmdDetails, ctlvs, (menu) => {
- // The 1st bit and 2nd bit determines the presentation type.
- menu.presentationType = cmdDetails.commandQualifier & 0x03;
- onComplete(menu);
- });
- },
-
- /**
- * Construct a param for Display Text.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processDisplayText: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let textMsg = {
- isHighPriority: !!(cmdDetails.commandQualifier & 0x01),
- userClear: !!(cmdDetails.commandQualifier & 0x80)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TEXT_STRING,
- COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE,
- COMPREHENSIONTLV_TAG_DURATION,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Text string is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TEXT_STRING);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Display Text: Required value missing : Text String");
- }
- textMsg.text = ctlv.value.textString;
-
- // Immediate response is optional.
- textMsg.responseNeeded =
- !!(selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE));
-
- // Duration is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DURATION);
- if (ctlv) {
- textMsg.duration = ctlv.value;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- textMsg,
- onComplete);
- },
-
- /**
- * Construct a param for Setup Idle Mode Text.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSetUpIdleModeText: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let textMsg = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TEXT_STRING,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Text string is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TEXT_STRING);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Set Up Idle Text: Required value missing : Text String");
- }
- textMsg.text = ctlv.value.textString;
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- textMsg,
- onComplete);
- },
-
- /**
- * Construct a param for Get Inkey.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processGetInkey: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let input = {
- minLength: 1,
- maxLength: 1,
- isAlphabet: !!(cmdDetails.commandQualifier & 0x01),
- isUCS2: !!(cmdDetails.commandQualifier & 0x02),
- // Character sets defined in bit 1 and bit 2 are disable and
- // the YES/NO reponse is required.
- isYesNoRequested: !!(cmdDetails.commandQualifier & 0x04),
- // Help information available.
- isHelpAvailable: !!(cmdDetails.commandQualifier & 0x80)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TEXT_STRING,
- COMPREHENSIONTLV_TAG_DURATION,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Text string is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TEXT_STRING);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Get InKey: Required value missing : Text String");
- }
- input.text = ctlv.value.textString;
-
- // Duration is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DURATION);
- if (ctlv) {
- input.duration = ctlv.value;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- input,
- onComplete);
- },
-
- /**
- * Construct a param for Get Input.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processGetInput: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let input = {
- isAlphabet: !!(cmdDetails.commandQualifier & 0x01),
- isUCS2: !!(cmdDetails.commandQualifier & 0x02),
- // User input shall not be revealed
- hideInput: !!(cmdDetails.commandQualifier & 0x04),
- // User input in SMS packed format
- isPacked: !!(cmdDetails.commandQualifier & 0x08),
- // Help information available.
- isHelpAvailable: !!(cmdDetails.commandQualifier & 0x80)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TEXT_STRING,
- COMPREHENSIONTLV_TAG_RESPONSE_LENGTH,
- COMPREHENSIONTLV_TAG_DEFAULT_TEXT,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Text string is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TEXT_STRING);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Get Input: Required value missing : Text String");
- }
- input.text = ctlv.value.textString;
-
- // Response length is mandatory.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_RESPONSE_LENGTH);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Get Input: Required value missing : Response Length");
- }
- input.minLength = ctlv.value.minLength;
- input.maxLength = ctlv.value.maxLength;
-
- // Default text is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DEFAULT_TEXT);
- if (ctlv) {
- input.defaultText = ctlv.value.textString;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- input,
- onComplete);
- },
-
- /**
- * Construct a param for SendSS/SMS/USSD/DTMF.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processEventNotify: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let textMsg = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Alpha identifier is optional.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- textMsg.text = ctlv.value.identifier;
- }
-
- // According to section 6.4.10 of |ETSI TS 102 223|:
- //
- // - if the alpha identifier is provided by the UICC and is a null data
- // object (i.e. length = '00' and no value part), this is an indication
- // that the terminal should not give any information to the user on the
- // fact that the terminal is sending a short message;
- //
- // - if the alpha identifier is not provided by the UICC, the terminal may
- // give information to the user concerning what is happening.
- //
- // ICCPDUHelper reads alpha id as an empty string if the length is zero,
- // hence we'll notify the caller when it's not an empty string.
- if (textMsg.text !== "") {
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- textMsg,
- onComplete);
- }
- },
-
- /**
- * Construct a param for Setup Call.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSetupCall: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let call = {};
- let confirmMessage = {};
- let callMessage = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ADDRESS,
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ICON_ID,
- COMPREHENSIONTLV_TAG_DURATION
- ]);
-
- // Address is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ADDRESS);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Set Up Call: Required value missing : Address");
- }
- call.address = ctlv.value.number;
-
- // Alpha identifier (user confirmation phase) is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- confirmMessage.text = ctlv.value.identifier;
- call.confirmMessage = confirmMessage;
- }
-
- // Alpha identifier (call set up phase) is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- callMessage.text = ctlv.value.identifier;
- call.callMessage = callMessage;
- }
-
- // Duration is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DURATION);
- if (ctlv) {
- call.duration = ctlv.value;
- }
-
- // Icon identifier is optional.
- let iconIdCtlvs = selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null;
- this.loadIcons(iconIdCtlvs, (aIcons) => {
- if (aIcons) {
- confirmMessage.icons = aIcons[0];
- confirmMessage.iconSelfExplanatory =
- (iconIdCtlvs[0].value.qualifier == 0) ? true: false;
- call.confirmMessage = confirmMessage;
-
- if (aIcons.length > 1) {
- callMessage.icons = aIcons[1];
- callMessage.iconSelfExplanatory =
- (iconIdCtlvs[1].value.qualifier == 0) ? true: false;
- call.callMessage = callMessage;
- }
- }
-
- onComplete(call);
- });
- },
-
- /**
- * Construct a param for Launch Browser.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processLaunchBrowser: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let browser = {
- mode: cmdDetails.commandQualifier & 0x03
- };
- let confirmMessage = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_URL,
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // URL is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_URL);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Launch Browser: Required value missing : URL");
- }
- browser.url = ctlv.value.url;
-
- // Alpha identifier is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- confirmMessage.text = ctlv.value.identifier;
- browser.confirmMessage = confirmMessage;
- }
-
- // Icon identifier is optional.
- let iconIdCtlvs = selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null;
- this.loadIcons(iconIdCtlvs, (aIcons) => {
- if (aIcons) {
- confirmMessage.icons = aIcons[0];
- confirmMessage.iconSelfExplanatory =
- (iconIdCtlvs[0].value.qualifier == 0) ? true: false;
- browser.confirmMessage = confirmMessage;
- }
-
- onComplete(browser);
- });
- },
-
- /**
- * Construct a param for Play Tone.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processPlayTone: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let playTone = {
- // The vibrate is only defined in TS 102.223.
- isVibrate: !!(cmdDetails.commandQualifier & 0x01)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_TONE,
- COMPREHENSIONTLV_TAG_DURATION,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Alpha identifier is optional.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- playTone.text = ctlv.value.identifier;
- }
-
- // Tone is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TONE);
- if (ctlv) {
- playTone.tone = ctlv.value.tone;
- }
-
- // Duration is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DURATION);
- if (ctlv) {
- playTone.duration = ctlv.value;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- playTone,
- onComplete);
- },
-
- /**
- * Construct a param for Provide Local Information.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processProvideLocalInfo: function(cmdDetails, ctlvs, onComplete) {
- let provideLocalInfo = {
- localInfoType: cmdDetails.commandQualifier
- };
-
- onComplete(provideLocalInfo);
- },
-
- /**
- * Construct a param for Timer Management.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processTimerManagement: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let timer = {
- timerAction: cmdDetails.commandQualifier
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER,
- COMPREHENSIONTLV_TAG_TIMER_VALUE
- ]);
-
- // Timer identifier is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Timer Management: Required value missing : Timer Identifier");
- }
- timer.timerId = ctlv.value.timerId;
-
- // Timer value is conditional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TIMER_VALUE);
- if (ctlv) {
- timer.timerValue = ctlv.value.timerValue;
- }
-
- onComplete(timer);
- },
-
- /**
- * Construct a param for BIP commands.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processBipMessage: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let bipMsg = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Alpha identifier is optional.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- bipMsg.text = ctlv.value.identifier;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- bipMsg,
- onComplete);
- }
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_REFRESH] = function STK_CMD_REFRESH(cmdDetails, ctlvs, onComplete) {
- return this.processRefresh(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_POLL_INTERVAL] = function STK_CMD_POLL_INTERVAL(cmdDetails, ctlvs, onComplete) {
- return this.processPollInterval(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_POLL_OFF] = function STK_CMD_POLL_OFF(cmdDetails, ctlvs, onComplete) {
- return this.processPollOff(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_PROVIDE_LOCAL_INFO] = function STK_CMD_PROVIDE_LOCAL_INFO(cmdDetails, ctlvs, onComplete) {
- return this.processProvideLocalInfo(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_EVENT_LIST] = function STK_CMD_SET_UP_EVENT_LIST(cmdDetails, ctlvs, onComplete) {
- return this.processSetUpEventList(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_MENU] = function STK_CMD_SET_UP_MENU(cmdDetails, ctlvs, onComplete) {
- return this.processSetupMenu(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SELECT_ITEM] = function STK_CMD_SELECT_ITEM(cmdDetails, ctlvs, onComplete) {
- return this.processSelectItem(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_DISPLAY_TEXT] = function STK_CMD_DISPLAY_TEXT(cmdDetails, ctlvs, onComplete) {
- return this.processDisplayText(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_IDLE_MODE_TEXT] = function STK_CMD_SET_UP_IDLE_MODE_TEXT(cmdDetails, ctlvs, onComplete) {
- return this.processSetUpIdleModeText(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_GET_INKEY] = function STK_CMD_GET_INKEY(cmdDetails, ctlvs, onComplete) {
- return this.processGetInkey(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_GET_INPUT] = function STK_CMD_GET_INPUT(cmdDetails, ctlvs, onComplete) {
- return this.processGetInput(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_SS] = function STK_CMD_SEND_SS(cmdDetails, ctlvs, onComplete) {
- return this.processEventNotify(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_USSD] = function STK_CMD_SEND_USSD(cmdDetails, ctlvs, onComplete) {
- return this.processEventNotify(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_SMS] = function STK_CMD_SEND_SMS(cmdDetails, ctlvs, onComplete) {
- return this.processEventNotify(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_DTMF] = function STK_CMD_SEND_DTMF(cmdDetails, ctlvs, onComplete) {
- return this.processEventNotify(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_CALL] = function STK_CMD_SET_UP_CALL(cmdDetails, ctlvs, onComplete) {
- return this.processSetupCall(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_LAUNCH_BROWSER] = function STK_CMD_LAUNCH_BROWSER(cmdDetails, ctlvs, onComplete) {
- return this.processLaunchBrowser(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_PLAY_TONE] = function STK_CMD_PLAY_TONE(cmdDetails, ctlvs, onComplete) {
- return this.processPlayTone(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_TIMER_MANAGEMENT] = function STK_CMD_TIMER_MANAGEMENT(cmdDetails, ctlvs, onComplete) {
- return this.processTimerManagement(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_OPEN_CHANNEL] = function STK_CMD_OPEN_CHANNEL(cmdDetails, ctlvs, onComplete) {
- return this.processBipMessage(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_CLOSE_CHANNEL] = function STK_CMD_CLOSE_CHANNEL(cmdDetails, ctlvs, onComplete) {
- return this.processBipMessage(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_RECEIVE_DATA] = function STK_CMD_RECEIVE_DATA(cmdDetails, ctlvs, onComplete) {
- return this.processBipMessage(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_DATA] = function STK_CMD_SEND_DATA(cmdDetails, ctlvs, onComplete) {
- return this.processBipMessage(cmdDetails, ctlvs, onComplete);
-};
-
-function StkProactiveCmdHelperObject(aContext) {
- this.context = aContext;
-}
-StkProactiveCmdHelperObject.prototype = {
- context: null,
-
- retrieve: function(tag, length) {
- let method = this[tag];
- if (typeof method != "function") {
- if (DEBUG) {
- this.context.debug("Unknown comprehension tag " + tag.toString(16));
- }
- let Buf = this.context.Buf;
- Buf.seekIncoming(length * Buf.PDU_HEX_OCTET_SIZE);
- return null;
- }
- return method.call(this, length);
- },
-
- /**
- * Command Details.
- *
- * | Byte | Description | Length |
- * | 1 | Command details Tag | 1 |
- * | 2 | Length = 03 | 1 |
- * | 3 | Command number | 1 |
- * | 4 | Type of Command | 1 |
- * | 5 | Command Qualifier | 1 |
- */
- retrieveCommandDetails: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let cmdDetails = {
- commandNumber: GsmPDUHelper.readHexOctet(),
- typeOfCommand: GsmPDUHelper.readHexOctet(),
- commandQualifier: GsmPDUHelper.readHexOctet()
- };
- return cmdDetails;
- },
-
- /**
- * Device Identities.
- *
- * | Byte | Description | Length |
- * | 1 | Device Identity Tag | 1 |
- * | 2 | Length = 02 | 1 |
- * | 3 | Source device Identity | 1 |
- * | 4 | Destination device Id | 1 |
- */
- retrieveDeviceId: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let deviceId = {
- sourceId: GsmPDUHelper.readHexOctet(),
- destinationId: GsmPDUHelper.readHexOctet()
- };
- return deviceId;
- },
-
- /**
- * Alpha Identifier.
- *
- * | Byte | Description | Length |
- * | 1 | Alpha Identifier Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 ~ | Alpha identfier | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveAlphaId: function(length) {
- let alphaId = {
- identifier: this.context.ICCPDUHelper.readAlphaIdentifier(length)
- };
- return alphaId;
- },
-
- /**
- * Duration.
- *
- * | Byte | Description | Length |
- * | 1 | Response Length Tag | 1 |
- * | 2 | Lenth = 02 | 1 |
- * | 3 | Time unit | 1 |
- * | 4 | Time interval | 1 |
- */
- retrieveDuration: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let duration = {
- timeUnit: GsmPDUHelper.readHexOctet(),
- timeInterval: GsmPDUHelper.readHexOctet(),
- };
- return duration;
- },
-
- /**
- * Address.
- *
- * | Byte | Description | Length |
- * | 1 | Alpha Identifier Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 | TON and NPI | 1 |
- * | (Y-1)+4 ~ | Dialling number | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveAddress: function(length) {
- let address = {
- number : this.context.ICCPDUHelper.readDiallingNumber(length)
- };
- return address;
- },
-
- /**
- * Text String.
- *
- * | Byte | Description | Length |
- * | 1 | Text String Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 | Data coding scheme | 1 |
- * | (Y-1)+4~ | Text String | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveTextString: function(length) {
- if (!length) {
- // null string.
- return {textString: null};
- }
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let text = {
- codingScheme: GsmPDUHelper.readHexOctet()
- };
-
- length--; // -1 for the codingScheme.
- switch (text.codingScheme & 0x0c) {
- case STK_TEXT_CODING_GSM_7BIT_PACKED:
- text.textString =
- GsmPDUHelper.readSeptetsToString(Math.floor(length * 8 / 7), 0, 0, 0);
- break;
- case STK_TEXT_CODING_GSM_8BIT:
- text.textString =
- this.context.ICCPDUHelper.read8BitUnpackedToString(length);
- break;
- case STK_TEXT_CODING_UCS2:
- text.textString = GsmPDUHelper.readUCS2String(length);
- break;
- }
- return text;
- },
-
- /**
- * Tone.
- *
- * | Byte | Description | Length |
- * | 1 | Tone Tag | 1 |
- * | 2 | Lenth = 01 | 1 |
- * | 3 | Tone | 1 |
- */
- retrieveTone: function(length) {
- let tone = {
- tone: this.context.GsmPDUHelper.readHexOctet(),
- };
- return tone;
- },
-
- /**
- * Item.
- *
- * | Byte | Description | Length |
- * | 1 | Item Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 | Identifier of item | 1 |
- * | (Y-1)+4 ~ | Text string of item | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveItem: function(length) {
- // TS 102.223 ,clause 6.6.7 SET-UP MENU
- // If the "Item data object for item 1" is a null data object
- // (i.e. length = '00' and no value part), this is an indication to the ME
- // to remove the existing menu from the menu system in the ME.
- if (!length) {
- return null;
- }
- let item = {
- identifier: this.context.GsmPDUHelper.readHexOctet(),
- text: this.context.ICCPDUHelper.readAlphaIdentifier(length - 1)
- };
- return item;
- },
-
- /**
- * Item Identifier.
- *
- * | Byte | Description | Length |
- * | 1 | Item Identifier Tag | 1 |
- * | 2 | Lenth = 01 | 1 |
- * | 3 | Identifier of Item chosen | 1 |
- */
- retrieveItemId: function(length) {
- let itemId = {
- identifier: this.context.GsmPDUHelper.readHexOctet()
- };
- return itemId;
- },
-
- /**
- * Response Length.
- *
- * | Byte | Description | Length |
- * | 1 | Response Length Tag | 1 |
- * | 2 | Lenth = 02 | 1 |
- * | 3 | Minimum length of response | 1 |
- * | 4 | Maximum length of response | 1 |
- */
- retrieveResponseLength: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let rspLength = {
- minLength : GsmPDUHelper.readHexOctet(),
- maxLength : GsmPDUHelper.readHexOctet()
- };
- return rspLength;
- },
-
- /**
- * File List.
- *
- * | Byte | Description | Length |
- * | 1 | File List Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 | Number of files | 1 |
- * | (Y-1)+4 ~ | Files | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveFileList: function(length) {
- let num = this.context.GsmPDUHelper.readHexOctet();
- let fileList = "";
- length--; // -1 for the num octet.
- for (let i = 0; i < 2 * length; i++) {
- // Didn't use readHexOctet here,
- // otherwise 0x00 will be "0", not "00"
- fileList += String.fromCharCode(this.context.Buf.readUint16());
- }
- return {
- fileList: fileList
- };
- },
-
- /**
- * Default Text.
- *
- * Same as Text String.
- */
- retrieveDefaultText: function(length) {
- return this.retrieveTextString(length);
- },
-
- /**
- * Event List.
- */
- retrieveEventList: function(length) {
- if (!length) {
- // null means an indication to ME to remove the existing list of events
- // in ME.
- return null;
- }
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let eventList = [];
- for (let i = 0; i < length; i++) {
- eventList.push(GsmPDUHelper.readHexOctet());
- }
- return {
- eventList: eventList
- };
- },
-
- /**
- * Icon Id.
- *
- * | Byte | Description | Length |
- * | 1 | Icon Identifier Tag | 1 |
- * | 2 | Length = 02 | 1 |
- * | 3 | Icon qualifier | 1 |
- * | 4 | Icon identifier | 1 |
- */
- retrieveIconId: function(length) {
- if (!length) {
- return null;
- }
-
- let iconId = {
- qualifier: this.context.GsmPDUHelper.readHexOctet(),
- identifier: this.context.GsmPDUHelper.readHexOctet()
- };
- return iconId;
- },
-
- /**
- * Icon Id List.
- *
- * | Byte | Description | Length |
- * | 1 | Icon Identifier Tag | 1 |
- * | 2 | Length = X | 1 |
- * | 3 | Icon qualifier | 1 |
- * | 4~ | Icon identifier | X-1 |
- * | 4+X-2 | | |
- */
- retrieveIconIdList: function(length) {
- if (!length) {
- return null;
- }
-
- let iconIdList = {
- qualifier: this.context.GsmPDUHelper.readHexOctet(),
- identifiers: []
- };
- for (let i = 0; i < length - 1; i++) {
- iconIdList.identifiers.push(this.context.GsmPDUHelper.readHexOctet());
- }
- return iconIdList;
- },
-
- /**
- * Timer Identifier.
- *
- * | Byte | Description | Length |
- * | 1 | Timer Identifier Tag | 1 |
- * | 2 | Length = 01 | 1 |
- * | 3 | Timer Identifier | 1 |
- */
- retrieveTimerId: function(length) {
- let id = {
- timerId: this.context.GsmPDUHelper.readHexOctet()
- };
- return id;
- },
-
- /**
- * Timer Value.
- *
- * | Byte | Description | Length |
- * | 1 | Timer Value Tag | 1 |
- * | 2 | Length = 03 | 1 |
- * | 3 | Hour | 1 |
- * | 4 | Minute | 1 |
- * | 5 | Second | 1 |
- */
- retrieveTimerValue: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let value = {
- timerValue: (GsmPDUHelper.readSwappedNibbleBcdNum(1) * 60 * 60) +
- (GsmPDUHelper.readSwappedNibbleBcdNum(1) * 60) +
- (GsmPDUHelper.readSwappedNibbleBcdNum(1))
- };
- return value;
- },
-
- /**
- * Immediate Response.
- *
- * | Byte | Description | Length |
- * | 1 | Immediate Response Tag | 1 |
- * | 2 | Length = 00 | 1 |
- */
- retrieveImmediaResponse: function(length) {
- return {};
- },
-
- /**
- * URL
- *
- * | Byte | Description | Length |
- * | 1 | URL Tag | 1 |
- * | 2 ~ (Y+1) | Length(X) | Y |
- * | (Y+2) ~ | URL | X |
- * | (Y+1+X) | | |
- */
- retrieveUrl: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let s = "";
- for (let i = 0; i < length; i++) {
- s += String.fromCharCode(GsmPDUHelper.readHexOctet());
- }
- return {url: s};
- },
-
- /**
- * Next Action Indicator List.
- *
- * | Byte | Description | Length |
- * | 1 | Next Action tag | 1 |
- * | 1 | Length(X) | 1 |
- * | 3~ | Next Action List | X |
- * | 3+X-1 | | |
- */
- retrieveNextActionList: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let nextActionList = [];
- for (let i = 0; i < length; i++) {
- nextActionList.push(GsmPDUHelper.readHexOctet());
- }
- return nextActionList;
- },
-
- searchForTag: function(tag, ctlvs) {
- for (let ctlv of ctlvs) {
- if ((ctlv.tag & ~COMPREHENSIONTLV_FLAG_CR) == tag) {
- return ctlv;
- }
- }
- return null;
- },
-
- searchForSelectedTags: function(ctlvs, tags) {
- let ret = {
- // Handy utility to de-queue the 1st ctlv of the specified tag.
- retrieve: function(aTag) {
- return (this[aTag]) ? this[aTag].shift() : null;
- }
- };
-
- ctlvs.forEach((aCtlv) => {
- tags.forEach((aTag) => {
- if ((aCtlv.tag & ~COMPREHENSIONTLV_FLAG_CR) == aTag) {
- if (!ret[aTag]) {
- ret[aTag] = [];
- }
- ret[aTag].push(aCtlv);
- }
- });
- });
-
- return ret;
- },
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_COMMAND_DETAILS] = function COMPREHENSIONTLV_TAG_COMMAND_DETAILS(length) {
- return this.retrieveCommandDetails(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DEVICE_ID] = function COMPREHENSIONTLV_TAG_DEVICE_ID(length) {
- return this.retrieveDeviceId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ALPHA_ID] = function COMPREHENSIONTLV_TAG_ALPHA_ID(length) {
- return this.retrieveAlphaId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DURATION] = function COMPREHENSIONTLV_TAG_DURATION(length) {
- return this.retrieveDuration(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ADDRESS] = function COMPREHENSIONTLV_TAG_ADDRESS(length) {
- return this.retrieveAddress(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TEXT_STRING] = function COMPREHENSIONTLV_TAG_TEXT_STRING(length) {
- return this.retrieveTextString(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TONE] = function COMPREHENSIONTLV_TAG_TONE(length) {
- return this.retrieveTone(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ITEM] = function COMPREHENSIONTLV_TAG_ITEM(length) {
- return this.retrieveItem(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ITEM_ID] = function COMPREHENSIONTLV_TAG_ITEM_ID(length) {
- return this.retrieveItemId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_RESPONSE_LENGTH] = function COMPREHENSIONTLV_TAG_RESPONSE_LENGTH(length) {
- return this.retrieveResponseLength(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_FILE_LIST] = function COMPREHENSIONTLV_TAG_FILE_LIST(length) {
- return this.retrieveFileList(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DEFAULT_TEXT] = function COMPREHENSIONTLV_TAG_DEFAULT_TEXT(length) {
- return this.retrieveDefaultText(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_EVENT_LIST] = function COMPREHENSIONTLV_TAG_EVENT_LIST(length) {
- return this.retrieveEventList(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ICON_ID] = function COMPREHENSIONTLV_TAG_ICON_ID(length) {
- return this.retrieveIconId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ICON_ID_LIST] = function COMPREHENSIONTLV_TAG_ICON_ID_LIST(length) {
- return this.retrieveIconIdList(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER] = function COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER(length) {
- return this.retrieveTimerId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TIMER_VALUE] = function COMPREHENSIONTLV_TAG_TIMER_VALUE(length) {
- return this.retrieveTimerValue(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE] = function COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE(length) {
- return this.retrieveImmediaResponse(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_URL] = function COMPREHENSIONTLV_TAG_URL(length) {
- return this.retrieveUrl(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_NEXT_ACTION_IND] = function COMPREHENSIONTLV_TAG_NEXT_ACTION_IND(length) {
- return this.retrieveNextActionList(length);
-};
-
-function ComprehensionTlvHelperObject(aContext) {
- this.context = aContext;
-}
-ComprehensionTlvHelperObject.prototype = {
- context: null,
-
- /**
- * Decode raw data to a Comprehension-TLV.
- */
- decode: function() {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let hlen = 0; // For header(tag field + length field) length.
- let temp = GsmPDUHelper.readHexOctet();
- hlen++;
-
- // TS 101.220, clause 7.1.1
- let tag, cr;
- switch (temp) {
- // TS 101.220, clause 7.1.1
- case 0x0: // Not used.
- case 0xff: // Not used.
- case 0x80: // Reserved for future use.
- throw new Error("Invalid octet when parsing Comprehension TLV :" + temp);
- case 0x7f: // Tag is three byte format.
- // TS 101.220 clause 7.1.1.2.
- // | Byte 1 | Byte 2 | Byte 3 |
- // | | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
- // | 0x7f |CR | Tag Value |
- tag = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- hlen += 2;
- cr = (tag & 0x8000) !== 0;
- tag &= ~0x8000;
- break;
- default: // Tag is single byte format.
- tag = temp;
- // TS 101.220 clause 7.1.1.1.
- // | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
- // |CR | Tag Value |
- cr = (tag & 0x80) !== 0;
- tag &= ~0x80;
- }
-
- // TS 101.220 clause 7.1.2, Length Encoding.
- // Length | Byte 1 | Byte 2 | Byte 3 | Byte 4 |
- // 0 - 127 | 00 - 7f | N/A | N/A | N/A |
- // 128-255 | 81 | 80 - ff| N/A | N/A |
- // 256-65535| 82 | 0100 - ffff | N/A |
- // 65536- | 83 | 010000 - ffffff |
- // 16777215
- //
- // Length errors: TS 11.14, clause 6.10.6
-
- let length; // Data length.
- temp = GsmPDUHelper.readHexOctet();
- hlen++;
- if (temp < 0x80) {
- length = temp;
- } else if (temp == 0x81) {
- length = GsmPDUHelper.readHexOctet();
- hlen++;
- if (length < 0x80) {
- throw new Error("Invalid length in Comprehension TLV :" + length);
- }
- } else if (temp == 0x82) {
- length = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- hlen += 2;
- if (lenth < 0x0100) {
- throw new Error("Invalid length in 3-byte Comprehension TLV :" + length);
- }
- } else if (temp == 0x83) {
- length = (GsmPDUHelper.readHexOctet() << 16) |
- (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet();
- hlen += 3;
- if (length < 0x010000) {
- throw new Error("Invalid length in 4-byte Comprehension TLV :" + length);
- }
- } else {
- throw new Error("Invalid octet in Comprehension TLV :" + temp);
- }
-
- let ctlv = {
- tag: tag,
- length: length,
- value: this.context.StkProactiveCmdHelper.retrieve(tag, length),
- cr: cr,
- hlen: hlen
- };
- return ctlv;
- },
-
- decodeChunks: function(length) {
- let chunks = [];
- let index = 0;
- while (index < length) {
- let tlv = this.decode();
- chunks.push(tlv);
- index += tlv.length;
- index += tlv.hlen;
- }
- return chunks;
- },
-
- /**
- * Write Location Info Comprehension TLV.
- *
- * @param loc location Information.
- */
- writeLocationInfoTlv: function(loc) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(loc.gsmCellId > 0xffff ? 9 : 7);
- // From TS 11.14, clause 12.19
- // "The mobile country code (MCC), the mobile network code (MNC),
- // the location area code (LAC) and the cell ID are
- // coded as in TS 04.08."
- // And from TS 04.08 and TS 24.008,
- // the format is as follows:
- //
- // MCC = MCC_digit_1 + MCC_digit_2 + MCC_digit_3
- //
- // 8 7 6 5 4 3 2 1
- // +-------------+-------------+
- // | MCC digit 2 | MCC digit 1 | octet 2
- // | MNC digit 3 | MCC digit 3 | octet 3
- // | MNC digit 2 | MNC digit 1 | octet 4
- // +-------------+-------------+
- //
- // Also in TS 24.008
- // "However a network operator may decide to
- // use only two digits in the MNC in the LAI over the
- // radio interface. In this case, bits 5 to 8 of octet 3
- // shall be coded as '1111'".
-
- // MCC & MNC, 3 octets
- let mcc = loc.mcc, mnc;
- if (loc.mnc.length == 2) {
- mnc = "F" + loc.mnc;
- } else {
- mnc = loc.mnc[2] + loc.mnc[0] + loc.mnc[1];
- }
- GsmPDUHelper.writeSwappedNibbleBCD(mcc + mnc);
-
- // LAC, 2 octets
- GsmPDUHelper.writeHexOctet((loc.gsmLocationAreaCode >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(loc.gsmLocationAreaCode & 0xff);
-
- // Cell Id
- if (loc.gsmCellId > 0xffff) {
- // UMTS/WCDMA, gsmCellId is 28 bits.
- GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 24) & 0xff);
- GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 16) & 0xff);
- GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(loc.gsmCellId & 0xff);
- } else {
- // GSM, gsmCellId is 16 bits.
- GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(loc.gsmCellId & 0xff);
- }
- },
-
- /**
- * Given a geckoError string, this function translates it into cause value
- * and write the value into buffer.
- *
- * @param geckoError Error string that is passed to gecko.
- */
- writeCauseTlv: function(geckoError) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let cause = -1;
- for (let errorNo in RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR) {
- if (geckoError == RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[errorNo]) {
- cause = errorNo;
- break;
- }
- }
-
- // Causes specified in 10.5.4.11 of TS 04.08 are less than 128.
- // we can ignore causes > 127 since Cause TLV is optional in
- // STK_EVENT_TYPE_CALL_DISCONNECTED.
- if (cause > 127) {
- return;
- }
-
- cause = (cause == -1) ? ERROR_SUCCESS : cause;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_CAUSE |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(2); // For single cause value.
-
- // TS 04.08, clause 10.5.4.11:
- // Code Standard : Standard defined for GSM PLMNS
- // Location: User
- GsmPDUHelper.writeHexOctet(0x60);
-
- // TS 04.08, clause 10.5.4.11: ext bit = 1 + 7 bits for cause.
- // +-----------------+----------------------------------+
- // | Ext = 1 (1 bit) | Cause (7 bits) |
- // +-----------------+----------------------------------+
- GsmPDUHelper.writeHexOctet(0x80 | cause);
- },
-
- writeDateTimeZoneTlv: function(date) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DATE_TIME_ZONE);
- GsmPDUHelper.writeHexOctet(7);
- GsmPDUHelper.writeTimestamp(date);
- },
-
- writeLanguageTlv: function(language) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LANGUAGE);
- GsmPDUHelper.writeHexOctet(2);
-
- // ISO 639-1, Alpha-2 code
- // TS 123.038, clause 6.2.1, GSM 7 bit Default Alphabet
- GsmPDUHelper.writeHexOctet(
- PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[0]));
- GsmPDUHelper.writeHexOctet(
- PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[1]));
- },
-
- /**
- * Write Timer Value Comprehension TLV.
- *
- * @param seconds length of time during of the timer.
- * @param cr Comprehension Required or not
- */
- writeTimerValueTlv: function(seconds, cr) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_VALUE |
- (cr ? COMPREHENSIONTLV_FLAG_CR : 0));
- GsmPDUHelper.writeHexOctet(3);
-
- // TS 102.223, clause 8.38
- // +----------------+------------------+-------------------+
- // | hours (1 byte) | minutes (1 btye) | seconds (1 byte) |
- // +----------------+------------------+-------------------+
- GsmPDUHelper.writeSwappedNibbleBCDNum(Math.floor(seconds / 60 / 60));
- GsmPDUHelper.writeSwappedNibbleBCDNum(Math.floor(seconds / 60) % 60);
- GsmPDUHelper.writeSwappedNibbleBCDNum(Math.floor(seconds) % 60);
- },
-
- writeTextStringTlv: function(text, coding) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let buf = GsmPDUHelper.writeWithBuffer(() => {
- // Write Coding.
- GsmPDUHelper.writeHexOctet(coding);
-
- // Write Text String.
- switch (coding) {
- case STK_TEXT_CODING_UCS2:
- GsmPDUHelper.writeUCS2String(text);
- break;
- case STK_TEXT_CODING_GSM_7BIT_PACKED:
- GsmPDUHelper.writeStringAsSeptets(text, 0, 0, 0);
- break;
- case STK_TEXT_CODING_GSM_8BIT:
- GsmPDUHelper.writeStringAs8BitUnpacked(text);
- break;
- }
- });
-
- let length = buf.length;
- if (length) {
- // Write Tag.
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- // Write Length.
- this.writeLength(length);
- // Write Value.
- for (let i = 0; i < length; i++) {
- GsmPDUHelper.writeHexOctet(buf[i]);
- }
- }
- },
-
- getSizeOfLengthOctets: function(length) {
- if (length >= 0x10000) {
- return 4; // 0x83, len_1, len_2, len_3
- } else if (length >= 0x100) {
- return 3; // 0x82, len_1, len_2
- } else if (length >= 0x80) {
- return 2; // 0x81, len
- } else {
- return 1; // len
- }
- },
-
- writeLength: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // TS 101.220 clause 7.1.2, Length Encoding.
- // Length | Byte 1 | Byte 2 | Byte 3 | Byte 4 |
- // 0 - 127 | 00 - 7f | N/A | N/A | N/A |
- // 128-255 | 81 | 80 - ff| N/A | N/A |
- // 256-65535| 82 | 0100 - ffff | N/A |
- // 65536- | 83 | 010000 - ffffff |
- // 16777215
- if (length < 0x80) {
- GsmPDUHelper.writeHexOctet(length);
- } else if (0x80 <= length && length < 0x100) {
- GsmPDUHelper.writeHexOctet(0x81);
- GsmPDUHelper.writeHexOctet(length);
- } else if (0x100 <= length && length < 0x10000) {
- GsmPDUHelper.writeHexOctet(0x82);
- GsmPDUHelper.writeHexOctet((length >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(length & 0xff);
- } else if (0x10000 <= length && length < 0x1000000) {
- GsmPDUHelper.writeHexOctet(0x83);
- GsmPDUHelper.writeHexOctet((length >> 16) & 0xff);
- GsmPDUHelper.writeHexOctet((length >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(length & 0xff);
- } else {
- throw new Error("Invalid length value :" + length);
- }
- },
-};
-
-function BerTlvHelperObject(aContext) {
- this.context = aContext;
-}
-BerTlvHelperObject.prototype = {
- context: null,
-
- /**
- * Decode Ber TLV.
- *
- * @param dataLen
- * The length of data in bytes.
- */
- decode: function(dataLen) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let hlen = 0;
- let tag = GsmPDUHelper.readHexOctet();
- hlen++;
-
- // The length is coded onto 1 or 2 bytes.
- // Length | Byte 1 | Byte 2
- // 0 - 127 | length ('00' to '7f') | N/A
- // 128 - 255 | '81' | length ('80' to 'ff')
- let length;
- let temp = GsmPDUHelper.readHexOctet();
- hlen++;
- if (temp < 0x80) {
- length = temp;
- } else if (temp === 0x81) {
- length = GsmPDUHelper.readHexOctet();
- hlen++;
- if (length < 0x80) {
- throw new Error("Invalid length " + length);
- }
- } else {
- throw new Error("Invalid length octet " + temp);
- }
-
- // Header + body length check.
- if (dataLen - hlen !== length) {
- throw new Error("Unexpected BerTlvHelper value length!!");
- }
-
- let method = this[tag];
- if (typeof method != "function") {
- throw new Error("Unknown Ber tag 0x" + tag.toString(16));
- }
-
- let value = method.call(this, length);
-
- return {
- tag: tag,
- length: length,
- value: value
- };
- },
-
- /**
- * Process the value part for FCP template TLV.
- *
- * @param length
- * The length of data in bytes.
- */
- processFcpTemplate: function(length) {
- let tlvs = this.decodeChunks(length);
- return tlvs;
- },
-
- /**
- * Process the value part for proactive command TLV.
- *
- * @param length
- * The length of data in bytes.
- */
- processProactiveCommand: function(length) {
- let ctlvs = this.context.ComprehensionTlvHelper.decodeChunks(length);
- return ctlvs;
- },
-
- /**
- * Decode raw data to a Ber-TLV.
- */
- decodeInnerTlv: function() {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let tag = GsmPDUHelper.readHexOctet();
- let length = GsmPDUHelper.readHexOctet();
- return {
- tag: tag,
- length: length,
- value: this.retrieve(tag, length)
- };
- },
-
- decodeChunks: function(length) {
- let chunks = [];
- let index = 0;
- while (index < length) {
- let tlv = this.decodeInnerTlv();
- if (tlv.value) {
- chunks.push(tlv);
- }
- index += tlv.length;
- // tag + length fields consume 2 bytes.
- index += 2;
- }
- return chunks;
- },
-
- retrieve: function(tag, length) {
- let method = this[tag];
- if (typeof method != "function") {
- if (DEBUG) {
- this.context.debug("Unknown Ber tag : 0x" + tag.toString(16));
- }
- let Buf = this.context.Buf;
- Buf.seekIncoming(length * Buf.PDU_HEX_OCTET_SIZE);
- return null;
- }
- return method.call(this, length);
- },
-
- /**
- * File Size Data.
- *
- * | Byte | Description | Length |
- * | 1 | Tag | 1 |
- * | 2 | Length | 1 |
- * | 3 to X+24 | Number of allocated data bytes in the file | X |
- * | | , excluding structural information | |
- */
- retrieveFileSizeData: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let fileSizeData = 0;
- for (let i = 0; i < length; i++) {
- fileSizeData = fileSizeData << 8;
- fileSizeData += GsmPDUHelper.readHexOctet();
- }
-
- return {fileSizeData: fileSizeData};
- },
-
- /**
- * File Descriptor.
- *
- * | Byte | Description | Length |
- * | 1 | Tag | 1 |
- * | 2 | Length | 1 |
- * | 3 | File descriptor byte | 1 |
- * | 4 | Data coding byte | 1 |
- * | 5 ~ 6 | Record length | 2 |
- * | 7 | Number of records | 1 |
- */
- retrieveFileDescriptor: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let fileDescriptorByte = GsmPDUHelper.readHexOctet();
- let dataCodingByte = GsmPDUHelper.readHexOctet();
- // See TS 102 221 Table 11.5, we only care the least 3 bits for the
- // structure of file.
- let fileStructure = fileDescriptorByte & 0x07;
-
- let fileDescriptor = {
- fileStructure: fileStructure
- };
- // byte 5 ~ 7 are mandatory for linear fixed and cyclic files, otherwise
- // they are not applicable.
- if (fileStructure === UICC_EF_STRUCTURE[EF_STRUCTURE_LINEAR_FIXED] ||
- fileStructure === UICC_EF_STRUCTURE[EF_STRUCTURE_CYCLIC]) {
- fileDescriptor.recordLength = (GsmPDUHelper.readHexOctet() << 8) +
- GsmPDUHelper.readHexOctet();
- fileDescriptor.numOfRecords = GsmPDUHelper.readHexOctet();
- }
-
- return fileDescriptor;
- },
-
- /**
- * File identifier.
- *
- * | Byte | Description | Length |
- * | 1 | Tag | 1 |
- * | 2 | Length | 1 |
- * | 3 ~ 4 | File identifier | 2 |
- */
- retrieveFileIdentifier: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- return {fileId : (GsmPDUHelper.readHexOctet() << 8) +
- GsmPDUHelper.readHexOctet()};
- },
-
- searchForNextTag: function(tag, iter) {
- for (let tlv of iter) {
- if (tlv.tag === tag) {
- return tlv;
- }
- }
- return null;
- }
-};
-BerTlvHelperObject.prototype[BER_FCP_TEMPLATE_TAG] = function BER_FCP_TEMPLATE_TAG(length) {
- return this.processFcpTemplate(length);
-};
-BerTlvHelperObject.prototype[BER_PROACTIVE_COMMAND_TAG] = function BER_PROACTIVE_COMMAND_TAG(length) {
- return this.processProactiveCommand(length);
-};
-BerTlvHelperObject.prototype[BER_FCP_FILE_SIZE_DATA_TAG] = function BER_FCP_FILE_SIZE_DATA_TAG(length) {
- return this.retrieveFileSizeData(length);
-};
-BerTlvHelperObject.prototype[BER_FCP_FILE_DESCRIPTOR_TAG] = function BER_FCP_FILE_DESCRIPTOR_TAG(length) {
- return this.retrieveFileDescriptor(length);
-};
-BerTlvHelperObject.prototype[BER_FCP_FILE_IDENTIFIER_TAG] = function BER_FCP_FILE_IDENTIFIER_TAG(length) {
- return this.retrieveFileIdentifier(length);
-};
-
-/**
- * ICC Helper for getting EF path.
- */
-function ICCFileHelperObject(aContext) {
- this.context = aContext;
-}
-ICCFileHelperObject.prototype = {
- context: null,
-
- /**
- * This function handles only EFs that are common to RUIM, SIM, USIM
- * and other types of ICC cards.
- */
- getCommonEFPath: function(fileId) {
- switch (fileId) {
- case ICC_EF_ICCID:
- return EF_PATH_MF_SIM;
- case ICC_EF_ADN:
- case ICC_EF_SDN: // Fall through.
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
- case ICC_EF_PBR:
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
- case ICC_EF_IMG:
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_GRAPHICS;
- }
- return null;
- },
-
- /**
- * This function handles EFs for SIM.
- */
- getSimEFPath: function(fileId) {
- switch (fileId) {
- case ICC_EF_FDN:
- case ICC_EF_MSISDN:
- case ICC_EF_SMS:
- case ICC_EF_EXT1:
- case ICC_EF_EXT2:
- case ICC_EF_EXT3:
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
- case ICC_EF_AD:
- case ICC_EF_MBDN:
- case ICC_EF_MWIS:
- case ICC_EF_PLMNsel:
- case ICC_EF_SPN:
- case ICC_EF_SPDI:
- case ICC_EF_SST:
- case ICC_EF_PHASE:
- case ICC_EF_CBMI:
- case ICC_EF_CBMID:
- case ICC_EF_CBMIR:
- case ICC_EF_OPL:
- case ICC_EF_PNN:
- case ICC_EF_GID1:
- case ICC_EF_CPHS_INFO:
- case ICC_EF_CPHS_MBN:
- return EF_PATH_MF_SIM + EF_PATH_DF_GSM;
- default:
- return null;
- }
- },
-
- /**
- * This function handles EFs for USIM.
- */
- getUSimEFPath: function(fileId) {
- switch (fileId) {
- case ICC_EF_AD:
- case ICC_EF_FDN:
- case ICC_EF_MBDN:
- case ICC_EF_MWIS:
- case ICC_EF_UST:
- case ICC_EF_MSISDN:
- case ICC_EF_SPN:
- case ICC_EF_SPDI:
- case ICC_EF_CBMI:
- case ICC_EF_CBMID:
- case ICC_EF_CBMIR:
- case ICC_EF_OPL:
- case ICC_EF_PNN:
- case ICC_EF_SMS:
- case ICC_EF_GID1:
- // CPHS spec was provided in 1997 based on SIM requirement, there is no
- // detailed info about how these ICC_EF_CPHS_XXX are allocated in USIM.
- // What we can do now is to follow what has been done in AOSP to have file
- // path equal to MF_SIM/DF_GSM.
- case ICC_EF_CPHS_INFO:
- case ICC_EF_CPHS_MBN:
- return EF_PATH_MF_SIM + EF_PATH_ADF_USIM;
- default:
- // The file ids in USIM phone book entries are decided by the
- // card manufacturer. So if we don't match any of the cases
- // above and if its a USIM return the phone book path.
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
- }
- },
-
- /**
- * This function handles EFs for RUIM
- */
- getRuimEFPath: function(fileId) {
- switch(fileId) {
- case ICC_EF_CSIM_IMSI_M:
- case ICC_EF_CSIM_CDMAHOME:
- case ICC_EF_CSIM_CST:
- case ICC_EF_CSIM_SPN:
- return EF_PATH_MF_SIM + EF_PATH_DF_CDMA;
- case ICC_EF_FDN:
- case ICC_EF_EXT1:
- case ICC_EF_EXT2:
- case ICC_EF_EXT3:
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
- default:
- return null;
- }
- },
-
- /**
- * Helper function for getting the pathId for the specific ICC record
- * depeding on which type of ICC card we are using.
- *
- * @param fileId
- * File id.
- * @return The pathId or null in case of an error or invalid input.
- */
- getEFPath: function(fileId) {
- let path = this.getCommonEFPath(fileId);
- if (path) {
- return path;
- }
-
- switch (this.context.RIL.appType) {
- case CARD_APPTYPE_SIM:
- return this.getSimEFPath(fileId);
- case CARD_APPTYPE_USIM:
- return this.getUSimEFPath(fileId);
- case CARD_APPTYPE_RUIM:
- return this.getRuimEFPath(fileId);
- default:
- return null;
- }
- }
-};
-
-/**
- * Helper for ICC IO functionalities.
- */
-function ICCIOHelperObject(aContext) {
- this.context = aContext;
-}
-ICCIOHelperObject.prototype = {
- context: null,
-
- /**
- * Load EF with type 'Linear Fixed'.
- *
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- * @param recordNumber [optional]
- * The number of the record shall be loaded.
- * @param recordSize [optional]
- * The size of the record.
- * @param callback [optional]
- * The callback function shall be called when the record(s) is read.
- * @param onerror [optional]
- * The callback function shall be called when failure.
- */
- loadLinearFixedEF: function(options) {
- let cb;
- let readRecord = (function(options) {
- options.command = ICC_COMMAND_READ_RECORD;
- options.p1 = options.recordNumber || 1; // Record number
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = options.recordSize;
- options.callback = cb || options.callback;
- this.context.RIL.iccIO(options);
- }).bind(this);
-
- options.structure = EF_STRUCTURE_LINEAR_FIXED;
- options.pathId = this.context.ICCFileHelper.getEFPath(options.fileId);
- if (options.recordSize) {
- readRecord(options);
- return;
- }
-
- cb = options.callback;
- options.callback = readRecord;
- this.getResponse(options);
- },
-
- /**
- * Load next record from current record Id.
- */
- loadNextRecord: function(options) {
- options.p1++;
- this.context.RIL.iccIO(options);
- },
-
- /**
- * Update EF with type 'Linear Fixed'.
- *
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- * @param recordNumber
- * The number of the record shall be updated.
- * @param dataWriter [optional]
- * The function for writing string parameter for the ICC_COMMAND_UPDATE_RECORD.
- * @param pin2 [optional]
- * PIN2 is required when updating ICC_EF_FDN.
- * @param callback [optional]
- * The callback function shall be called when the record is updated.
- * @param onerror [optional]
- * The callback function shall be called when failure.
- */
- updateLinearFixedEF: function(options) {
- if (!options.fileId || !options.recordNumber) {
- throw new Error("Unexpected fileId " + options.fileId +
- " or recordNumber " + options.recordNumber);
- }
-
- options.structure = EF_STRUCTURE_LINEAR_FIXED;
- options.pathId = this.context.ICCFileHelper.getEFPath(options.fileId);
- let cb = options.callback;
- options.callback = function callback(options) {
- options.callback = cb;
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = options.recordSize;
- this.context.RIL.iccIO(options);
- }.bind(this);
- this.getResponse(options);
- },
-
- /**
- * Load EF with type 'Transparent'.
- *
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- * @param callback [optional]
- * The callback function shall be called when the record(s) is read.
- * @param onerror [optional]
- * The callback function shall be called when failure.
- */
- loadTransparentEF: function(options) {
- options.structure = EF_STRUCTURE_TRANSPARENT;
- let cb = options.callback;
- options.callback = function callback(options) {
- options.callback = cb;
- options.command = ICC_COMMAND_READ_BINARY;
- options.p2 = 0x00;
- options.p3 = options.fileSize;
- this.context.RIL.iccIO(options);
- }.bind(this);
- this.getResponse(options);
- },
-
- /**
- * Use ICC_COMMAND_GET_RESPONSE to query the EF.
- *
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- */
- getResponse: function(options) {
- options.command = ICC_COMMAND_GET_RESPONSE;
- options.pathId = options.pathId ||
- this.context.ICCFileHelper.getEFPath(options.fileId);
- if (!options.pathId) {
- throw new Error("Unknown pathId for " + options.fileId.toString(16));
- }
- options.p1 = 0; // For GET_RESPONSE, p1 = 0
- switch (this.context.RIL.appType) {
- case CARD_APPTYPE_USIM:
- options.p2 = GET_RESPONSE_FCP_TEMPLATE;
- options.p3 = 0x00;
- break;
- // For RUIM, CSIM and ISIM, cf bug 955946: keep the old behavior
- case CARD_APPTYPE_RUIM:
- case CARD_APPTYPE_CSIM:
- case CARD_APPTYPE_ISIM:
- // For SIM, this is what we want
- case CARD_APPTYPE_SIM:
- default:
- options.p2 = 0x00;
- options.p3 = GET_RESPONSE_EF_SIZE_BYTES;
- break;
- }
- this.context.RIL.iccIO(options);
- },
-
- /**
- * Process ICC I/O response.
- */
- processICCIO: function(options) {
- let func = this[options.command];
- func.call(this, options);
- },
-
- /**
- * Process a ICC_COMMAND_GET_RESPONSE type command for REQUEST_SIM_IO.
- */
- processICCIOGetResponse: function(options) {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
-
- let peek = this.context.GsmPDUHelper.readHexOctet();
- Buf.seekIncoming(-1 * Buf.PDU_HEX_OCTET_SIZE);
- if (peek === BER_FCP_TEMPLATE_TAG) {
- this.processUSimGetResponse(options, strLen / 2);
- } else {
- this.processSimGetResponse(options);
- }
- Buf.readStringDelimiter(strLen);
-
- if (options.callback) {
- options.callback(options);
- }
- },
-
- /**
- * Helper function for processing USIM get response.
- */
- processUSimGetResponse: function(options, octetLen) {
- let BerTlvHelper = this.context.BerTlvHelper;
-
- let berTlv = BerTlvHelper.decode(octetLen);
- // See TS 102 221 Table 11.4 for the content order of getResponse.
- let iter = berTlv.value.values();
- let tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG,
- iter);
- if (!tlv ||
- (tlv.value.fileStructure !== UICC_EF_STRUCTURE[options.structure])) {
- throw new Error("Expected EF structure " +
- UICC_EF_STRUCTURE[options.structure] +
- " but read " + tlv.value.fileStructure);
- }
-
- if (tlv.value.fileStructure === UICC_EF_STRUCTURE[EF_STRUCTURE_LINEAR_FIXED] ||
- tlv.value.fileStructure === UICC_EF_STRUCTURE[EF_STRUCTURE_CYCLIC]) {
- options.recordSize = tlv.value.recordLength;
- options.totalRecords = tlv.value.numOfRecords;
- }
-
- tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
- if (!tlv || (tlv.value.fileId !== options.fileId)) {
- throw new Error("Expected file ID " + options.fileId.toString(16) +
- " but read " + fileId.toString(16));
- }
-
- tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
- if (!tlv) {
- throw new Error("Unexpected file size data");
- }
- options.fileSize = tlv.value.fileSizeData;
- },
-
- /**
- * Helper function for processing SIM get response.
- */
- processSimGetResponse: function(options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // The format is from TS 51.011, clause 9.2.1
-
- // Skip RFU, data[0] data[1].
- Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
-
- // File size, data[2], data[3]
- options.fileSize = (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet();
-
- // 2 bytes File id. data[4], data[5]
- let fileId = (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet();
- if (fileId != options.fileId) {
- throw new Error("Expected file ID " + options.fileId.toString(16) +
- " but read " + fileId.toString(16));
- }
-
- // Type of file, data[6]
- let fileType = GsmPDUHelper.readHexOctet();
- if (fileType != TYPE_EF) {
- throw new Error("Unexpected file type " + fileType);
- }
-
- // Skip 1 byte RFU, data[7],
- // 3 bytes Access conditions, data[8] data[9] data[10],
- // 1 byte File status, data[11],
- // 1 byte Length of the following data, data[12].
- Buf.seekIncoming(((RESPONSE_DATA_STRUCTURE - RESPONSE_DATA_FILE_TYPE - 1) *
- Buf.PDU_HEX_OCTET_SIZE));
-
- // Read Structure of EF, data[13]
- let efStructure = GsmPDUHelper.readHexOctet();
- if (efStructure != options.structure) {
- throw new Error("Expected EF structure " + options.structure +
- " but read " + efStructure);
- }
-
- // Length of a record, data[14].
- // Only available for LINEAR_FIXED and CYCLIC.
- if (efStructure == EF_STRUCTURE_LINEAR_FIXED ||
- efStructure == EF_STRUCTURE_CYCLIC) {
- options.recordSize = GsmPDUHelper.readHexOctet();
- options.totalRecords = options.fileSize / options.recordSize;
- } else {
- Buf.seekIncoming(1 * Buf.PDU_HEX_OCTET_SIZE);
- }
- },
-
- /**
- * Process a ICC_COMMAND_READ_RECORD type command for REQUEST_SIM_IO.
- */
- processICCIOReadRecord: function(options) {
- if (options.callback) {
- options.callback(options);
- }
- },
-
- /**
- * Process a ICC_COMMAND_READ_BINARY type command for REQUEST_SIM_IO.
- */
- processICCIOReadBinary: function(options) {
- if (options.callback) {
- options.callback(options);
- }
- },
-
- /**
- * Process a ICC_COMMAND_UPDATE_RECORD type command for REQUEST_SIM_IO.
- */
- processICCIOUpdateRecord: function(options) {
- if (options.callback) {
- options.callback(options);
- }
- },
-};
-ICCIOHelperObject.prototype[ICC_COMMAND_SEEK] = null;
-ICCIOHelperObject.prototype[ICC_COMMAND_READ_BINARY] = function ICC_COMMAND_READ_BINARY(options) {
- this.processICCIOReadBinary(options);
-};
-ICCIOHelperObject.prototype[ICC_COMMAND_READ_RECORD] = function ICC_COMMAND_READ_RECORD(options) {
- this.processICCIOReadRecord(options);
-};
-ICCIOHelperObject.prototype[ICC_COMMAND_GET_RESPONSE] = function ICC_COMMAND_GET_RESPONSE(options) {
- this.processICCIOGetResponse(options);
-};
-ICCIOHelperObject.prototype[ICC_COMMAND_UPDATE_BINARY] = null;
-ICCIOHelperObject.prototype[ICC_COMMAND_UPDATE_RECORD] = function ICC_COMMAND_UPDATE_RECORD(options) {
- this.processICCIOUpdateRecord(options);
-};
-
-/**
- * Helper for ICC records.
- */
-function ICCRecordHelperObject(aContext) {
- this.context = aContext;
- // Cache the possible free record id for all files, use fileId as key.
- this._freeRecordIds = {};
-}
-ICCRecordHelperObject.prototype = {
- context: null,
-
- /**
- * Fetch ICC records.
- */
- fetchICCRecords: function() {
- switch (this.context.RIL.appType) {
- case CARD_APPTYPE_SIM:
- case CARD_APPTYPE_USIM:
- this.context.SimRecordHelper.fetchSimRecords();
- break;
- case CARD_APPTYPE_RUIM:
- this.context.RuimRecordHelper.fetchRuimRecords();
- break;
- }
- },
-
- /**
- * Read the ICCID.
- */
- readICCID: function() {
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- RIL.iccInfo.iccid =
- GsmPDUHelper.readSwappedNibbleBcdString(octetLen, true);
- // Consumes the remaining buffer if any.
- let unReadBuffer = this.context.Buf.getReadAvailable() -
- this.context.Buf.PDU_HEX_OCTET_SIZE;
- if (unReadBuffer > 0) {
- this.context.Buf.seekIncoming(unReadBuffer);
- }
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) this.context.debug("ICCID: " + RIL.iccInfo.iccid);
- if (RIL.iccInfo.iccid) {
- this.context.ICCUtilsHelper.handleICCInfoChange();
- RIL.reportStkServiceIsRunning();
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_ICCID,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read ICC ADN like EF, i.e. EF_ADN, EF_FDN.
- *
- * @param fileId EF id of the ADN, FDN or SDN.
- * @param extFileId EF id of the EXT.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readADNLike: function(fileId, extFileId, onsuccess, onerror) {
- let ICCIOHelper = this.context.ICCIOHelper;
-
- function callback(options) {
- let loadNextContactRecord = () => {
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- return;
- }
- if (DEBUG) {
- for (let i = 0; i < contacts.length; i++) {
- this.context.debug("contact [" + i + "] " +
- JSON.stringify(contacts[i]));
- }
- }
- if (onsuccess) {
- onsuccess(contacts);
- }
- };
-
- let contact =
- this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
- if (contact) {
- let record = {
- recordId: options.p1,
- alphaId: contact.alphaId,
- number: contact.number
- };
- contacts.push(record);
-
- if (extFileId && contact.extRecordNumber != 0xff) {
- this.readExtension(extFileId, contact.extRecordNumber, (number) => {
- if (number) {
- record.number += number;
- }
- loadNextContactRecord();
- }, () => loadNextContactRecord());
- return;
- }
- }
- loadNextContactRecord();
- }
-
- let contacts = [];
- ICCIOHelper.loadLinearFixedEF({fileId: fileId,
- callback: callback.bind(this),
- onerror: onerror});
- },
-
- /**
- * Update ICC ADN like EFs, like EF_ADN, EF_FDN.
- *
- * @param fileId EF id of the ADN or FDN.
- * @param extRecordNumber The record identifier of the EXT.
- * @param contact The contact will be updated. (Shall have recordId property)
- * @param pin2 PIN2 is required when updating ICC_EF_FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateADNLike: function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- let updatedContact;
- function dataWriter(recordSize) {
- updatedContact = this.context.ICCPDUHelper.writeAlphaIdDiallingNumber(recordSize,
- contact.alphaId,
- contact.number,
- extRecordNumber);
- }
-
- function callback(options) {
- if (onsuccess) {
- onsuccess(updatedContact);
- }
- }
-
- if (!contact || !contact.recordId) {
- if (onerror) onerror(GECKO_ERROR_INVALID_PARAMETER);
- return;
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: contact.recordId,
- dataWriter: dataWriter.bind(this),
- pin2: pin2,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Read USIM/RUIM Phonebook.
- *
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readPBR: function(onsuccess, onerror) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let ICCIOHelper = this.context.ICCIOHelper;
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- let RIL = this.context.RIL;
-
- function callback(options) {
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2, readLen = 0;
-
- let pbrTlvs = [];
- while (readLen < octetLen) {
- let tag = GsmPDUHelper.readHexOctet();
- if (tag == 0xff) {
- readLen++;
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- break;
- }
-
- let tlvLen = GsmPDUHelper.readHexOctet();
- let tlvs = ICCUtilsHelper.decodeSimTlvs(tlvLen);
- pbrTlvs.push({tag: tag,
- length: tlvLen,
- value: tlvs});
-
- readLen += tlvLen + 2; // +2 for tag and tlvLen
- }
- Buf.readStringDelimiter(strLen);
-
- if (pbrTlvs.length > 0) {
- let pbr = ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
- // EF_ADN is mandatory if and only if DF_PHONEBOOK is present.
- if (!pbr.adn) {
- if (onerror) onerror("Cannot access ADN.");
- return;
- }
- pbrs.push(pbr);
- }
-
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- } else {
- if (onsuccess) {
- RIL.iccInfoPrivate.pbrs = pbrs;
- onsuccess(pbrs);
- }
- }
- }
-
- if (RIL.iccInfoPrivate.pbrs) {
- onsuccess(RIL.iccInfoPrivate.pbrs);
- return;
- }
-
- let pbrs = [];
- ICCIOHelper.loadLinearFixedEF({fileId : ICC_EF_PBR,
- callback: callback.bind(this),
- onerror: onerror});
- },
-
- /**
- * Cache EF_IAP record size.
- */
- _iapRecordSize: null,
-
- /**
- * Read ICC EF_IAP. (Index Administration Phonebook)
- *
- * @see TS 131.102, clause 4.4.2.2
- *
- * @param fileId EF id of the IAP.
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readIAP: function(fileId, recordNumber, onsuccess, onerror) {
- function callback(options) {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- this._iapRecordSize = options.recordSize;
-
- let iap = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
-
- if (onsuccess) {
- onsuccess(iap);
- }
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- recordSize: this._iapRecordSize,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Update USIM/RUIM Phonebook EF_IAP.
- *
- * @see TS 131.102, clause 4.4.2.13
- *
- * @param fileId EF id of the IAP.
- * @param recordNumber The identifier of the record shall be updated.
- * @param iap The IAP value to be written.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateIAP: function(fileId, recordNumber, iap, onsuccess, onerror) {
- let dataWriter = function dataWriter(recordSize) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // Write String length
- let strLen = recordSize * 2;
- Buf.writeInt32(strLen);
-
- for (let i = 0; i < iap.length; i++) {
- GsmPDUHelper.writeHexOctet(iap[i]);
- }
-
- Buf.writeStringDelimiter(strLen);
- }.bind(this);
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: onsuccess,
- onerror: onerror
- });
- },
-
- /**
- * Cache EF_Email record size.
- */
- _emailRecordSize: null,
-
- /**
- * Read USIM/RUIM Phonebook EF_EMAIL.
- *
- * @see TS 131.102, clause 4.4.2.13
- *
- * @param fileId EF id of the EMAIL.
- * @param fileType The type of the EMAIL, one of the ICC_USIM_TYPE* constants.
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readEmail: function(fileId, fileType, recordNumber, onsuccess, onerror) {
- function callback(options) {
- let Buf = this.context.Buf;
- let ICCPDUHelper = this.context.ICCPDUHelper;
-
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- let email = null;
- this._emailRecordSize = options.recordSize;
-
- // Read contact's email
- //
- // | Byte | Description | Length | M/O
- // | 1 ~ X | E-mail Address | X | M
- // | X+1 | ADN file SFI | 1 | C
- // | X+2 | ADN file Record Identifier | 1 | C
- // Note: The fields marked as C above are mandatort if the file
- // is not type 1 (as specified in EF_PBR)
- if (fileType == ICC_USIM_TYPE1_TAG) {
- email = ICCPDUHelper.read8BitUnpackedToString(octetLen);
- } else {
- email = ICCPDUHelper.read8BitUnpackedToString(octetLen - 2);
-
- // Consumes the remaining buffer
- Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE); // For ADN SFI and Record Identifier
- }
-
- Buf.readStringDelimiter(strLen);
-
- if (onsuccess) {
- onsuccess(email);
- }
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- recordSize: this._emailRecordSize,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Update USIM/RUIM Phonebook EF_EMAIL.
- *
- * @see TS 131.102, clause 4.4.2.13
- *
- * @param pbr Phonebook Reference File.
- * @param recordNumber The identifier of the record shall be updated.
- * @param email The value to be written.
- * @param adnRecordId The record Id of ADN, only needed if the fileType of Email is TYPE2.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateEmail: function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
- let fileId = pbr[USIM_PBR_EMAIL].fileId;
- let fileType = pbr[USIM_PBR_EMAIL].fileType;
- let writtenEmail;
- let dataWriter = function dataWriter(recordSize) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let ICCPDUHelper = this.context.ICCPDUHelper;
-
- // Write String length
- let strLen = recordSize * 2;
- Buf.writeInt32(strLen);
-
- if (fileType == ICC_USIM_TYPE1_TAG) {
- writtenEmail = ICCPDUHelper.writeStringTo8BitUnpacked(recordSize, email);
- } else {
- writtenEmail = ICCPDUHelper.writeStringTo8BitUnpacked(recordSize - 2, email);
- GsmPDUHelper.writeHexOctet(pbr.adn.sfi || 0xff);
- GsmPDUHelper.writeHexOctet(adnRecordId);
- }
-
- Buf.writeStringDelimiter(strLen);
- }.bind(this);
-
- let callback = (options) => {
- if (onsuccess) {
- onsuccess(writtenEmail);
- }
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: callback,
- onerror: onerror
- });
- },
-
- /**
- * Cache EF_ANR record size.
- */
- _anrRecordSize: null,
-
- /**
- * Read USIM/RUIM Phonebook EF_ANR.
- *
- * @see TS 131.102, clause 4.4.2.9
- *
- * @param fileId EF id of the ANR.
- * @param fileType One of the ICC_USIM_TYPE* constants.
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readANR: function(fileId, fileType, recordNumber, onsuccess, onerror) {
- function callback(options) {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let number = null;
- this._anrRecordSize = options.recordSize;
-
- // Skip EF_AAS Record ID.
- Buf.seekIncoming(1 * Buf.PDU_HEX_OCTET_SIZE);
-
- number = this.context.ICCPDUHelper.readNumberWithLength();
-
- // Skip 2 unused octets, CCP and EXT1.
- Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
-
- // For Type 2 there are two extra octets.
- if (fileType == ICC_USIM_TYPE2_TAG) {
- // Skip 2 unused octets, ADN SFI and Record Identifier.
- Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
- }
-
- Buf.readStringDelimiter(strLen);
-
- if (onsuccess) {
- onsuccess(number);
- }
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- recordSize: this._anrRecordSize,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Update USIM/RUIM Phonebook EF_ANR.
- *
- * @see TS 131.102, clause 4.4.2.9
- *
- * @param pbr Phonebook Reference File.
- * @param recordNumber The identifier of the record shall be updated.
- * @param number The value to be written.
- * @param adnRecordId The record Id of ADN, only needed if the fileType of Email is TYPE2.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateANR: function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
- let fileId = pbr[USIM_PBR_ANR0].fileId;
- let fileType = pbr[USIM_PBR_ANR0].fileType;
- let writtenNumber;
- let dataWriter = function dataWriter(recordSize) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // Write String length
- let strLen = recordSize * 2;
- Buf.writeInt32(strLen);
-
- // EF_AAS record Id. Unused for now.
- GsmPDUHelper.writeHexOctet(0xff);
-
- writtenNumber = this.context.ICCPDUHelper.writeNumberWithLength(number);
-
- // Write unused octets 0xff, CCP and EXT1.
- GsmPDUHelper.writeHexOctet(0xff);
- GsmPDUHelper.writeHexOctet(0xff);
-
- // For Type 2 there are two extra octets.
- if (fileType == ICC_USIM_TYPE2_TAG) {
- GsmPDUHelper.writeHexOctet(pbr.adn.sfi || 0xff);
- GsmPDUHelper.writeHexOctet(adnRecordId);
- }
-
- Buf.writeStringDelimiter(strLen);
- }.bind(this);
-
- let callback = (options) => {
- if (onsuccess) {
- onsuccess(writtenNumber);
- }
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: callback,
- onerror: onerror
- });
- },
-
- /**
- * Cache the possible free record id for all files.
- */
- _freeRecordIds: null,
-
- /**
- * Find free record id.
- *
- * @param fileId EF id.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- findFreeRecordId: function(fileId, onsuccess, onerror) {
- let ICCIOHelper = this.context.ICCIOHelper;
-
- function callback(options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- let readLen = 0;
-
- while (readLen < octetLen) {
- let octet = GsmPDUHelper.readHexOctet();
- readLen++;
- if (octet != 0xff) {
- break;
- }
- }
-
- let nextRecord = (options.p1 % options.totalRecords) + 1;
-
- if (readLen == octetLen) {
- // Find free record, assume next record is probably free.
- this._freeRecordIds[fileId] = nextRecord;
- if (onsuccess) {
- onsuccess(options.p1);
- }
- return;
- } else {
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- }
-
- Buf.readStringDelimiter(strLen);
-
- if (nextRecord !== recordNumber) {
- options.p1 = nextRecord;
- this.context.RIL.iccIO(options);
- } else {
- // No free record found.
- delete this._freeRecordIds[fileId];
- if (DEBUG) {
- this.context.debug(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- }
- onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- }
- }
-
- // Start searching free records from the possible one.
- let recordNumber = this._freeRecordIds[fileId] || 1;
- ICCIOHelper.loadLinearFixedEF({fileId: fileId,
- recordNumber: recordNumber,
- callback: callback.bind(this),
- onerror: onerror});
- },
-
- /**
- * Read Extension Number from TS 151.011 clause 10.5.10, TS 31.102, clause 4.4.2.4
- *
- * @param fileId EF Extension id
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readExtension: function(fileId, recordNumber, onsuccess, onerror) {
- let callback = (options) => {
- let Buf = this.context.Buf;
- let length = Buf.readInt32();
- let recordType = this.context.GsmPDUHelper.readHexOctet();
- let number = "";
-
- // TS 31.102, clause 4.4.2.4 EFEXT1
- // Case 1, Extension1 record is additional data
- if (recordType & 0x02) {
- let numLen = this.context.GsmPDUHelper.readHexOctet();
- if (numLen != 0xff) {
- if (numLen > EXT_MAX_BCD_NUMBER_BYTES) {
- if (DEBUG) {
- this.context.debug(
- "Error: invalid length of BCD number/SSC contents - " + numLen);
- }
- // +1 to skip Identifier
- Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES + 1) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(length);
- onerror();
- return;
- }
-
- number = this.context.GsmPDUHelper.readSwappedNibbleExtendedBcdString(numLen);
- if (DEBUG) this.context.debug("Contact Extension Number: "+ number);
- Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES - numLen) * Buf.PDU_HEX_OCTET_SIZE);
- } else {
- Buf.seekIncoming(EXT_MAX_BCD_NUMBER_BYTES * Buf.PDU_HEX_OCTET_SIZE);
- }
- } else {
- // Don't support Case 2, Extension1 record is Called Party Subaddress.
- // +1 skip numLen
- Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES + 1) * Buf.PDU_HEX_OCTET_SIZE);
- }
-
- // Skip Identifier
- Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(length);
- onsuccess(number);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- callback: callback,
- onerror: onerror
- });
- },
-
- /**
- * Update Extension.
- *
- * @param fileId EF id of the EXT.
- * @param recordNumber The number of the record shall be updated.
- * @param number Dialling Number to be written.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateExtension: function(fileId, recordNumber, number, onsuccess, onerror) {
- let dataWriter = (recordSize) => {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- // Write String length
- let strLen = recordSize * 2;
- let Buf = this.context.Buf;
- Buf.writeInt32(strLen);
-
- // We don't support extension chain.
- if (number.length > EXT_MAX_NUMBER_DIGITS) {
- number = number.substring(0, EXT_MAX_NUMBER_DIGITS);
- }
-
- let numLen = Math.ceil(number.length / 2);
- // Write Extension record
- GsmPDUHelper.writeHexOctet(0x02);
- GsmPDUHelper.writeHexOctet(numLen);
- GsmPDUHelper.writeSwappedNibbleBCD(number);
- // Write trailing 0xff of Extension data.
- for (let i = 0; i < EXT_MAX_BCD_NUMBER_BYTES - numLen; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- // Write trailing 0xff for Identifier.
- GsmPDUHelper.writeHexOctet(0xff);
- Buf.writeStringDelimiter(strLen);
- };
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: onsuccess,
- onerror: onerror
- });
- },
-
- /**
- * Clean an EF record.
- *
- * @param fileId EF id.
- * @param recordNumber The number of the record shall be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- cleanEFRecord: function(fileId, recordNumber, onsuccess, onerror) {
- let dataWriter = (recordSize) => {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let Buf = this.context.Buf;
- // Write String length
- let strLen = recordSize * 2;
-
- Buf.writeInt32(strLen);
- // Write record to 0xff
- for (let i = 0; i < recordSize; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- Buf.writeStringDelimiter(strLen);
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: onsuccess,
- onerror: onerror
- });
- },
-
- /**
- * Get ADNLike extension record number.
- *
- * @param fileId EF id of the ADN or FDN.
- * @param recordNumber EF record id of the ADN or FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- getADNLikeExtensionRecordNumber: function(fileId, recordNumber, onsuccess, onerror) {
- let callback = (options) => {
- let Buf = this.context.Buf;
- let length = Buf.readInt32();
-
- // Skip alphaLen, numLen, BCD Number, CCP octets.
- Buf.seekIncoming((options.recordSize -1) * Buf.PDU_HEX_OCTET_SIZE);
-
- let extRecordNumber = this.context.GsmPDUHelper.readHexOctet();
- Buf.readStringDelimiter(length);
-
- onsuccess(extRecordNumber);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- callback: callback,
- onerror: onerror
- });
- },
-};
-
-/**
- * Helper for (U)SIM Records.
- */
-function SimRecordHelperObject(aContext) {
- this.context = aContext;
-}
-SimRecordHelperObject.prototype = {
- context: null,
-
- /**
- * Fetch (U)SIM records.
- */
- fetchSimRecords: function() {
- this.context.RIL.getIMSI();
- this.readAD();
- // CPHS was widely introduced in Europe during GSM(2G) era to provide easier
- // access to carrier's core service like voicemail, call forwarding, manual
- // PLMN selection, and etc.
- // Addition EF like EF_CPHS_MBN, EF_CPHS_CPHS_CFF, EF_CPHS_VWI, etc are
- // introduced to support these feature.
- // In USIM, the replancement of these EFs are provided. (EF_MBDN, EF_MWIS, ...)
- // However, some carriers in Europe still rely on these EFs.
- this.readCphsInfo(() => this.readSST(),
- (aErrorMsg) => {
- this.context.debug("Failed to read CPHS_INFO: " + aErrorMsg);
- this.readSST();
- });
- },
-
- /**
- * Read EF_phase.
- * This EF is only available in SIM.
- */
- readSimPhase: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let phase = GsmPDUHelper.readHexOctet();
- // If EF_phase is coded '03' or greater, an ME supporting STK shall
- // perform the PROFILE DOWNLOAD procedure.
- if (RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD &&
- phase >= ICC_PHASE_2_PROFILE_DOWNLOAD_REQUIRED) {
- this.context.RIL.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
- }
-
- Buf.readStringDelimiter(strLen);
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_PHASE,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read the MSISDN from the (U)SIM.
- */
- readMSISDN: function() {
- function callback(options) {
- let RIL = this.context.RIL;
-
- let contact =
- this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
- if (!contact ||
- (RIL.iccInfo.msisdn !== undefined &&
- RIL.iccInfo.msisdn === contact.number)) {
- return;
- }
- RIL.iccInfo.msisdn = contact.number;
- if (DEBUG) this.context.debug("MSISDN: " + RIL.iccInfo.msisdn);
- this.context.ICCUtilsHelper.handleICCInfoChange();
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_MSISDN,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read the AD (Administrative Data) from the (U)SIM.
- */
- readAD: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let ad = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) {
- let str = "";
- for (let i = 0; i < ad.length; i++) {
- str += ad[i] + ", ";
- }
- this.context.debug("AD: " + str);
- }
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- let RIL = this.context.RIL;
- // TS 31.102, clause 4.2.18 EFAD
- let mncLength = 0;
- if (ad && ad[3]) {
- mncLength = ad[3] & 0x0f;
- if (mncLength != 0x02 && mncLength != 0x03) {
- mncLength = 0;
- }
- }
- // The 4th byte of the response is the length of MNC.
- let mccMnc = ICCUtilsHelper.parseMccMncFromImsi(RIL.iccInfoPrivate.imsi,
- mncLength);
- if (mccMnc) {
- RIL.iccInfo.mcc = mccMnc.mcc;
- RIL.iccInfo.mnc = mccMnc.mnc;
- ICCUtilsHelper.handleICCInfoChange();
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_AD,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read the SPN (Service Provider Name) from the (U)SIM.
- */
- readSPN: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let spnDisplayCondition = this.context.GsmPDUHelper.readHexOctet();
- // Minus 1 because the first octet is used to store display condition.
- let spn = this.context.ICCPDUHelper.readAlphaIdentifier(octetLen - 1);
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) {
- this.context.debug("SPN: spn = " + spn +
- ", spnDisplayCondition = " + spnDisplayCondition);
- }
-
- let RIL = this.context.RIL;
- RIL.iccInfoPrivate.spnDisplayCondition = spnDisplayCondition;
- RIL.iccInfo.spn = spn;
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- ICCUtilsHelper.updateDisplayCondition();
- ICCUtilsHelper.handleICCInfoChange();
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_SPN,
- callback: callback.bind(this)
- });
- },
-
- readIMG: function(recordNumber, onsuccess, onerror) {
- function callback(options) {
- let RIL = this.context.RIL;
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
-
- let numInstances = GsmPDUHelper.readHexOctet();
-
- // Data length is defined as 9n+1 or 9n+2. See TS 31.102, sub-clause
- // 4.6.1.1. However, it's likely to have padding appended so we have a
- // rather loose check.
- if (octetLen < (9 * numInstances + 1)) {
- Buf.seekIncoming((octetLen - 1) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
- if (onerror) {
- onerror();
- }
- return;
- }
-
- let imgDescriptors = [];
- for (let i = 0; i < numInstances; i++) {
- imgDescriptors[i] = {
- width: GsmPDUHelper.readHexOctet(),
- height: GsmPDUHelper.readHexOctet(),
- codingScheme: GsmPDUHelper.readHexOctet(),
- fileId: (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet(),
- offset: (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet(),
- dataLen: (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet()
- };
- }
- Buf.seekIncoming((octetLen - 9 * numInstances - 1) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
-
- let instances = [];
- let currentInstance = 0;
- let readNextInstance = (function(img) {
- instances[currentInstance] = img;
- currentInstance++;
-
- if (currentInstance < numInstances) {
- let imgDescriptor = imgDescriptors[currentInstance];
- this.readIIDF(imgDescriptor.fileId,
- imgDescriptor.offset,
- imgDescriptor.dataLen,
- imgDescriptor.codingScheme,
- readNextInstance,
- onerror);
- } else {
- if (onsuccess) {
- onsuccess(instances);
- }
- }
- }).bind(this);
-
- this.readIIDF(imgDescriptors[0].fileId,
- imgDescriptors[0].offset,
- imgDescriptors[0].dataLen,
- imgDescriptors[0].codingScheme,
- readNextInstance,
- onerror);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_IMG,
- recordNumber: recordNumber,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- readIIDF: function(fileId, offset, dataLen, codingScheme, onsuccess, onerror) {
- // Valid fileId is '4FXX', see TS 31.102, clause 4.6.1.2.
- if ((fileId >> 8) != 0x4F) {
- if (onerror) {
- onerror();
- }
- return;
- }
-
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
-
- if (octetLen < offset + dataLen) {
- // Data length is not enough. See TS 31.102, clause 4.6.1.1, the
- // paragraph "Bytes 8 and 9: Length of Image Instance Data."
- Buf.seekIncoming(octetLen * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
- if (onerror) {
- onerror();
- }
- return;
- }
-
- Buf.seekIncoming(offset * Buf.PDU_HEX_OCTET_SIZE);
-
- let rawData = {
- width: GsmPDUHelper.readHexOctet(),
- height: GsmPDUHelper.readHexOctet(),
- codingScheme: codingScheme
- };
-
- switch (codingScheme) {
- case ICC_IMG_CODING_SCHEME_BASIC:
- rawData.body = GsmPDUHelper.readHexOctetArray(
- dataLen - ICC_IMG_HEADER_SIZE_BASIC);
- Buf.seekIncoming((octetLen - offset - dataLen) * Buf.PDU_HEX_OCTET_SIZE);
- break;
-
- case ICC_IMG_CODING_SCHEME_COLOR:
- case ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY:
- rawData.bitsPerImgPoint = GsmPDUHelper.readHexOctet();
- let num = GsmPDUHelper.readHexOctet();
- // The value 0 shall be interpreted as 256. See TS 31.102, Annex B.2.
- rawData.numOfClutEntries = (num === 0) ? 0x100 : num;
- rawData.clutOffset = (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet();
- rawData.body = GsmPDUHelper.readHexOctetArray(
- dataLen - ICC_IMG_HEADER_SIZE_COLOR);
-
- Buf.seekIncoming((rawData.clutOffset - offset - dataLen) *
- Buf.PDU_HEX_OCTET_SIZE);
- let clut = GsmPDUHelper.readHexOctetArray(rawData.numOfClutEntries *
- ICC_CLUT_ENTRY_SIZE);
-
- rawData.clut = clut;
- }
-
- Buf.readStringDelimiter(strLen);
-
- if (onsuccess) {
- onsuccess(rawData);
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: fileId,
- pathId: this.context.ICCFileHelper.getEFPath(ICC_EF_IMG),
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Read the (U)SIM Service Table from the (U)SIM.
- */
- readSST: function() {
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let sst = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
- RIL.iccInfoPrivate.sst = sst;
- if (DEBUG) {
- let str = "";
- for (let i = 0; i < sst.length; i++) {
- str += sst[i] + ", ";
- }
- this.context.debug("SST: " + str);
- }
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- if (ICCUtilsHelper.isICCServiceAvailable("MSISDN")) {
- if (DEBUG) this.context.debug("MSISDN: MSISDN is available");
- this.readMSISDN();
- } else {
- if (DEBUG) this.context.debug("MSISDN: MSISDN service is not available");
- }
-
- // Fetch SPN and PLMN list, if some of them are available.
- if (ICCUtilsHelper.isICCServiceAvailable("SPN")) {
- if (DEBUG) this.context.debug("SPN: SPN is available");
- this.readSPN();
- } else {
- if (DEBUG) this.context.debug("SPN: SPN service is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("MDN")) {
- if (DEBUG) this.context.debug("MDN: MDN available.");
- this.readMBDN();
- } else {
- if (DEBUG) this.context.debug("MDN: MDN service is not available");
-
- if (ICCUtilsHelper.isCphsServiceAvailable("MBN")) {
- // read CPHS_MBN in advance if MBDN is not available.
- this.readCphsMBN();
- } else {
- if (DEBUG) this.context.debug("CPHS_MBN: CPHS_MBN service is not available");
- }
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("MWIS")) {
- if (DEBUG) this.context.debug("MWIS: MWIS is available");
- this.readMWIS();
- } else {
- if (DEBUG) this.context.debug("MWIS: MWIS is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("SPDI")) {
- if (DEBUG) this.context.debug("SPDI: SPDI available.");
- this.readSPDI();
- } else {
- if (DEBUG) this.context.debug("SPDI: SPDI service is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("PNN")) {
- if (DEBUG) this.context.debug("PNN: PNN is available");
- this.readPNN();
- } else {
- if (DEBUG) this.context.debug("PNN: PNN is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("OPL")) {
- if (DEBUG) this.context.debug("OPL: OPL is available");
- this.readOPL();
- } else {
- if (DEBUG) this.context.debug("OPL: OPL is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("GID1")) {
- if (DEBUG) this.context.debug("GID1: GID1 is available");
- this.readGID1();
- } else {
- if (DEBUG) this.context.debug("GID1: GID1 is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("CBMI")) {
- this.readCBMI();
- } else {
- RIL.cellBroadcastConfigs.CBMI = null;
- }
- if (ICCUtilsHelper.isICCServiceAvailable("DATA_DOWNLOAD_SMS_CB")) {
- this.readCBMID();
- } else {
- RIL.cellBroadcastConfigs.CBMID = null;
- }
- if (ICCUtilsHelper.isICCServiceAvailable("CBMIR")) {
- this.readCBMIR();
- } else {
- RIL.cellBroadcastConfigs.CBMIR = null;
- }
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- // ICC_EF_UST has the same value with ICC_EF_SST.
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_SST,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read (U)SIM MBDN. (Mailbox Dialling Number)
- *
- * @see TS 131.102, clause 4.2.60
- */
- readMBDN: function() {
- function callback(options) {
- let RIL = this.context.RIL;
- let contact =
- this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
- if ((!contact ||
- ((!contact.alphaId || contact.alphaId == "") &&
- (!contact.number || contact.number == ""))) &&
- this.context.ICCUtilsHelper.isCphsServiceAvailable("MBN")) {
- // read CPHS_MBN in advance if MBDN is invalid or empty.
- this.readCphsMBN();
- return;
- }
-
- if (!contact ||
- (RIL.iccInfoPrivate.mbdn !== undefined &&
- RIL.iccInfoPrivate.mbdn === contact.number)) {
- return;
- }
- RIL.iccInfoPrivate.mbdn = contact.number;
- if (DEBUG) {
- this.context.debug("MBDN, alphaId=" + contact.alphaId +
- " number=" + contact.number);
- }
- contact.rilMessageType = "iccmbdn";
- RIL.sendChromeMessage(contact);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_MBDN,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read ICC MWIS. (Message Waiting Indication Status)
- *
- * @see TS 31.102, clause 4.2.63 for USIM and TS 51.011, clause 10.3.45 for SIM.
- */
- readMWIS: function() {
- function callback(options) {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let mwis = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
- if (!mwis) {
- return;
- }
- RIL.iccInfoPrivate.mwis = mwis; //Keep raw MWIS for updateMWIS()
-
- let mwi = {};
- // b8 b7 B6 b5 b4 b3 b2 b1 4.2.63, TS 31.102 version 11.6.0
- // | | | | | | | |__ Voicemail
- // | | | | | | |_____ Fax
- // | | | | | |________ Electronic Mail
- // | | | | |___________ Other
- // | | | |______________ Videomail
- // |__|__|_________________ RFU
- mwi.active = ((mwis[0] & 0x01) != 0);
-
- if (mwi.active) {
- // In TS 23.040 msgCount is in the range from 0 to 255.
- // The value 255 shall be taken to mean 255 or greater.
- //
- // However, There is no definition about 0 when MWI is active.
- //
- // Normally, when mwi is active, the msgCount must be larger than 0.
- // Refer to other reference phone,
- // 0 is usually treated as UNKNOWN for storing 2nd level MWI status (DCS).
- mwi.msgCount = (mwis[1] === 0) ? GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN
- : mwis[1];
- } else {
- mwi.msgCount = 0;
- }
-
- RIL.sendChromeMessage({ rilMessageType: "iccmwis",
- mwi: mwi });
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_MWIS,
- recordNumber: 1, // Get 1st Subscriber Profile.
- callback: callback.bind(this)
- });
- },
-
- /**
- * Update ICC MWIS. (Message Waiting Indication Status)
- *
- * @see TS 31.102, clause 4.2.63 for USIM and TS 51.011, clause 10.3.45 for SIM.
- */
- updateMWIS: function(mwi) {
- let RIL = this.context.RIL;
- if (!RIL.iccInfoPrivate.mwis) {
- return;
- }
-
- function dataWriter(recordSize) {
- let mwis = RIL.iccInfoPrivate.mwis;
-
- let msgCount =
- (mwi.msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : mwi.msgCount;
-
- [mwis[0], mwis[1]] = (mwi.active) ? [(mwis[0] | 0x01), msgCount]
- : [(mwis[0] & 0xFE), 0];
-
- let strLen = recordSize * 2;
- let Buf = this.context.Buf;
- Buf.writeInt32(strLen);
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- for (let i = 0; i < mwis.length; i++) {
- GsmPDUHelper.writeHexOctet(mwis[i]);
- }
-
- Buf.writeStringDelimiter(strLen);
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: ICC_EF_MWIS,
- recordNumber: 1, // Update 1st Subscriber Profile.
- dataWriter: dataWriter.bind(this)
- });
- },
-
- /**
- * Read the SPDI (Service Provider Display Information) from the (U)SIM.
- *
- * See TS 131.102 section 4.2.66 for USIM and TS 51.011 section 10.3.50
- * for SIM.
- */
- readSPDI: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- let readLen = 0;
- let endLoop = false;
-
- let RIL = this.context.RIL;
- RIL.iccInfoPrivate.SPDI = null;
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- while ((readLen < octetLen) && !endLoop) {
- let tlvTag = GsmPDUHelper.readHexOctet();
- let tlvLen = GsmPDUHelper.readHexOctet();
- readLen += 2; // For tag and length fields.
- switch (tlvTag) {
- case SPDI_TAG_SPDI:
- // The value part itself is a TLV.
- continue;
- case SPDI_TAG_PLMN_LIST:
- // This PLMN list is what we want.
- RIL.iccInfoPrivate.SPDI = this.readPLMNEntries(tlvLen / 3);
- readLen += tlvLen;
- endLoop = true;
- break;
- default:
- // We don't care about its content if its tag is not SPDI nor
- // PLMN_LIST.
- endLoop = true;
- break;
- }
- }
-
- // Consume unread octets.
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) {
- this.context.debug("SPDI: " + JSON.stringify(RIL.iccInfoPrivate.SPDI));
- }
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- if (ICCUtilsHelper.updateDisplayCondition()) {
- ICCUtilsHelper.handleICCInfoChange();
- }
- }
-
- // PLMN List is Servive 51 in USIM, EF_SPDI
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_SPDI,
- callback: callback.bind(this)
- });
- },
-
- _readCbmiHelper: function(which) {
- let RIL = this.context.RIL;
-
- function callback() {
- let Buf = this.context.Buf;
- let strLength = Buf.readInt32();
-
- // Each Message Identifier takes two octets and each octet is encoded
- // into two chars.
- let numIds = strLength / 4, list = null;
- if (numIds) {
- list = [];
- let GsmPDUHelper = this.context.GsmPDUHelper;
- for (let i = 0, id; i < numIds; i++) {
- id = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
- // `Unused entries shall be set to 'FF FF'.`
- if (id != 0xFFFF) {
- list.push(id);
- list.push(id + 1);
- }
- }
- }
- if (DEBUG) {
- this.context.debug(which + ": " + JSON.stringify(list));
- }
-
- Buf.readStringDelimiter(strLength);
-
- RIL.cellBroadcastConfigs[which] = list;
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- function onerror() {
- RIL.cellBroadcastConfigs[which] = null;
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- let fileId = GLOBAL["ICC_EF_" + which];
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: fileId,
- callback: callback.bind(this),
- onerror: onerror.bind(this)
- });
- },
-
- /**
- * Read EFcbmi (Cell Broadcast Message Identifier selection)
- *
- * @see 3GPP TS 31.102 v110.02.0 section 4.2.14 EFcbmi
- * @see 3GPP TS 51.011 v5.0.0 section 10.3.13 EFcbmi
- */
- readCBMI: function() {
- this._readCbmiHelper("CBMI");
- },
-
- /**
- * Read EFcbmid (Cell Broadcast Message Identifier for Data Download)
- *
- * @see 3GPP TS 31.102 v110.02.0 section 4.2.20 EFcbmid
- * @see 3GPP TS 51.011 v5.0.0 section 10.3.26 EFcbmid
- */
- readCBMID: function() {
- this._readCbmiHelper("CBMID");
- },
-
- /**
- * Read EFcbmir (Cell Broadcast Message Identifier Range selection)
- *
- * @see 3GPP TS 31.102 v110.02.0 section 4.2.22 EFcbmir
- * @see 3GPP TS 51.011 v5.0.0 section 10.3.28 EFcbmir
- */
- readCBMIR: function() {
- let RIL = this.context.RIL;
-
- function callback() {
- let Buf = this.context.Buf;
- let strLength = Buf.readInt32();
-
- // Each Message Identifier range takes four octets and each octet is
- // encoded into two chars.
- let numIds = strLength / 8, list = null;
- if (numIds) {
- list = [];
- let GsmPDUHelper = this.context.GsmPDUHelper;
- for (let i = 0, from, to; i < numIds; i++) {
- // `Bytes one and two of each range identifier equal the lower value
- // of a cell broadcast range, bytes three and four equal the upper
- // value of a cell broadcast range.`
- from = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
- to = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
- // `Unused entries shall be set to 'FF FF'.`
- if ((from != 0xFFFF) && (to != 0xFFFF)) {
- list.push(from);
- list.push(to + 1);
- }
- }
- }
- if (DEBUG) {
- this.context.debug("CBMIR: " + JSON.stringify(list));
- }
-
- Buf.readStringDelimiter(strLength);
-
- RIL.cellBroadcastConfigs.CBMIR = list;
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- function onerror() {
- RIL.cellBroadcastConfigs.CBMIR = null;
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CBMIR,
- callback: callback.bind(this),
- onerror: onerror.bind(this)
- });
- },
-
- /**
- * Read OPL (Operator PLMN List) from (U)SIM.
- *
- * See 3GPP TS 31.102 Sec. 4.2.59 for USIM
- * 3GPP TS 51.011 Sec. 10.3.42 for SIM.
- */
- readOPL: function() {
- let ICCIOHelper = this.context.ICCIOHelper;
- let opl = [];
- function callback(options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let strLen = Buf.readInt32();
- // The first 7 bytes are LAI (for UMTS) and the format of LAI is defined
- // in 3GPP TS 23.003, Sec 4.1
- // +-------------+---------+
- // | Octet 1 - 3 | MCC/MNC |
- // +-------------+---------+
- // | Octet 4 - 7 | LAC |
- // +-------------+---------+
- let mccMnc = [GsmPDUHelper.readHexOctet(),
- GsmPDUHelper.readHexOctet(),
- GsmPDUHelper.readHexOctet()];
- if (mccMnc[0] != 0xFF || mccMnc[1] != 0xFF || mccMnc[2] != 0xFF) {
- let oplElement = {};
- let semiOctets = [];
- for (let i = 0; i < mccMnc.length; i++) {
- semiOctets.push((mccMnc[i] & 0xf0) >> 4);
- semiOctets.push(mccMnc[i] & 0x0f);
- }
- let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
- semiOctets[5], semiOctets[4], semiOctets[2]];
- let buf = "";
- for (let i = 0; i < reformat.length; i++) {
- if (reformat[i] != 0xF) {
- buf += GsmPDUHelper.semiOctetToExtendedBcdChar(reformat[i]);
- }
- if (i === 2) {
- // 0-2: MCC
- oplElement.mcc = buf;
- buf = "";
- } else if (i === 5) {
- // 3-5: MNC
- oplElement.mnc = buf;
- }
- }
- // LAC/TAC
- oplElement.lacTacStart =
- (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- oplElement.lacTacEnd =
- (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- // PLMN Network Name Record Identifier
- oplElement.pnnRecordId = GsmPDUHelper.readHexOctet();
- if (DEBUG) {
- this.context.debug("OPL: [" + (opl.length + 1) + "]: " +
- JSON.stringify(oplElement));
- }
- opl.push(oplElement);
- } else {
- Buf.seekIncoming(5 * Buf.PDU_HEX_OCTET_SIZE);
- }
- Buf.readStringDelimiter(strLen);
-
- let RIL = this.context.RIL;
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- } else {
- RIL.iccInfoPrivate.OPL = opl;
- RIL.overrideICCNetworkName();
- }
- }
-
- ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_OPL,
- callback: callback.bind(this)});
- },
-
- /**
- * Read PNN (PLMN Network Name) from (U)SIM.
- *
- * See 3GPP TS 31.102 Sec. 4.2.58 for USIM
- * 3GPP TS 51.011 Sec. 10.3.41 for SIM.
- */
- readPNN: function() {
- let ICCIOHelper = this.context.ICCIOHelper;
- function callback(options) {
- let pnnElement;
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- let readLen = 0;
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- while (readLen < octetLen) {
- let tlvTag = GsmPDUHelper.readHexOctet();
-
- if (tlvTag == 0xFF) {
- // Unused byte
- readLen++;
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- break;
- }
-
- // Needs this check to avoid initializing twice.
- pnnElement = pnnElement || {};
-
- let tlvLen = GsmPDUHelper.readHexOctet();
-
- switch (tlvTag) {
- case PNN_IEI_FULL_NETWORK_NAME:
- pnnElement.fullName = GsmPDUHelper.readNetworkName(tlvLen);
- break;
- case PNN_IEI_SHORT_NETWORK_NAME:
- pnnElement.shortName = GsmPDUHelper.readNetworkName(tlvLen);
- break;
- default:
- Buf.seekIncoming(tlvLen * Buf.PDU_HEX_OCTET_SIZE);
- break;
- }
-
- readLen += (tlvLen + 2); // +2 for tlvTag and tlvLen
- }
- Buf.readStringDelimiter(strLen);
-
- pnn.push(pnnElement);
-
- let RIL = this.context.RIL;
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- } else {
- if (DEBUG) {
- for (let i = 0; i < pnn.length; i++) {
- this.context.debug("PNN: [" + i + "]: " + JSON.stringify(pnn[i]));
- }
- }
- RIL.iccInfoPrivate.PNN = pnn;
- RIL.overrideICCNetworkName();
- }
- }
-
- let pnn = [];
- ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_PNN,
- callback: callback.bind(this)});
- },
-
- /**
- * Read the list of PLMN (Public Land Mobile Network) entries
- * We cannot directly rely on readSwappedNibbleBcdToString(),
- * since it will no correctly handle some corner-cases that are
- * not a problem in our case (0xFF 0xFF 0xFF).
- *
- * @param length The number of PLMN records.
- * @return An array of string corresponding to the PLMNs.
- */
- readPLMNEntries: function(length) {
- let plmnList = [];
- // Each PLMN entry has 3 bytes.
- if (DEBUG) {
- this.context.debug("PLMN entries length = " + length);
- }
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let index = 0;
- while (index < length) {
- // Unused entries will be 0xFFFFFF, according to EF_SPDI
- // specs (TS 131 102, section 4.2.66)
- try {
- let plmn = [GsmPDUHelper.readHexOctet(),
- GsmPDUHelper.readHexOctet(),
- GsmPDUHelper.readHexOctet()];
- if (DEBUG) {
- this.context.debug("Reading PLMN entry: [" + index + "]: '" + plmn + "'");
- }
- if (plmn[0] != 0xFF &&
- plmn[1] != 0xFF &&
- plmn[2] != 0xFF) {
- let semiOctets = [];
- for (let idx = 0; idx < plmn.length; idx++) {
- semiOctets.push((plmn[idx] & 0xF0) >> 4);
- semiOctets.push(plmn[idx] & 0x0F);
- }
-
- // According to TS 24.301, 9.9.3.12, the semi octets is arranged
- // in format:
- // Byte 1: MCC[2] | MCC[1]
- // Byte 2: MNC[3] | MCC[3]
- // Byte 3: MNC[2] | MNC[1]
- // Therefore, we need to rearrange them.
- let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
- semiOctets[5], semiOctets[4], semiOctets[2]];
- let buf = "";
- let plmnEntry = {};
- for (let i = 0; i < reformat.length; i++) {
- if (reformat[i] != 0xF) {
- buf += GsmPDUHelper.semiOctetToExtendedBcdChar(reformat[i]);
- }
- if (i === 2) {
- // 0-2: MCC
- plmnEntry.mcc = buf;
- buf = "";
- } else if (i === 5) {
- // 3-5: MNC
- plmnEntry.mnc = buf;
- }
- }
- if (DEBUG) {
- this.context.debug("PLMN = " + plmnEntry.mcc + ", " + plmnEntry.mnc);
- }
- plmnList.push(plmnEntry);
- }
- } catch (e) {
- if (DEBUG) {
- this.context.debug("PLMN entry " + index + " is invalid.");
- }
- break;
- }
- index ++;
- }
- return plmnList;
- },
-
- /**
- * Read the SMS from the ICC.
- *
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readSMS: function(recordNumber, onsuccess, onerror) {
- function callback(options) {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
-
- // TS 51.011, 10.5.3 EF_SMS
- // b3 b2 b1
- // 0 0 1 message received by MS from network; message read
- // 0 1 1 message received by MS from network; message to be read
- // 1 1 1 MS originating message; message to be sent
- // 1 0 1 MS originating message; message sent to the network:
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let status = GsmPDUHelper.readHexOctet();
-
- let message = GsmPDUHelper.readMessage();
- message.simStatus = status;
-
- // Consumes the remaining buffer
- Buf.seekIncoming(Buf.getReadAvailable() - Buf.PDU_HEX_OCTET_SIZE);
-
- Buf.readStringDelimiter(strLen);
-
- if (message) {
- onsuccess(message);
- } else {
- onerror("Failed to decode SMS on SIM #" + recordNumber);
- }
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_SMS,
- recordNumber: recordNumber,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- readGID1: function() {
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- RIL.iccInfoPrivate.gid1 = Buf.readString();
- if (DEBUG) {
- this.context.debug("GID1: " + RIL.iccInfoPrivate.gid1);
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_GID1,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read CPHS Phase & Service Table from CPHS Info.
- *
- * @See B.3.1.1 CPHS Information in CPHS Phase 2.
- *
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readCphsInfo: function(onsuccess, onerror) {
- function callback() {
- try {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let cphsInfo = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
- if (DEBUG) {
- let str = "";
- for (let i = 0; i < cphsInfo.length; i++) {
- str += cphsInfo[i] + ", ";
- }
- this.context.debug("CPHS INFO: " + str);
- }
-
- /**
- * CPHS INFORMATION
- *
- * Byte 1: CPHS Phase
- * 01 phase 1
- * 02 phase 2
- * etc.
- *
- * Byte 2: CPHS Service Table
- * +----+----+----+----+----+----+----+----+
- * | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 |
- * +----+----+----+----+----+----+----+----+
- * | ONSF | MBN | SST | CSP |
- * | Phase 2 | ALL | Phase 1 | All |
- * +----+----+----+----+----+----+----+----+
- *
- * Byte 3: CPHS Service Table continued
- * +----+----+----+----+----+----+----+----+
- * | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 |
- * +----+----+----+----+----+----+----+----+
- * | RFU | RFU | RFU | INFO_NUM|
- * | | | | Phase 2 |
- * +----+----+----+----+----+----+----+----+
- */
- let cphsPhase = cphsInfo[0];
- if (cphsPhase == 1) {
- // Clear 'Phase 2 only' services.
- cphsInfo[1] &= 0x3F;
- // We don't know whether Byte 3 is available in CPHS phase 1 or not.
- // Add boundary check before accessing it.
- if (cphsInfo.length > 2) {
- cphsInfo[2] = 0x00;
- }
- } else if (cphsPhase == 2) {
- // Clear 'Phase 1 only' services.
- cphsInfo[1] &= 0xF3;
- } else {
- throw new Error("Unknown CPHS phase: " + cphsPhase);
- }
-
- RIL.iccInfoPrivate.cphsSt = cphsInfo.subarray(1);
- onsuccess();
- } catch(e) {
- onerror(e.toString());
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CPHS_INFO,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Read CPHS MBN. (Mailbox Numbers)
- *
- * @See B.4.2.2 Voice Message Retrieval and Indicator Clearing
- */
- readCphsMBN: function() {
- function callback(options) {
- let RIL = this.context.RIL;
- let contact =
- this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
- if (!contact ||
- (RIL.iccInfoPrivate.mbdn !== undefined &&
- RIL.iccInfoPrivate.mbdn === contact.number)) {
- return;
- }
- RIL.iccInfoPrivate.mbdn = contact.number;
- if (DEBUG) {
- this.context.debug("CPHS_MDN, alphaId=" + contact.alphaId +
- " number=" + contact.number);
- }
- contact.rilMessageType = "iccmbdn";
- RIL.sendChromeMessage(contact);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_CPHS_MBN,
- callback: callback.bind(this)
- });
- }
-};
-
-function RuimRecordHelperObject(aContext) {
- this.context = aContext;
-}
-RuimRecordHelperObject.prototype = {
- context: null,
-
- fetchRuimRecords: function() {
- this.getIMSI_M();
- this.readCST();
- this.readCDMAHome();
- this.context.RIL.getCdmaSubscription();
- },
-
- /**
- * Get IMSI_M from CSIM/RUIM.
- * See 3GPP2 C.S0065 Sec. 5.2.2
- */
- getIMSI_M: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let encodedImsi = this.context.GsmPDUHelper.readHexOctetArray(strLen / 2);
- Buf.readStringDelimiter(strLen);
-
- if ((encodedImsi[CSIM_IMSI_M_PROGRAMMED_BYTE] & 0x80)) { // IMSI_M programmed
- let RIL = this.context.RIL;
- RIL.iccInfoPrivate.imsi = this.decodeIMSI(encodedImsi);
- RIL.sendChromeMessage({rilMessageType: "iccimsi",
- imsi: RIL.iccInfoPrivate.imsi});
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- let mccMnc = ICCUtilsHelper.parseMccMncFromImsi(RIL.iccInfoPrivate.imsi);
- if (mccMnc) {
- RIL.iccInfo.mcc = mccMnc.mcc;
- RIL.iccInfo.mnc = mccMnc.mnc;
- ICCUtilsHelper.handleICCInfoChange();
- }
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CSIM_IMSI_M,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Decode IMSI from IMSI_M
- * See 3GPP2 C.S0005 Sec. 2.3.1
- * +---+---------+------------+---+--------+---------+---+---------+--------+
- * |RFU| MCC | programmed |RFU| MNC | MIN1 |RFU| MIN2 | CLASS |
- * +---+---------+------------+---+--------+---------+---+---------+--------+
- * | 6 | 10 bits | 8 bits | 1 | 7 bits | 24 bits | 6 | 10 bits | 8 bits |
- * +---+---------+------------+---+--------+---------+---+---------+--------+
- */
- decodeIMSI: function(encodedImsi) {
- // MCC: 10 bits, 3 digits
- let encodedMCC = ((encodedImsi[CSIM_IMSI_M_MCC_BYTE + 1] & 0x03) << 8) +
- (encodedImsi[CSIM_IMSI_M_MCC_BYTE] & 0xff);
- let mcc = this.decodeIMSIValue(encodedMCC, 3);
-
- // MNC: 7 bits, 2 digits
- let encodedMNC = encodedImsi[CSIM_IMSI_M_MNC_BYTE] & 0x7f;
- let mnc = this.decodeIMSIValue(encodedMNC, 2);
-
- // MIN2: 10 bits, 3 digits
- let encodedMIN2 = ((encodedImsi[CSIM_IMSI_M_MIN2_BYTE + 1] & 0x03) << 8) +
- (encodedImsi[CSIM_IMSI_M_MIN2_BYTE] & 0xff);
- let min2 = this.decodeIMSIValue(encodedMIN2, 3);
-
- // MIN1: 10+4+10 bits, 3+1+3 digits
- let encodedMIN1First3 = ((encodedImsi[CSIM_IMSI_M_MIN1_BYTE + 2] & 0xff) << 2) +
- ((encodedImsi[CSIM_IMSI_M_MIN1_BYTE + 1] & 0xc0) >> 6);
- let min1First3 = this.decodeIMSIValue(encodedMIN1First3, 3);
-
- let encodedFourthDigit = (encodedImsi[CSIM_IMSI_M_MIN1_BYTE + 1] & 0x3c) >> 2;
- if (encodedFourthDigit > 9) {
- encodedFourthDigit = 0;
- }
- let fourthDigit = encodedFourthDigit.toString();
-
- let encodedMIN1Last3 = ((encodedImsi[CSIM_IMSI_M_MIN1_BYTE + 1] & 0x03) << 8) +
- (encodedImsi[CSIM_IMSI_M_MIN1_BYTE] & 0xff);
- let min1Last3 = this.decodeIMSIValue(encodedMIN1Last3, 3);
-
- return mcc + mnc + min2 + min1First3 + fourthDigit + min1Last3;
- },
-
- /**
- * Decode IMSI Helper function
- * See 3GPP2 C.S0005 section 2.3.1.1
- */
- decodeIMSIValue: function(encoded, length) {
- let offset = length === 3 ? 111 : 11;
- let value = encoded + offset;
-
- for (let base = 10, temp = value, i = 0; i < length; i++) {
- if (temp % 10 === 0) {
- value -= base;
- }
- temp = Math.floor(value / base);
- base = base * 10;
- }
-
- let s = value.toString();
- while (s.length < length) {
- s = "0" + s;
- }
-
- return s;
- },
-
- /**
- * Read CDMAHOME for CSIM.
- * See 3GPP2 C.S0023 Sec. 3.4.8.
- */
- readCDMAHome: function() {
- let ICCIOHelper = this.context.ICCIOHelper;
-
- function callback(options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let strLen = Buf.readInt32();
- let tempOctet = GsmPDUHelper.readHexOctet();
- cdmaHomeSystemId.push(((GsmPDUHelper.readHexOctet() & 0x7f) << 8) | tempOctet);
- tempOctet = GsmPDUHelper.readHexOctet();
- cdmaHomeNetworkId.push(((GsmPDUHelper.readHexOctet() & 0xff) << 8) | tempOctet);
-
- // Consuming the last octet: band class.
- Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
-
- Buf.readStringDelimiter(strLen);
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- } else {
- if (DEBUG) {
- this.context.debug("CDMAHome system id: " +
- JSON.stringify(cdmaHomeSystemId));
- this.context.debug("CDMAHome network id: " +
- JSON.stringify(cdmaHomeNetworkId));
- }
- this.context.RIL.cdmaHome = {
- systemId: cdmaHomeSystemId,
- networkId: cdmaHomeNetworkId
- };
- }
- }
-
- let cdmaHomeSystemId = [], cdmaHomeNetworkId = [];
- ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_CSIM_CDMAHOME,
- callback: callback.bind(this)});
- },
-
- /**
- * Read CDMA Service Table.
- * See 3GPP2 C.S0023 Sec. 3.4.18
- */
- readCST: function() {
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- RIL.iccInfoPrivate.cst =
- this.context.GsmPDUHelper.readHexOctetArray(strLen / 2);
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) {
- let str = "";
- for (let i = 0; i < RIL.iccInfoPrivate.cst.length; i++) {
- str += RIL.iccInfoPrivate.cst[i] + ", ";
- }
- this.context.debug("CST: " + str);
- }
-
- if (this.context.ICCUtilsHelper.isICCServiceAvailable("SPN")) {
- if (DEBUG) this.context.debug("SPN: SPN is available");
- this.readSPN();
- }
- }
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CSIM_CST,
- callback: callback.bind(this)
- });
- },
-
- readSPN: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let displayCondition = GsmPDUHelper.readHexOctet();
- let codingScheme = GsmPDUHelper.readHexOctet();
- // Skip one octet: language indicator.
- Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
- let readLen = 3;
-
- // SPN String ends up with 0xff.
- let userDataBuffer = [];
-
- while (readLen < octetLen) {
- let octet = GsmPDUHelper.readHexOctet();
- readLen++;
- if (octet == 0xff) {
- break;
- }
- userDataBuffer.push(octet);
- }
-
- this.context.BitBufferHelper.startRead(userDataBuffer);
-
- let CdmaPDUHelper = this.context.CdmaPDUHelper;
- let msgLen;
- switch (CdmaPDUHelper.getCdmaMsgEncoding(codingScheme)) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- msgLen = Math.floor(userDataBuffer.length * 8 / 7);
- break;
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- msgLen = userDataBuffer.length;
- break;
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- msgLen = Math.floor(userDataBuffer.length / 2);
- break;
- }
-
- let RIL = this.context.RIL;
- RIL.iccInfo.spn = CdmaPDUHelper.decodeCdmaPDUMsg(codingScheme, null, msgLen);
- if (DEBUG) {
- this.context.debug("CDMA SPN: " + RIL.iccInfo.spn +
- ", Display condition: " + displayCondition);
- }
- RIL.iccInfoPrivate.spnDisplayCondition = displayCondition;
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CSIM_SPN,
- callback: callback.bind(this)
- });
- }
-};
-
-/**
- * Helper functions for ICC utilities.
- */
-function ICCUtilsHelperObject(aContext) {
- this.context = aContext;
-}
-ICCUtilsHelperObject.prototype = {
- context: null,
-
- /**
- * Get network names by using EF_OPL and EF_PNN
- *
- * @See 3GPP TS 31.102 sec. 4.2.58 and sec. 4.2.59 for USIM,
- * 3GPP TS 51.011 sec. 10.3.41 and sec. 10.3.42 for SIM.
- *
- * @param mcc The mobile country code of the network.
- * @param mnc The mobile network code of the network.
- * @param lac The location area code of the network.
- */
- getNetworkNameFromICC: function(mcc, mnc, lac) {
- let RIL = this.context.RIL;
- let iccInfoPriv = RIL.iccInfoPrivate;
- let iccInfo = RIL.iccInfo;
- let pnnEntry;
-
- if (!mcc || !mnc || lac == null || lac < 0) {
- return null;
- }
-
- // We won't get network name if there is no PNN file.
- if (!iccInfoPriv.PNN) {
- return null;
- }
-
- if (!this.isICCServiceAvailable("OPL")) {
- // When OPL is not present:
- // According to 3GPP TS 31.102 Sec. 4.2.58 and 3GPP TS 51.011 Sec. 10.3.41,
- // If EF_OPL is not present, the first record in this EF is used for the
- // default network name when registered to the HPLMN.
- // If we haven't get pnnEntry assigned, we should try to assign default
- // value to it.
- if (mcc == iccInfo.mcc && mnc == iccInfo.mnc) {
- pnnEntry = iccInfoPriv.PNN[0];
- }
- } else {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let wildChar = GsmPDUHelper.extendedBcdChars.charAt(0x0d);
- // According to 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42,
- // the ME shall use this EF_OPL in association with the EF_PNN in place
- // of any network name stored within the ME's internal list and any network
- // name received when registered to the PLMN.
- let length = iccInfoPriv.OPL ? iccInfoPriv.OPL.length : 0;
- for (let i = 0; i < length; i++) {
- let unmatch = false;
- let opl = iccInfoPriv.OPL[i];
- // Try to match the MCC/MNC. Besides, A BCD value of 'D' in any of the
- // MCC and/or MNC digits shall be used to indicate a "wild" value for
- // that corresponding MCC/MNC digit.
- if (opl.mcc.indexOf(wildChar) !== -1) {
- for (let j = 0; j < opl.mcc.length; j++) {
- if (opl.mcc[j] !== wildChar && opl.mcc[j] !== mcc[j]) {
- unmatch = true;
- break;
- }
- }
- if (unmatch) {
- continue;
- }
- } else {
- if (mcc !== opl.mcc) {
- continue;
- }
- }
-
- if (mnc.length !== opl.mnc.length) {
- continue;
- }
-
- if (opl.mnc.indexOf(wildChar) !== -1) {
- for (let j = 0; j < opl.mnc.length; j++) {
- if (opl.mnc[j] !== wildChar && opl.mnc[j] !== mnc[j]) {
- unmatch = true;
- break;
- }
- }
- if (unmatch) {
- continue;
- }
- } else {
- if (mnc !== opl.mnc) {
- continue;
- }
- }
-
- // Try to match the location area code. If current local area code is
- // covered by lac range that specified in the OPL entry, use the PNN
- // that specified in the OPL entry.
- if ((opl.lacTacStart === 0x0 && opl.lacTacEnd == 0xFFFE) ||
- (opl.lacTacStart <= lac && opl.lacTacEnd >= lac)) {
- if (opl.pnnRecordId === 0) {
- // See 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42,
- // A value of '00' indicates that the name is to be taken from other
- // sources.
- return null;
- }
- pnnEntry = iccInfoPriv.PNN[opl.pnnRecordId - 1];
- break;
- }
- }
- }
-
- if (!pnnEntry) {
- return null;
- }
-
- // Return a new object to avoid global variable, PNN, be modified by accident.
- return { fullName: pnnEntry.fullName || "",
- shortName: pnnEntry.shortName || "" };
- },
-
- /**
- * This will compute the spnDisplay field of the network.
- * See TS 22.101 Annex A and TS 51.011 10.3.11 for details.
- *
- * @return True if some of iccInfo is changed in by this function.
- */
- updateDisplayCondition: function() {
- let RIL = this.context.RIL;
-
- // If EFspn isn't existed in SIM or it haven't been read yet, we should
- // just set isDisplayNetworkNameRequired = true and
- // isDisplaySpnRequired = false
- let iccInfo = RIL.iccInfo;
- let iccInfoPriv = RIL.iccInfoPrivate;
- let displayCondition = iccInfoPriv.spnDisplayCondition;
- let origIsDisplayNetworkNameRequired = iccInfo.isDisplayNetworkNameRequired;
- let origIsDisplaySPNRequired = iccInfo.isDisplaySpnRequired;
-
- if (displayCondition === undefined) {
- iccInfo.isDisplayNetworkNameRequired = true;
- iccInfo.isDisplaySpnRequired = false;
- } else if (RIL._isCdma) {
- // CDMA family display rule.
- let cdmaHome = RIL.cdmaHome;
- let cell = RIL.voiceRegistrationState.cell;
- let sid = cell && cell.cdmaSystemId;
- let nid = cell && cell.cdmaNetworkId;
-
- iccInfo.isDisplayNetworkNameRequired = false;
-
- // If display condition is 0x0, we don't even need to check network id
- // or system id.
- if (displayCondition === 0x0) {
- iccInfo.isDisplaySpnRequired = false;
- } else {
- // CDMA SPN Display condition dosen't specify whenever network name is
- // reqired.
- if (!cdmaHome ||
- !cdmaHome.systemId ||
- cdmaHome.systemId.length === 0 ||
- cdmaHome.systemId.length != cdmaHome.networkId.length ||
- !sid || !nid) {
- // CDMA Home haven't been ready, or we haven't got the system id and
- // network id of the network we register to, assuming we are in home
- // network.
- iccInfo.isDisplaySpnRequired = true;
- } else {
- // Determine if we are registered in the home service area.
- // System ID and Network ID are described in 3GPP2 C.S0005 Sec. 2.6.5.2.
- let inHomeArea = false;
- for (let i = 0; i < cdmaHome.systemId.length; i++) {
- let homeSid = cdmaHome.systemId[i],
- homeNid = cdmaHome.networkId[i];
- if (homeSid === 0 || homeNid === 0 // Reserved system id/network id
- || homeSid != sid) {
- continue;
- }
- // According to 3GPP2 C.S0005 Sec. 2.6.5.2, NID number 65535 means
- // all networks in the system should be considered as home.
- if (homeNid == 65535 || homeNid == nid) {
- inHomeArea = true;
- break;
- }
- }
- iccInfo.isDisplaySpnRequired = inHomeArea;
- }
- }
- } else {
- // GSM family display rule.
- let operatorMnc = RIL.operator ? RIL.operator.mnc : -1;
- let operatorMcc = RIL.operator ? RIL.operator.mcc : -1;
-
- // First detect if we are on HPLMN or one of the PLMN
- // specified by the SIM card.
- let isOnMatchingPlmn = false;
-
- // If the current network is the one defined as mcc/mnc
- // in SIM card, it's okay.
- if (iccInfo.mcc == operatorMcc && iccInfo.mnc == operatorMnc) {
- isOnMatchingPlmn = true;
- }
-
- // Test to see if operator's mcc/mnc match mcc/mnc of PLMN.
- if (!isOnMatchingPlmn && iccInfoPriv.SPDI) {
- let iccSpdi = iccInfoPriv.SPDI; // PLMN list
- for (let plmn in iccSpdi) {
- let plmnMcc = iccSpdi[plmn].mcc;
- let plmnMnc = iccSpdi[plmn].mnc;
- isOnMatchingPlmn = (plmnMcc == operatorMcc) && (plmnMnc == operatorMnc);
- if (isOnMatchingPlmn) {
- break;
- }
- }
- }
-
- // See 3GPP TS 22.101 A.4 Service Provider Name indication, and TS 31.102
- // clause 4.2.12 EF_SPN for detail.
- if (isOnMatchingPlmn) {
- // The first bit of display condition tells us if we should display
- // registered PLMN.
- if (DEBUG) {
- this.context.debug("PLMN is HPLMN or PLMN " + "is in PLMN list");
- }
-
- // TS 31.102 Sec. 4.2.66 and TS 51.011 Sec. 10.3.50
- // EF_SPDI contains a list of PLMNs in which the Service Provider Name
- // shall be displayed.
- iccInfo.isDisplaySpnRequired = true;
- iccInfo.isDisplayNetworkNameRequired = (displayCondition & 0x01) !== 0;
- } else {
- // The second bit of display condition tells us if we should display
- // registered PLMN.
- if (DEBUG) {
- this.context.debug("PLMN isn't HPLMN and PLMN isn't in PLMN list");
- }
-
- iccInfo.isDisplayNetworkNameRequired = true;
- iccInfo.isDisplaySpnRequired = (displayCondition & 0x02) === 0;
- }
- }
-
- if (DEBUG) {
- this.context.debug("isDisplayNetworkNameRequired = " +
- iccInfo.isDisplayNetworkNameRequired);
- this.context.debug("isDisplaySpnRequired = " + iccInfo.isDisplaySpnRequired);
- }
-
- return ((origIsDisplayNetworkNameRequired !== iccInfo.isDisplayNetworkNameRequired) ||
- (origIsDisplaySPNRequired !== iccInfo.isDisplaySpnRequired));
- },
-
- decodeSimTlvs: function(tlvsLen) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let index = 0;
- let tlvs = [];
- while (index < tlvsLen) {
- let simTlv = {
- tag : GsmPDUHelper.readHexOctet(),
- length : GsmPDUHelper.readHexOctet(),
- };
- simTlv.value = GsmPDUHelper.readHexOctetArray(simTlv.length);
- tlvs.push(simTlv);
- index += simTlv.length + 2; // The length of 'tag' and 'length' field.
- }
- return tlvs;
- },
-
- /**
- * Parse those TLVs and convert it to an object.
- */
- parsePbrTlvs: function(pbrTlvs) {
- let pbr = {};
- for (let i = 0; i < pbrTlvs.length; i++) {
- let pbrTlv = pbrTlvs[i];
- let anrIndex = 0;
- for (let j = 0; j < pbrTlv.value.length; j++) {
- let tlv = pbrTlv.value[j];
- let tagName = USIM_TAG_NAME[tlv.tag];
-
- // ANR could have multiple files. We save it as anr0, anr1,...etc.
- if (tlv.tag == ICC_USIM_EFANR_TAG) {
- tagName += anrIndex;
- anrIndex++;
- }
- pbr[tagName] = tlv;
- pbr[tagName].fileType = pbrTlv.tag;
- pbr[tagName].fileId = (tlv.value[0] << 8) | tlv.value[1];
- pbr[tagName].sfi = tlv.value[2];
-
- // For Type 2, the order of files is in the same order in IAP.
- if (pbrTlv.tag == ICC_USIM_TYPE2_TAG) {
- pbr[tagName].indexInIAP = j;
- }
- }
- }
-
- return pbr;
- },
-
- /**
- * Update the ICC information to RadioInterfaceLayer.
- */
- handleICCInfoChange: function() {
- let RIL = this.context.RIL;
- RIL.iccInfo.rilMessageType = "iccinfochange";
- RIL.sendChromeMessage(RIL.iccInfo);
- },
-
- /**
- * Get whether specificed (U)SIM service is available.
- *
- * @param geckoService
- * Service name like "ADN", "BDN", etc.
- *
- * @return true if the service is enabled, false otherwise.
- */
- isICCServiceAvailable: function(geckoService) {
- let RIL = this.context.RIL;
- let serviceTable = RIL._isCdma ? RIL.iccInfoPrivate.cst:
- RIL.iccInfoPrivate.sst;
- let index, bitmask;
- if (RIL.appType == CARD_APPTYPE_SIM || RIL.appType == CARD_APPTYPE_RUIM) {
- /**
- * Service id is valid in 1..N, and 2 bits are used to code each service.
- *
- * +----+-- --+----+----+
- * | b8 | ... | b2 | b1 |
- * +----+-- --+----+----+
- *
- * b1 = 0, service not allocated.
- * 1, service allocated.
- * b2 = 0, service not activated.
- * 1, service activated.
- *
- * @see 3GPP TS 51.011 10.3.7.
- */
- let simService;
- if (RIL.appType == CARD_APPTYPE_SIM) {
- simService = GECKO_ICC_SERVICES.sim[geckoService];
- } else {
- simService = GECKO_ICC_SERVICES.ruim[geckoService];
- }
- if (!simService) {
- return false;
- }
- simService -= 1;
- index = Math.floor(simService / 4);
- bitmask = 2 << ((simService % 4) << 1);
- } else if (RIL.appType == CARD_APPTYPE_USIM) {
- /**
- * Service id is valid in 1..N, and 1 bit is used to code each service.
- *
- * +----+-- --+----+----+
- * | b8 | ... | b2 | b1 |
- * +----+-- --+----+----+
- *
- * b1 = 0, service not avaiable.
- * 1, service available.
- *
- * @see 3GPP TS 31.102 4.2.8.
- */
- let usimService = GECKO_ICC_SERVICES.usim[geckoService];
- if (!usimService) {
- return false;
- }
- usimService -= 1;
- index = Math.floor(usimService / 8);
- bitmask = 1 << ((usimService % 8) << 0);
- }
-
- return (serviceTable !== null) &&
- (index < serviceTable.length) &&
- ((serviceTable[index] & bitmask) !== 0);
- },
-
- /**
- * Get whether specificed CPHS service is available.
- *
- * @param geckoService
- * Service name like "MDN", etc.
- *
- * @return true if the service is enabled, false otherwise.
- */
- isCphsServiceAvailable: function(geckoService) {
- let RIL = this.context.RIL;
- let serviceTable = RIL.iccInfoPrivate.cphsSt;
-
- if (!(serviceTable instanceof Uint8Array)) {
- return false;
- }
-
- /**
- * Service id is valid in 1..N, and 2 bits are used to code each service.
- *
- * +----+-- --+----+----+
- * | b8 | ... | b2 | b1 |
- * +----+-- --+----+----+
- *
- * b1 = 0, service not allocated.
- * 1, service allocated.
- * b2 = 0, service not activated.
- * 1, service activated.
- *
- * @See B.3.1.1 CPHS Information in CPHS Phase 2.
- */
- let cphsService = GECKO_ICC_SERVICES.cphs[geckoService];
-
- if (!cphsService) {
- return false;
- }
- cphsService -= 1;
- let index = Math.floor(cphsService / 4);
- let bitmask = 2 << ((cphsService % 4) << 1);
-
- return (index < serviceTable.length) &&
- ((serviceTable[index] & bitmask) !== 0);
- },
-
- /**
- * Check if the string is of GSM default 7-bit coded alphabets with bit 8
- * set to 0.
- *
- * @param str String to be checked.
- */
- isGsm8BitAlphabet: function(str) {
- if (!str) {
- return false;
- }
-
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- for (let i = 0; i < str.length; i++) {
- let c = str.charAt(i);
- let octet = langTable.indexOf(c);
- if (octet == -1) {
- octet = langShiftTable.indexOf(c);
- if (octet == -1) {
- return false;
- }
- }
- }
-
- return true;
- },
-
- /**
- * Parse MCC/MNC from IMSI. If there is no available value for the length of
- * mnc, it will use the data in MCC table to parse.
- *
- * @param imsi
- * The imsi of icc.
- * @param mncLength [optional]
- * The length of mnc.
- * Zero indicates we haven't got a valid mnc length.
- *
- * @return An object contains the parsing result of mcc and mnc.
- * Or null if any error occurred.
- */
- parseMccMncFromImsi: function(imsi, mncLength) {
- if (!imsi) {
- return null;
- }
-
- // MCC is the first 3 digits of IMSI.
- let mcc = imsi.substr(0,3);
- if (!mncLength) {
- // Check the MCC/MNC table for MNC length = 3 first for the case we don't
- // have the 4th byte data from EF_AD.
- if (PLMN_HAVING_3DIGITS_MNC[mcc] &&
- PLMN_HAVING_3DIGITS_MNC[mcc].indexOf(imsi.substr(3, 3)) !== -1) {
- mncLength = 3;
- } else {
- // Check the MCC table to decide the length of MNC.
- let index = MCC_TABLE_FOR_MNC_LENGTH_IS_3.indexOf(mcc);
- mncLength = (index !== -1) ? 3 : 2;
- }
- }
- let mnc = imsi.substr(3, mncLength);
- if (DEBUG) {
- this.context.debug("IMSI: " + imsi + " MCC: " + mcc + " MNC: " + mnc);
- }
-
- return { mcc: mcc, mnc: mnc};
- },
-};
-
-/**
- * Helper for ICC Contacts.
- */
-function ICCContactHelperObject(aContext) {
- this.context = aContext;
-}
-ICCContactHelperObject.prototype = {
- context: null,
-
- /**
- * Helper function to check DF_PHONEBOOK.
- */
- hasDfPhoneBook: function(appType) {
- switch (appType) {
- case CARD_APPTYPE_SIM:
- return false;
- case CARD_APPTYPE_USIM:
- return true;
- case CARD_APPTYPE_RUIM:
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- return ICCUtilsHelper.isICCServiceAvailable("ENHANCED_PHONEBOOK");
- default:
- return false;
- }
- },
-
- /**
- * Helper function to read ICC contacts.
- *
- * @param appType One of CARD_APPTYPE_*.
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readICCContacts: function(appType, contactType, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
-
- switch (contactType) {
- case GECKO_CARDCONTACT_TYPE_ADN:
- if (!this.hasDfPhoneBook(appType)) {
- ICCRecordHelper.readADNLike(ICC_EF_ADN,
- (ICCUtilsHelper.isICCServiceAvailable("EXT1")) ? ICC_EF_EXT1 : null,
- onsuccess, onerror);
- } else {
- this.readUSimContacts(onsuccess, onerror);
- }
- break;
- case GECKO_CARDCONTACT_TYPE_FDN:
- if (!ICCUtilsHelper.isICCServiceAvailable("FDN")) {
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- ICCRecordHelper.readADNLike(ICC_EF_FDN,
- (ICCUtilsHelper.isICCServiceAvailable("EXT2")) ? ICC_EF_EXT2 : null,
- onsuccess, onerror);
- break;
- case GECKO_CARDCONTACT_TYPE_SDN:
- if (!ICCUtilsHelper.isICCServiceAvailable("SDN")) {
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
-
- ICCRecordHelper.readADNLike(ICC_EF_SDN,
- (ICCUtilsHelper.isICCServiceAvailable("EXT3")) ? ICC_EF_EXT3 : null,
- onsuccess, onerror);
- break;
- default:
- if (DEBUG) {
- this.context.debug("Unsupported contactType :" + contactType);
- }
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- },
-
- /**
- * Helper function to find free contact record.
- *
- * @param appType One of CARD_APPTYPE_*.
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- findFreeICCContact: function(appType, contactType, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- switch (contactType) {
- case GECKO_CARDCONTACT_TYPE_ADN:
- if (!this.hasDfPhoneBook(appType)) {
- ICCRecordHelper.findFreeRecordId(ICC_EF_ADN, onsuccess.bind(null, 0), onerror);
- } else {
- let gotPbrCb = function gotPbrCb(pbrs) {
- this.findUSimFreeADNRecordId(pbrs, onsuccess, onerror);
- }.bind(this);
-
- ICCRecordHelper.readPBR(gotPbrCb, onerror);
- }
- break;
- case GECKO_CARDCONTACT_TYPE_FDN:
- ICCRecordHelper.findFreeRecordId(ICC_EF_FDN, onsuccess.bind(null, 0), onerror);
- break;
- default:
- if (DEBUG) {
- this.context.debug("Unsupported contactType :" + contactType);
- }
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- },
-
- /**
- * Cache the pbr index of the possible free record.
- */
- _freePbrIndex: 0,
-
- /**
- * Find free ADN record id in USIM.
- *
- * @param pbrs All Phonebook Reference Files read.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- findUSimFreeADNRecordId: function(pbrs, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- function callback(pbrIndex, recordId) {
- // Assume other free records are probably in the same phonebook set.
- this._freePbrIndex = pbrIndex;
- onsuccess(pbrIndex, recordId);
- }
-
- let nextPbrIndex = -1;
- (function findFreeRecordId(pbrIndex) {
- if (nextPbrIndex === this._freePbrIndex) {
- // No free record found, reset the pbr index of free record.
- this._freePbrIndex = 0;
- if (DEBUG) {
- this.context.debug(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- }
- onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- return;
- }
-
- let pbr = pbrs[pbrIndex];
- nextPbrIndex = (pbrIndex + 1) % pbrs.length;
- ICCRecordHelper.findFreeRecordId(
- pbr.adn.fileId,
- callback.bind(this, pbrIndex),
- findFreeRecordId.bind(this, nextPbrIndex));
- }).call(this, this._freePbrIndex);
- },
-
- /**
- * Helper function to add a new ICC contact.
- *
- * @param appType One of CARD_APPTYPE_*.
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param contact The contact will be added.
- * @param pin2 PIN2 is required for FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- addICCContact: function(appType, contactType, contact, pin2, onsuccess, onerror) {
- let foundFreeCb = (function foundFreeCb(pbrIndex, recordId) {
- contact.pbrIndex = pbrIndex;
- contact.recordId = recordId;
- this.updateICCContact(appType, contactType, contact, pin2, onsuccess, onerror);
- }).bind(this);
-
- // Find free record first.
- this.findFreeICCContact(appType, contactType, foundFreeCb, onerror);
- },
-
- /**
- * Helper function to update ICC contact.
- *
- * @param appType One of CARD_APPTYPE_*.
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param contact The contact will be updated.
- * @param pin2 PIN2 is required for FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateICCContact: function(appType, contactType, contact, pin2, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
-
- let updateContactCb = (updatedContact) => {
- updatedContact.pbrIndex = contact.pbrIndex;
- updatedContact.recordId = contact.recordId;
- onsuccess(updatedContact);
- }
-
- switch (contactType) {
- case GECKO_CARDCONTACT_TYPE_ADN:
- if (!this.hasDfPhoneBook(appType)) {
- if (ICCUtilsHelper.isICCServiceAvailable("EXT1")) {
- this.updateADNLikeWithExtension(ICC_EF_ADN, ICC_EF_EXT1,
- contact, null,
- updateContactCb, onerror);
- } else {
- ICCRecordHelper.updateADNLike(ICC_EF_ADN, 0xff,
- contact, null,
- updateContactCb, onerror);
- }
- } else {
- this.updateUSimContact(contact, updateContactCb, onerror);
- }
- break;
- case GECKO_CARDCONTACT_TYPE_FDN:
- if (!pin2) {
- onerror(GECKO_ERROR_SIM_PIN2);
- return;
- }
- if (!ICCUtilsHelper.isICCServiceAvailable("FDN")) {
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- if (ICCUtilsHelper.isICCServiceAvailable("EXT2")) {
- this.updateADNLikeWithExtension(ICC_EF_FDN, ICC_EF_EXT2,
- contact, pin2,
- updateContactCb, onerror);
- } else {
- ICCRecordHelper.updateADNLike(ICC_EF_FDN,
- 0xff,
- contact, pin2,
- updateContactCb, onerror);
- }
- break;
- default:
- if (DEBUG) {
- this.context.debug("Unsupported contactType :" + contactType);
- }
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- },
-
- /**
- * Read contacts from USIM.
- *
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readUSimContacts: function(onsuccess, onerror) {
- let gotPbrCb = function gotPbrCb(pbrs) {
- this.readAllPhonebookSets(pbrs, onsuccess, onerror);
- }.bind(this);
-
- this.context.ICCRecordHelper.readPBR(gotPbrCb, onerror);
- },
-
- /**
- * Read all Phonebook sets.
- *
- * @param pbrs All Phonebook Reference Files read.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readAllPhonebookSets: function(pbrs, onsuccess, onerror) {
- let allContacts = [], pbrIndex = 0;
- let readPhonebook = function(contacts) {
- if (contacts) {
- allContacts = allContacts.concat(contacts);
- }
-
- let cLen = contacts ? contacts.length : 0;
- for (let i = 0; i < cLen; i++) {
- contacts[i].pbrIndex = pbrIndex;
- }
-
- pbrIndex++;
- if (pbrIndex >= pbrs.length) {
- if (onsuccess) {
- onsuccess(allContacts);
- }
- return;
- }
-
- this.readPhonebookSet(pbrs[pbrIndex], readPhonebook, onerror);
- }.bind(this);
-
- this.readPhonebookSet(pbrs[pbrIndex], readPhonebook, onerror);
- },
-
- /**
- * Read from Phonebook Reference File.
- *
- * @param pbr Phonebook Reference File to be read.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readPhonebookSet: function(pbr, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let gotAdnCb = function gotAdnCb(contacts) {
- this.readSupportedPBRFields(pbr, contacts, onsuccess, onerror);
- }.bind(this);
-
- ICCRecordHelper.readADNLike(pbr.adn.fileId,
- (pbr.ext1) ? pbr.ext1.fileId : null, gotAdnCb, onerror);
- },
-
- /**
- * Read supported Phonebook fields.
- *
- * @param pbr Phone Book Reference file.
- * @param contacts Contacts stored on ICC.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readSupportedPBRFields: function(pbr, contacts, onsuccess, onerror) {
- let fieldIndex = 0;
- (function readField() {
- let field = USIM_PBR_FIELDS[fieldIndex];
- fieldIndex += 1;
- if (!field) {
- if (onsuccess) {
- onsuccess(contacts);
- }
- return;
- }
-
- this.readPhonebookField(pbr, contacts, field, readField.bind(this), onerror);
- }).call(this);
- },
-
- /**
- * Read Phonebook field.
- *
- * @param pbr The phonebook reference file.
- * @param contacts Contacts stored on ICC.
- * @param field Phonebook field to be retrieved.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readPhonebookField: function(pbr, contacts, field, onsuccess, onerror) {
- if (!pbr[field]) {
- if (onsuccess) {
- onsuccess(contacts);
- }
- return;
- }
-
- (function doReadContactField(n) {
- if (n >= contacts.length) {
- // All contact's fields are read.
- if (onsuccess) {
- onsuccess(contacts);
- }
- return;
- }
-
- // get n-th contact's field.
- this.readContactField(pbr, contacts[n], field,
- doReadContactField.bind(this, n + 1), onerror);
- }).call(this, 0);
- },
-
- /**
- * Read contact's field from USIM.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to get field.
- * @param field Phonebook field to be retrieved.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readContactField: function(pbr, contact, field, onsuccess, onerror) {
- let gotRecordIdCb = function gotRecordIdCb(recordId) {
- if (recordId == 0xff) {
- if (onsuccess) {
- onsuccess();
- }
- return;
- }
-
- let fileId = pbr[field].fileId;
- let fileType = pbr[field].fileType;
- let gotFieldCb = function gotFieldCb(value) {
- if (value) {
- // Move anr0 anr1,.. into anr[].
- if (field.startsWith(USIM_PBR_ANR)) {
- if (!contact[USIM_PBR_ANR]) {
- contact[USIM_PBR_ANR] = [];
- }
- contact[USIM_PBR_ANR].push(value);
- } else {
- contact[field] = value;
- }
- }
-
- if (onsuccess) {
- onsuccess();
- }
- }.bind(this);
-
- let ICCRecordHelper = this.context.ICCRecordHelper;
- // Detect EF to be read, for anr, it could have anr0, anr1,...
- let ef = field.startsWith(USIM_PBR_ANR) ? USIM_PBR_ANR : field;
- switch (ef) {
- case USIM_PBR_EMAIL:
- ICCRecordHelper.readEmail(fileId, fileType, recordId, gotFieldCb, onerror);
- break;
- case USIM_PBR_ANR:
- ICCRecordHelper.readANR(fileId, fileType, recordId, gotFieldCb, onerror);
- break;
- default:
- if (DEBUG) {
- this.context.debug("Unsupported field :" + field);
- }
- onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
- break;
- }
- }.bind(this);
-
- this.getContactFieldRecordId(pbr, contact, field, gotRecordIdCb, onerror);
- },
-
- /**
- * Get the recordId.
- *
- * If the fileType of field is ICC_USIM_TYPE1_TAG, use corresponding ADN recordId.
- * otherwise get the recordId from IAP.
- *
- * @see TS 131.102, clause 4.4.2.2
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact will be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- getContactFieldRecordId: function(pbr, contact, field, onsuccess, onerror) {
- if (pbr[field].fileType == ICC_USIM_TYPE1_TAG) {
- // If the file type is ICC_USIM_TYPE1_TAG, use corresponding ADN recordId.
- if (onsuccess) {
- onsuccess(contact.recordId);
- }
- } else if (pbr[field].fileType == ICC_USIM_TYPE2_TAG) {
- // If the file type is ICC_USIM_TYPE2_TAG, the recordId shall be got from IAP.
- let gotIapCb = function gotIapCb(iap) {
- let indexInIAP = pbr[field].indexInIAP;
- let recordId = iap[indexInIAP];
-
- if (onsuccess) {
- onsuccess(recordId);
- }
- }.bind(this);
-
- this.context.ICCRecordHelper.readIAP(pbr.iap.fileId, contact.recordId,
- gotIapCb, onerror);
- } else {
- if (DEBUG) {
- this.context.debug("USIM PBR files in Type 3 format are not supported.");
- }
- onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED);
- }
- },
-
- /**
- * Update USIM contact.
- *
- * @param contact The contact will be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateUSimContact: function(contact, onsuccess, onerror) {
- let gotPbrCb = function gotPbrCb(pbrs) {
- let pbr = pbrs[contact.pbrIndex];
- if (!pbr) {
- if (DEBUG) {
- this.context.debug(CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
- }
- onerror(CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
- return;
- }
- this.updatePhonebookSet(pbr, contact, onsuccess, onerror);
- }.bind(this);
-
- this.context.ICCRecordHelper.readPBR(gotPbrCb, onerror);
- },
-
- /**
- * Update fields in Phonebook Reference File.
- *
- * @param pbr Phonebook Reference File to be read.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updatePhonebookSet: function(pbr, contact, onsuccess, onerror) {
- let updateAdnCb = function(updatedContact) {
- this.updateSupportedPBRFields(pbr, contact, (updatedContactField) => {
- onsuccess(Object.assign(updatedContact, updatedContactField));
- }, onerror);
- }.bind(this);
-
- if (pbr.ext1) {
- this.updateADNLikeWithExtension(pbr.adn.fileId, pbr.ext1.fileId,
- contact, null, updateAdnCb, onerror);
- } else {
- this.context.ICCRecordHelper.updateADNLike(pbr.adn.fileId, 0xff, contact,
- null, updateAdnCb, onerror);
- }
- },
-
- /**
- * Update supported Phonebook fields.
- *
- * @param pbr Phone Book Reference file.
- * @param contact Contact to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateSupportedPBRFields: function(pbr, contact, onsuccess, onerror) {
- let fieldIndex = 0;
- let contactField = {};
-
- (function updateField() {
- let field = USIM_PBR_FIELDS[fieldIndex];
- fieldIndex += 1;
-
- if (!field) {
- if (onsuccess) {
- onsuccess(contactField);
- }
- return;
- }
-
- // Check if PBR has this field.
- if (!pbr[field]) {
- updateField.call(this);
- return;
- }
-
- this.updateContactField(pbr, contact, field, (fieldEntry) => {
- contactField = Object.assign(contactField, fieldEntry);
- updateField.call(this);
- }, (errorMsg) => {
- // Bug 1194149, there are some sim cards without sufficient
- // Type 2 USIM contact fields record. We allow user continue
- // importing contacts.
- if (errorMsg === CONTACT_ERR_NO_FREE_RECORD_FOUND) {
- updateField.call(this);
- return;
- }
- onerror(errorMsg);
- });
- }).call(this);
- },
-
- /**
- * Update contact's field from USIM.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to be updated.
- * @param field Phonebook field to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateContactField: function(pbr, contact, field, onsuccess, onerror) {
- if (pbr[field].fileType === ICC_USIM_TYPE1_TAG) {
- this.updateContactFieldType1(pbr, contact, field, onsuccess, onerror);
- } else if (pbr[field].fileType === ICC_USIM_TYPE2_TAG) {
- this.updateContactFieldType2(pbr, contact, field, onsuccess, onerror);
- } else {
- if (DEBUG) {
- this.context.debug("USIM PBR files in Type 3 format are not supported.");
- }
- onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED);
- }
- },
-
- /**
- * Update Type 1 USIM contact fields.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to be updated.
- * @param field Phonebook field to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateContactFieldType1: function(pbr, contact, field, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- if (field === USIM_PBR_EMAIL) {
- ICCRecordHelper.updateEmail(pbr, contact.recordId, contact.email, null,
- (updatedEmail) => {
- onsuccess({email: updatedEmail});
- }, onerror);
- } else if (field === USIM_PBR_ANR0) {
- let anr = Array.isArray(contact.anr) ? contact.anr[0] : null;
- ICCRecordHelper.updateANR(pbr, contact.recordId, anr, null,
- (updatedANR) => {
- // ANR could have multiple files. If we support more than one anr,
- // we will save it as anr0, anr1,...etc.
- onsuccess((updatedANR) ? {anr: [updatedANR]} : null);
- }, onerror);
- } else {
- if (DEBUG) {
- this.context.debug("Unsupported field :" + field);
- }
- onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
- }
- },
-
- /**
- * Update Type 2 USIM contact fields.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to be updated.
- * @param field Phonebook field to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateContactFieldType2: function(pbr, contact, field, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- // Case 1 : EF_IAP[adnRecordId] doesn't have a value(0xff)
- // Find a free recordId for EF_field
- // Update field with that free recordId.
- // Update IAP.
- //
- // Case 2: EF_IAP[adnRecordId] has a value
- // update EF_field[iap[field.indexInIAP]]
-
- let gotIapCb = function gotIapCb(iap) {
- let recordId = iap[pbr[field].indexInIAP];
- if (recordId === 0xff) {
- // If the value in IAP[index] is 0xff, which means the contact stored on
- // the SIM doesn't have the additional attribute (email or anr).
- // So if the contact to be updated doesn't have the attribute either,
- // we don't have to update it.
- if ((field === USIM_PBR_EMAIL && contact.email) ||
- (field === USIM_PBR_ANR0 &&
- (Array.isArray(contact.anr) && contact.anr[0]))) {
- // Case 1.
- this.addContactFieldType2(pbr, contact, field, onsuccess, onerror);
- } else {
- if (onsuccess) {
- onsuccess();
- }
- }
- return;
- }
-
- // Case 2.
- if (field === USIM_PBR_EMAIL) {
- ICCRecordHelper.updateEmail(pbr, recordId, contact.email, contact.recordId,
- (updatedEmail) => {
- onsuccess({email: updatedEmail});
- }, onerror);
- } else if (field === USIM_PBR_ANR0) {
- let anr = Array.isArray(contact.anr) ? contact.anr[0] : null;
- ICCRecordHelper.updateANR(pbr, recordId, anr, contact.recordId,
- (updatedANR) => {
- // ANR could have multiple files. If we support more than one anr,
- // we will save it as anr0, anr1,...etc.
- onsuccess((updatedANR) ? {anr: [updatedANR]} : null);
- }, onerror);
- } else {
- if (DEBUG) {
- this.context.debug("Unsupported field :" + field);
- }
- onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
- }
-
- }.bind(this);
-
- ICCRecordHelper.readIAP(pbr.iap.fileId, contact.recordId, gotIapCb, onerror);
- },
-
- /**
- * Add Type 2 USIM contact fields.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to be updated.
- * @param field Phonebook field to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- addContactFieldType2: function(pbr, contact, field, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let successCb = function successCb(recordId) {
-
- let updateCb = function updateCb(contactField) {
- this.updateContactFieldIndexInIAP(pbr, contact.recordId, field, recordId, () => {
- onsuccess(contactField);
- }, onerror);
- }.bind(this);
-
- if (field === USIM_PBR_EMAIL) {
- ICCRecordHelper.updateEmail(pbr, recordId, contact.email, contact.recordId,
- (updatedEmail) => {
- updateCb({email: updatedEmail});
- }, onerror);
- } else if (field === USIM_PBR_ANR0) {
- ICCRecordHelper.updateANR(pbr, recordId, contact.anr[0], contact.recordId,
- (updatedANR) => {
- // ANR could have multiple files. If we support more than one anr,
- // we will save it as anr0, anr1,...etc.
- updateCb((updatedANR) ? {anr: [updatedANR]} : null);
- }, onerror);
- }
- }.bind(this);
-
- let errorCb = function errorCb(errorMsg) {
- if (DEBUG) {
- this.context.debug(errorMsg + " USIM field " + field);
- }
- onerror(errorMsg);
- }.bind(this);
-
- ICCRecordHelper.findFreeRecordId(pbr[field].fileId, successCb, errorCb);
- },
-
- /**
- * Update IAP value.
- *
- * @param pbr The phonebook reference file.
- * @param recordNumber The record identifier of EF_IAP.
- * @param field Phonebook field.
- * @param value The value of 'field' in IAP.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- *
- */
- updateContactFieldIndexInIAP: function(pbr, recordNumber, field, value, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- let gotIAPCb = function gotIAPCb(iap) {
- iap[pbr[field].indexInIAP] = value;
- ICCRecordHelper.updateIAP(pbr.iap.fileId, recordNumber, iap, onsuccess, onerror);
- }.bind(this);
- ICCRecordHelper.readIAP(pbr.iap.fileId, recordNumber, gotIAPCb, onerror);
- },
-
- /**
- * Update ICC ADN like EFs with Extension, like EF_ADN, EF_FDN.
- *
- * @param fileId EF id of the ADN or FDN.
- * @param extFileId EF id of the EXT.
- * @param contact The contact will be updated. (Shall have recordId property)
- * @param pin2 PIN2 is required when updating ICC_EF_FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateADNLikeWithExtension: function(fileId, extFileId, contact, pin2, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let extNumber;
-
- if (contact.number) {
- let numStart = contact.number[0] == "+" ? 1 : 0;
- let number = contact.number.substring(0, numStart) +
- this.context.GsmPDUHelper.stringToExtendedBcd(
- contact.number.substring(numStart));
- extNumber = number.substr(numStart + ADN_MAX_NUMBER_DIGITS,
- EXT_MAX_NUMBER_DIGITS);
- }
-
- ICCRecordHelper.getADNLikeExtensionRecordNumber(fileId, contact.recordId,
- (extRecordNumber) => {
- let updateADNLike = (extRecordNumber) => {
- ICCRecordHelper.updateADNLike(fileId, extRecordNumber, contact,
- pin2, (updatedContact) => {
- if (extNumber && extRecordNumber != 0xff) {
- updatedContact.number = updatedContact.number.concat(extNumber);
- }
- onsuccess(updatedContact);
- }, onerror);
- };
-
- let updateExtension = (extRecordNumber) => {
- ICCRecordHelper.updateExtension(extFileId, extRecordNumber, extNumber,
- () => updateADNLike(extRecordNumber),
- () => updateADNLike(0xff));
- };
-
- if (extNumber) {
- if (extRecordNumber != 0xff) {
- updateExtension(extRecordNumber);
- return;
- }
-
- ICCRecordHelper.findFreeRecordId(extFileId,
- (extRecordNumber) => updateExtension(extRecordNumber),
- (errorMsg) => {
- if (DEBUG) {
- this.context.debug("Couldn't find free extension record Id for " + extFileId + ": " + errorMsg);
- }
- updateADNLike(0xff);
- });
- return;
- }
-
- if (extRecordNumber != 0xff) {
- ICCRecordHelper.cleanEFRecord(extFileId, extRecordNumber,
- () => updateADNLike(0xff), onerror);
- return;
- }
-
- updateADNLike(0xff);
- }, onerror);
- },
-};
-
-function IconLoaderObject(aContext) {
- this.context = aContext;
-}
-IconLoaderObject.prototype = {
- context: null,
-
- /**
- * Load icons.
- *
- * @param recordNumbers Array of the record identifiers of EF_IMG.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- loadIcons: function(recordNumbers, onsuccess, onerror) {
- if (!recordNumbers || !recordNumbers.length) {
- if (onerror) {
- onerror();
- }
- return;
- }
-
- this._start({
- recordNumbers: recordNumbers,
- onsuccess: onsuccess,
- onerror: onerror});
- },
-
- _start: function(options) {
- let callback = (function(icons) {
- if (!options.icons) {
- options.icons = [];
- }
- for (let i = 0; i < icons.length; i++) {
- icons[i] = this._parseRawData(icons[i]);
- }
- options.icons[options.currentRecordIndex] = icons;
- options.currentRecordIndex++;
-
- let recordNumbers = options.recordNumbers;
- if (options.currentRecordIndex < recordNumbers.length) {
- let recordNumber = recordNumbers[options.currentRecordIndex];
- this.context.SimRecordHelper.readIMG(recordNumber,
- callback,
- options.onerror);
- } else {
- if (options.onsuccess) {
- options.onsuccess(options.icons);
- }
- }
- }).bind(this);
-
- options.currentRecordIndex = 0;
- this.context.SimRecordHelper.readIMG(options.recordNumbers[0],
- callback,
- options.onerror);
- },
-
- _parseRawData: function(rawData) {
- let codingScheme = rawData.codingScheme;
-
- switch (codingScheme) {
- case ICC_IMG_CODING_SCHEME_BASIC:
- return this._decodeBasicImage(rawData.width, rawData.height, rawData.body);
-
- case ICC_IMG_CODING_SCHEME_COLOR:
- case ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY:
- return this._decodeColorImage(codingScheme,
- rawData.width, rawData.height,
- rawData.bitsPerImgPoint,
- rawData.numOfClutEntries,
- rawData.clut, rawData.body);
- }
-
- return null;
- },
-
- _decodeBasicImage: function(width, height, body) {
- let numOfPixels = width * height;
- let pixelIndex = 0;
- let currentByteIndex = 0;
- let currentByte = 0x00;
-
- const BLACK = 0x000000FF;
- const WHITE = 0xFFFFFFFF;
-
- let pixels = [];
- while (pixelIndex < numOfPixels) {
- // Reassign data and index for every byte (8 bits).
- if (pixelIndex % 8 == 0) {
- currentByte = body[currentByteIndex++];
- }
- let bit = (currentByte >> (7 - (pixelIndex % 8))) & 0x01;
- pixels[pixelIndex++] = bit ? WHITE : BLACK;
- }
-
- return {pixels: pixels,
- codingScheme: GECKO_IMG_CODING_SCHEME_BASIC,
- width: width,
- height: height};
- },
-
- _decodeColorImage: function(codingScheme, width, height, bitsPerImgPoint,
- numOfClutEntries, clut, body) {
- let mask = 0xff >> (8 - bitsPerImgPoint);
- let bitsStartOffset = 8 - bitsPerImgPoint;
- let bitIndex = bitsStartOffset;
- let numOfPixels = width * height;
- let pixelIndex = 0;
- let currentByteIndex = 0;
- let currentByte = body[currentByteIndex++];
-
- let pixels = [];
- while (pixelIndex < numOfPixels) {
- // Reassign data and index for every byte (8 bits).
- if (bitIndex < 0) {
- currentByte = body[currentByteIndex++];
- bitIndex = bitsStartOffset;
- }
- let clutEntry = ((currentByte >> bitIndex) & mask);
- let clutIndex = clutEntry * ICC_CLUT_ENTRY_SIZE;
- let alpha = codingScheme == ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY &&
- clutEntry == numOfClutEntries - 1;
- pixels[pixelIndex++] = alpha ? 0x00
- : (clut[clutIndex] << 24 |
- clut[clutIndex + 1] << 16 |
- clut[clutIndex + 2] << 8 |
- 0xFF) >>> 0;
- bitIndex -= bitsPerImgPoint;
- }
-
- return {pixels: pixels,
- codingScheme: ICC_IMG_CODING_SCHEME_TO_GECKO[codingScheme],
- width: width,
- height: height};
- },
-};
-
-/**
- * Global stuff.
- */
-
-function Context(aClientId) {
- this.clientId = aClientId;
-
- this.Buf = new BufObject(this);
- this.RIL = new RilObject(this);
- this.RIL.initRILState();
-}
-Context.prototype = {
- clientId: null,
- Buf: null,
- RIL: null,
-
- debug: function(aMessage) {
- GLOBAL.debug("[" + this.clientId + "] " + aMessage);
- }
-};
-
-(function() {
- let lazySymbols = [
- "BerTlvHelper", "BitBufferHelper", "CdmaPDUHelper",
- "ComprehensionTlvHelper", "GsmPDUHelper", "ICCContactHelper",
- "ICCFileHelper", "ICCIOHelper", "ICCPDUHelper", "ICCRecordHelper",
- "ICCUtilsHelper", "RuimRecordHelper", "SimRecordHelper",
- "StkCommandParamsFactory", "StkProactiveCmdHelper", "IconLoader",
- ];
-
- for (let i = 0; i < lazySymbols.length; i++) {
- let symbol = lazySymbols[i];
- Object.defineProperty(Context.prototype, symbol, {
- get: function() {
- let real = new GLOBAL[symbol + "Object"](this);
- Object.defineProperty(this, symbol, {
- value: real,
- enumerable: true
- });
- return real;
- },
- configurable: true,
- enumerable: true
- });
- }
-})();
-
-var ContextPool = {
- _contexts: [],
-
- handleRilMessage: function(aClientId, aUint8Array) {
- let context = this._contexts[aClientId];
- context.Buf.processIncoming(aUint8Array);
- },
-
- handleChromeMessage: function(aMessage) {
- let clientId = aMessage.rilMessageClientId;
- if (clientId != null) {
- let context = this._contexts[clientId];
- context.RIL.handleChromeMessage(aMessage);
- return;
- }
-
- if (DEBUG) debug("Received global chrome message " + JSON.stringify(aMessage));
- let method = this[aMessage.rilMessageType];
- if (typeof method != "function") {
- if (DEBUG) {
- debug("Don't know what to do");
- }
- return;
- }
- method.call(this, aMessage);
- },
-
- setInitialOptions: function(aOptions) {
- DEBUG = DEBUG_WORKER || aOptions.debug;
-
- let quirks = aOptions.quirks;
- RILQUIRKS_CALLSTATE_EXTRA_UINT32 = quirks.callstateExtraUint32;
- RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = quirks.requestUseDialEmergencyCall;
- RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = quirks.simAppStateExtraFields;
- RILQUIRKS_EXTRA_UINT32_2ND_CALL = quirks.extraUint2ndCall;
- RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = quirks.haveQueryIccLockRetryCount;
- RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = quirks.sendStkProfileDownload;
- RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
- RILQUIRKS_SUBSCRIPTION_CONTROL = quirks.subscriptionControl;
- RILQUIRKS_SIGNAL_EXTRA_INT32 = quirks.signalExtraInt;
- RILQUIRKS_AVAILABLE_NETWORKS_EXTRA_STRING = quirks.availableNetworkExtraStr;
- RILQUIRKS_SMSC_ADDRESS_FORMAT = quirks.smscAddressFormat;
- },
-
- setDebugFlag: function(aOptions) {
- DEBUG = DEBUG_WORKER || aOptions.debug;
- },
-
- registerClient: function(aOptions) {
- let clientId = aOptions.clientId;
- this._contexts[clientId] = new Context(clientId);
- },
-};
-
-function onRILMessage(aClientId, aUint8Array) {
- ContextPool.handleRilMessage(aClientId, aUint8Array);
-}
-
-onmessage = function onmessage(event) {
- ContextPool.handleChromeMessage(event.data);
-};
-
-onerror = function onerror(event) {
- if (DEBUG) debug("onerror" + event.message + "\n");
-};
diff --git a/dom/system/gonk/ril_worker_buf_object.js b/dom/system/gonk/ril_worker_buf_object.js
deleted file mode 100644
index 70018c5b2..000000000
--- a/dom/system/gonk/ril_worker_buf_object.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/* global require */
-/* global DEBUG, DEBUG_WORKER */
-/* global RESPONSE_TYPE_SOLICITED */
-/* global RESPONSE_TYPE_UNSOLICITED */
-
-"use strict";
-
-/**
- * This is a specialized worker buffer for the Parcel protocol.
- *
- * NOTE: To prevent including/importing twice, this file should be included
- * in a file which already includes 'ril_consts.js' and 'require.js'.
- */
-(function(exports) {
-
- // Set to true in ril_consts.js to see debug messages
- let DEBUG = DEBUG_WORKER;
- // Need to inherit it.
- let Buf = require("resource://gre/modules/workers/worker_buf.js").Buf;
-
- let BufObject = function(aContext) {
- this.context = aContext;
- // This gets incremented each time we send out a parcel.
- this.mToken = 1;
- // Maps tokens we send out with requests to the request type, so that
- // when we get a response parcel back, we know what request it was for.
- this.mTokenRequestMap = new Map();
- // This is because the underlying 'Buf' is still using the 'init' pattern, so
- // this derived one needs to invoke it.
- // Using 'apply' style to mark it's a parent method calling explicitly.
- Buf._init.apply(this);
-
- // Remapping the request type to different values based on RIL version.
- // We only have to do this for SUBSCRIPTION right now, so I just make it
- // simple. A generic logic or structure could be discussed if we have more
- // use cases, especially the cases from different partners.
- this._requestMap = {};
- // RIL version 8.
- // For the CAF's proprietary parcels. Please see
- // https://www.codeaurora.org/cgit/quic/la/platform/hardware/ril/tree/include/telephony/ril.h?h=b2g_jb_3.2
- let map = {};
- map[REQUEST_SET_UICC_SUBSCRIPTION] = 114;
- map[REQUEST_SET_DATA_SUBSCRIPTION] = 115;
- this._requestMap[8] = map;
- // RIL version 9.
- // For the CAF's proprietary parcels. Please see
- // https://www.codeaurora.org/cgit/quic/la/platform/hardware/ril/tree/include/telephony/ril.h?h=b2g_kk_3.5
- map = {};
- map[REQUEST_SET_UICC_SUBSCRIPTION] = 115;
- map[REQUEST_SET_DATA_SUBSCRIPTION] = 116;
- this._requestMap[9] = map;
- };
-
- /**
- * "inherit" the basic worker buffer.
- */
- BufObject.prototype = Object.create(Buf);
-
- /**
- * Process one parcel.
- */
- BufObject.prototype.processParcel = function() {
- let responseType = this.readInt32();
-
- let requestType, options;
- if (responseType == RESPONSE_TYPE_SOLICITED) {
- let token = this.readInt32();
- let error = this.readInt32();
-
- options = this.mTokenRequestMap.get(token);
- if (!options) {
- if (DEBUG) {
- this.context.debug("Suspicious uninvited request found: " +
- token + ". Ignored!");
- }
- return;
- }
-
- this.mTokenRequestMap.delete(token);
- requestType = options.rilRequestType;
-
- if (error !== ERROR_SUCCESS) {
- options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[error] ||
- GECKO_ERROR_UNSPECIFIED_ERROR;
- }
- if (DEBUG) {
- this.context.debug("Solicited response for request type " + requestType +
- ", token " + token + ", error " + error);
- }
- } else if (responseType == RESPONSE_TYPE_UNSOLICITED) {
- requestType = this.readInt32();
- if (DEBUG) {
- this.context.debug("Unsolicited response for request type " + requestType);
- }
- } else {
- if (DEBUG) {
- this.context.debug("Unknown response type: " + responseType);
- }
- return;
- }
-
- this.context.RIL.handleParcel(requestType, this.readAvailable, options);
- };
-
- /**
- * Start a new outgoing parcel.
- *
- * @param type
- * Integer specifying the request type.
- * @param options [optional]
- * Object containing information about the request, e.g. the
- * original main thread message object that led to the RIL request.
- */
- BufObject.prototype.newParcel = function(type, options) {
- if (DEBUG) {
- this.context.debug("New outgoing parcel of type " + type);
- }
-
- // We're going to leave room for the parcel size at the beginning.
- this.outgoingIndex = this.PARCEL_SIZE_SIZE;
- this.writeInt32(this._reMapRequestType(type));
- this.writeInt32(this.mToken);
-
- if (!options) {
- options = {};
- }
- options.rilRequestType = type;
- this.mTokenRequestMap.set(this.mToken, options);
- this.mToken++;
- return this.mToken;
- };
-
- BufObject.prototype.simpleRequest = function(type, options) {
- this.newParcel(type, options);
- this.sendParcel();
- };
-
- BufObject.prototype.onSendParcel = function(parcel) {
- self.postRILMessage(this.context.clientId, parcel);
- };
-
- /**
- * Remapping the request type to different values based on RIL version.
- * We only have to do this for SUBSCRIPTION right now, so I just make it
- * simple. A generic logic or structure could be discussed if we have more
- * use cases, especially the cases from different partners.
- */
- BufObject.prototype._reMapRequestType = function(type) {
- for (let version in this._requestMap) {
- if (this.context.RIL.version <= version) {
- let newType = this._requestMap[version][type];
- if (newType) {
- if (DEBUG) {
- this.context.debug("Remap request type to " + newType);
- }
- return newType;
- }
- }
- }
- return type;
- };
-
- // Before we make sure to form it as a module would not add extra
- // overhead of module loading, we need to define it in this way
- // rather than 'module.exports' it as a module component.
- exports.BufObject = BufObject;
-})(self); // in worker self is the global
-
diff --git a/dom/system/gonk/ril_worker_telephony_request_queue.js b/dom/system/gonk/ril_worker_telephony_request_queue.js
deleted file mode 100644
index 4dba7a42f..000000000
--- a/dom/system/gonk/ril_worker_telephony_request_queue.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/* global DEBUG, DEBUG_WORKER */
-/* global REQUEST_GET_CURRENT_CALLS */
-/* global REQUEST_ANSWER, REQUEST_CONFERENCE, REQUEST_DIAL */
-/* global REQUEST_DIAL_EMERGENCY_CALL, REQUEST_HANGUP */
-/* global REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND */
-/* global REQUEST_HANGUP_WAITING_OR_BACKGROUND */
-/* global REQUEST_SEPARATE_CONNECTION */
-/* global REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, REQUEST_UDUB */
-
-"use strict";
-
-(function(exports) {
-
- const TELEPHONY_REQUESTS = [
- REQUEST_GET_CURRENT_CALLS,
- REQUEST_ANSWER,
- REQUEST_CONFERENCE,
- REQUEST_DIAL,
- REQUEST_DIAL_EMERGENCY_CALL,
- REQUEST_HANGUP,
- REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
- REQUEST_HANGUP_WAITING_OR_BACKGROUND,
- REQUEST_SEPARATE_CONNECTION,
- REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
- REQUEST_UDUB
- ];
-
- // Set to true in ril_consts.js to see debug messages
- let DEBUG = DEBUG_WORKER;
-
- /**
- * Queue entry; only used in the queue.
- */
- let TelephonyRequestEntry = function(request, callback) {
- this.request = request;
- this.callback = callback;
- };
-
- let TelephonyRequestQueue = function(ril) {
- this.ril = ril;
- this.currentQueue = null; // Point to the current running queue.
-
- this.queryQueue = [];
- this.controlQueue = [];
- };
-
- TelephonyRequestQueue.prototype._getQueue = function(request) {
- return (request === REQUEST_GET_CURRENT_CALLS) ? this.queryQueue
- : this.controlQueue;
- };
-
- TelephonyRequestQueue.prototype._getAnotherQueue = function(queue) {
- return (this.queryQueue === queue) ? this.controlQueue : this.queryQueue;
- };
-
- TelephonyRequestQueue.prototype._find = function(queue, request) {
- for (let i = 0; i < queue.length; ++i) {
- if (queue[i].request === request) {
- return i;
- }
- }
- return -1;
- };
-
- TelephonyRequestQueue.prototype._startQueue = function(queue) {
- if (queue.length === 0) {
- return;
- }
-
- // We only need to keep one entry for queryQueue.
- if (queue === this.queryQueue) {
- queue.splice(1, queue.length - 1);
- }
-
- this.currentQueue = queue;
- for (let entry of queue) {
- this._executeEntry(entry);
- }
- };
-
- TelephonyRequestQueue.prototype._executeEntry = function(entry) {
- if (DEBUG) {
- this.debug("execute " + this._getRequestName(entry.request));
- }
- entry.callback();
- };
-
- TelephonyRequestQueue.prototype._getRequestName = function(request) {
- let method = this.ril[request];
- return (typeof method === 'function') ? method.name : "";
- };
-
- TelephonyRequestQueue.prototype.debug = function(msg) {
- this.ril.context.debug("[TeleQ] " + msg);
- };
-
- TelephonyRequestQueue.prototype.isValidRequest = function(request) {
- return TELEPHONY_REQUESTS.indexOf(request) !== -1;
- };
-
- TelephonyRequestQueue.prototype.push = function(request, callback) {
- if (!this.isValidRequest(request)) {
- if (DEBUG) {
- this.debug("Error: " + this._getRequestName(request) +
- " is not a telephony request");
- }
- return;
- }
-
- if (DEBUG) {
- this.debug("push " + this._getRequestName(request));
- }
- let entry = new TelephonyRequestEntry(request, callback);
- let queue = this._getQueue(request);
- queue.push(entry);
-
- // Try to run the request.
- if (this.currentQueue === queue) {
- this._executeEntry(entry);
- } else if (!this.currentQueue) {
- this._startQueue(queue);
- }
- };
-
- TelephonyRequestQueue.prototype.pop = function(request) {
- if (!this.isValidRequest(request)) {
- if (DEBUG) {
- this.debug("Error: " + this._getRequestName(request) +
- " is not a telephony request");
- }
- return;
- }
-
- if (DEBUG) {
- this.debug("pop " + this._getRequestName(request));
- }
- let queue = this._getQueue(request);
- let index = this._find(queue, request);
- if (index === -1) {
- throw new Error("Cannot find the request in telephonyRequestQueue.");
- } else {
- queue.splice(index, 1);
- }
-
- if (queue.length === 0) {
- this.currentQueue = null;
- this._startQueue(this._getAnotherQueue(queue));
- }
- };
-
-
- // Before we make sure to form it as a module would not add extra
- // overhead of module loading, we need to define it in this way
- // rather than 'module.exports' it as a module component.
- exports.TelephonyRequestQueue = TelephonyRequestQueue;
-})(self); // in worker self is the global
-
diff --git a/dom/system/gonk/systemlibs.js b/dom/system/gonk/systemlibs.js
deleted file mode 100644
index a27b30e20..000000000
--- a/dom/system/gonk/systemlibs.js
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-if (!this.ctypes) {
- // We're likely being loaded as a JSM.
- this.EXPORTED_SYMBOLS = [ "libcutils", "netHelpers" ];
- Components.utils.import("resource://gre/modules/ctypes.jsm");
-}
-
-const SYSTEM_PROPERTY_KEY_MAX = 32;
-const SYSTEM_PROPERTY_VALUE_MAX = 92;
-
-// We leave this as 'undefined' instead of setting it to 'false'. That
-// way a file that includes us can have it defined already without us
-// overriding the value here.
-var DEBUG;
-
-/**
- * Expose some system-level functions.
- */
-this.libcutils = (function() {
- let lib;
- try {
- lib = ctypes.open("libcutils.so");
- } catch(ex) {
- // Return a fallback option in case libcutils.so isn't present (e.g.
- // when building Firefox with MOZ_B2G_RIL.
- if (DEBUG) {
- dump("Could not load libcutils.so. Using fake propdb.\n");
- }
- let fake_propdb = Object.create(null);
- return {
- property_get: function(key, defaultValue) {
- if (key in fake_propdb) {
- return fake_propdb[key];
- }
- return defaultValue === undefined ? null : defaultValue;
- },
- property_set: function(key, value) {
- fake_propdb[key] = value;
- }
- };
- }
-
- let c_property_get = lib.declare("property_get", ctypes.default_abi,
- ctypes.int, // return value: length
- ctypes.char.ptr, // key
- ctypes.char.ptr, // value
- ctypes.char.ptr); // default
- let c_property_set = lib.declare("property_set", ctypes.default_abi,
- ctypes.int, // return value: success
- ctypes.char.ptr, // key
- ctypes.char.ptr); // value
- let c_value_buf = ctypes.char.array(SYSTEM_PROPERTY_VALUE_MAX)();
-
- return {
-
- /**
- * Get a system property.
- *
- * @param key
- * Name of the property
- * @param defaultValue [optional]
- * Default value to return if the property isn't set (default: null)
- */
- property_get: function(key, defaultValue) {
- if (defaultValue === undefined) {
- defaultValue = null;
- }
- c_property_get(key, c_value_buf, defaultValue);
- return c_value_buf.readString();
- },
-
- /**
- * Set a system property
- *
- * @param key
- * Name of the property
- * @param value
- * Value to set the property to.
- */
- property_set: function(key, value) {
- let rv = c_property_set(key, value);
- if (rv) {
- throw Error('libcutils.property_set("' + key + '", "' + value +
- '") failed with error ' + rv);
- }
- }
-
- };
-})();
-
-/**
- * Helpers for conversions.
- */
-this.netHelpers = {
-
- /**
- * Swap byte orders for 32-bit value
- */
- swap32: function(n) {
- return (((n >> 24) & 0xFF) << 0) |
- (((n >> 16) & 0xFF) << 8) |
- (((n >> 8) & 0xFF) << 16) |
- (((n >> 0) & 0xFF) << 24);
- },
-
- /**
- * Convert network byte order to host byte order
- * Note: Assume that the system is little endian
- */
- ntohl: function(n) {
- return this.swap32(n);
- },
-
- /**
- * Convert host byte order to network byte order
- * Note: Assume that the system is little endian
- */
- htonl: function(n) {
- return this.swap32(n);
- },
-
- /**
- * Convert integer representation of an IP address to the string
- * representation.
- *
- * @param ip
- * IP address in number format.
- */
- ipToString: function(ip) {
- return ((ip >> 0) & 0xFF) + "." +
- ((ip >> 8) & 0xFF) + "." +
- ((ip >> 16) & 0xFF) + "." +
- ((ip >> 24) & 0xFF);
- },
-
- /**
- * Convert string representation of an IP address to the integer
- * representation (network byte order).
- *
- * @param string
- * String containing the IP address.
- */
- stringToIP: function(string) {
- if (!string) {
- return null;
- }
- let ip = 0;
- let start, end = -1;
- for (let i = 0; i < 4; i++) {
- start = end + 1;
- end = string.indexOf(".", start);
- if (end == -1) {
- end = string.length;
- }
- let num = parseInt(string.slice(start, end), 10);
- if (isNaN(num)) {
- return null;
- }
- ip |= num << (i * 8);
- }
- return ip;
- },
-
- /**
- * Make a subnet mask.
- */
- makeMask: function(len) {
- let mask = 0;
- for (let i = 0; i < len; ++i) {
- mask |= (0x80000000 >> i);
- }
- return this.ntohl(mask);
- },
-
- /**
- * Get Mask length from given mask address
- */
- getMaskLength: function(mask) {
- let len = 0;
- let netmask = this.ntohl(mask);
- while (netmask & 0x80000000) {
- len++;
- netmask = netmask << 1;
- }
- return len;
- }
-};
diff --git a/dom/system/gonk/tests/header_helpers.js b/dom/system/gonk/tests/header_helpers.js
deleted file mode 100644
index 8d1144f75..000000000
--- a/dom/system/gonk/tests/header_helpers.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-
-var subscriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Ci.mozIJSSubScriptLoader);
-
-/**
- * Start a new RIL worker.
- *
- * @param custom_ns
- * Namespace with symbols to be injected into the new worker
- * namespace.
- *
- * @return an object that represents the worker's namespace.
- *
- * @note that this does not start an actual worker thread. The worker
- * is executed on the main thread, within a separate namespace object.
- */
-function newWorker(custom_ns) {
- let worker_ns = {
- importScripts: function() {
- Array.slice(arguments).forEach(function(script) {
- if (!script.startsWith("resource:")) {
- script = "resource://gre/modules/" + script;
- }
- subscriptLoader.loadSubScript(script, this);
- }, this);
- },
-
- postRILMessage: function(message) {
- },
-
- postMessage: function(message) {
- },
-
- // Define these variables inside the worker scope so ES5 strict mode
- // doesn't flip out.
- onmessage: undefined,
- onerror: undefined,
-
- DEBUG: true
- };
- // The 'self' variable in a worker points to the worker's own namespace.
- worker_ns.self = worker_ns;
-
- // Copy the custom definitions over.
- for (let key in custom_ns) {
- worker_ns[key] = custom_ns[key];
- }
-
- // fake require() for toolkit/components/workerloader/require.js
- let require = (function() {
- return function require(script) {
- worker_ns.module = {};
- worker_ns.importScripts(script);
- return worker_ns;
- }
- })();
-
- Object.freeze(require);
- Object.defineProperty(worker_ns, "require", {
- value: require,
- enumerable: true,
- configurable: false
- });
-
- // Load the RIL worker itself.
- worker_ns.importScripts("ril_worker.js");
-
- // Register at least one client.
- worker_ns.ContextPool.registerClient({ clientId: 0 });
-
- return worker_ns;
-}
-
-/**
- * Create a buffered RIL worker.
- *
- * @return A worker object that stores sending octets in a internal buffer.
- */
-function newUint8Worker() {
- let worker = newWorker();
- let index = 0; // index for read
- let buf = [];
-
- let context = worker.ContextPool._contexts[0];
- context.Buf.writeUint8 = function(value) {
- buf.push(value);
- };
-
- context.Buf.readUint8 = function() {
- return buf[index++];
- };
-
- context.Buf.seekIncoming = function(offset) {
- index += offset;
- };
-
- context.Buf.getReadAvailable = function() {
- return buf.length - index;
- };
-
- worker.debug = do_print;
-
- return worker;
-}
-
-/**
- * Create a worker that keeps posted chrome message.
- */
-function newInterceptWorker() {
- let postedMessage;
- let worker = newWorker({
- postRILMessage: function(data) {
- },
- postMessage: function(message) {
- postedMessage = message;
- }
- });
- return {
- get postedMessage() {
- return postedMessage;
- },
- get worker() {
- return worker;
- }
- };
-}
-
-/**
- * Create a parcel suitable for postRILMessage().
- *
- * @param fakeParcelSize
- * Value to be written to parcel size field for testing
- * incorrect/incomplete parcel reading. Replaced with correct
- * one determined length of data if negative.
- * @param response
- * Response code of the incoming parcel.
- * @param request
- * Request code of the incoming parcel.
- * @param data
- * Extra data to be appended.
- *
- * @return an Uint8Array carrying all parcel data.
- */
-function newIncomingParcel(fakeParcelSize, response, request, data) {
- const UINT32_SIZE = 4;
- const PARCEL_SIZE_SIZE = 4;
-
- let realParcelSize = data.length + 2 * UINT32_SIZE;
- let buffer = new ArrayBuffer(realParcelSize + PARCEL_SIZE_SIZE);
- let bytes = new Uint8Array(buffer);
-
- let writeIndex = 0;
- function writeUint8(value) {
- bytes[writeIndex] = value;
- ++writeIndex;
- }
-
- function writeInt32(value) {
- writeUint8(value & 0xff);
- writeUint8((value >> 8) & 0xff);
- writeUint8((value >> 16) & 0xff);
- writeUint8((value >> 24) & 0xff);
- }
-
- function writeParcelSize(value) {
- writeUint8((value >> 24) & 0xff);
- writeUint8((value >> 16) & 0xff);
- writeUint8((value >> 8) & 0xff);
- writeUint8(value & 0xff);
- }
-
- if (fakeParcelSize < 0) {
- fakeParcelSize = realParcelSize;
- }
- writeParcelSize(fakeParcelSize);
-
- writeInt32(response);
- writeInt32(request);
-
- // write parcel data
- for (let ii = 0; ii < data.length; ++ii) {
- writeUint8(data[ii]);
- }
-
- return bytes;
-}
-
-/**
- * Create a parcel buffer which represents the hex string.
- *
- * @param hexString
- * The HEX string to be converted.
- *
- * @return an Uint8Array carrying all parcel data.
- */
-function hexStringToParcelByteArrayData(hexString) {
- let length = Math.ceil((hexString.length / 2));
- let bytes = new Uint8Array(4 + length);
-
- bytes[0] = length & 0xFF;
- bytes[1] = (length >> 8) & 0xFF;
- bytes[2] = (length >> 16) & 0xFF;
- bytes[3] = (length >> 24) & 0xFF;
-
- for (let i = 0; i < length; i ++) {
- bytes[i + 4] = Number.parseInt(hexString.substr(i * 2, 2), 16);
- }
-
- return bytes;
-}
diff --git a/dom/system/gonk/tests/marionette/head.js b/dom/system/gonk/tests/marionette/head.js
deleted file mode 100644
index 5a6ee1272..000000000
--- a/dom/system/gonk/tests/marionette/head.js
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_CONTEXT = "chrome";
-
-const SETTINGS_KEY_DATA_ENABLED = "ril.data.enabled";
-const SETTINGS_KEY_DATA_APN_SETTINGS = "ril.data.apnSettings";
-const SETTINGS_KEY_WIFI_ENABLED = "wifi.enabled";
-
-const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const TOPIC_NETWORK_ACTIVE_CHANGED = "network-active-changed";
-
-const NETWORK_STATE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN;
-const NETWORK_STATE_CONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTING;
-const NETWORK_STATE_CONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
-const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTING;
-const NETWORK_STATE_DISCONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
-
-const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
-const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS;
-const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL;
-const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS;
-const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN;
-const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA;
-
-const networkTypes = [
- NETWORK_TYPE_MOBILE,
- NETWORK_TYPE_MOBILE_MMS,
- NETWORK_TYPE_MOBILE_SUPL,
- NETWORK_TYPE_MOBILE_IMS,
- NETWORK_TYPE_MOBILE_DUN,
- NETWORK_TYPE_MOBILE_FOTA
-];
-
-var Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;
-
-var ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
-ok(ril, "ril.constructor is " + ril.constructor);
-
-var radioInterface = ril.getRadioInterface(0);
-ok(radioInterface, "radioInterface.constructor is " + radioInterface.constrctor);
-
-var _pendingEmulatorShellCmdCount = 0;
-var _pendingEmulatorCmdCount = 0;
-
-/**
- * Send emulator shell command with safe guard.
- *
- * We should only call |finish()| after all emulator shell command transactions
- * end, so here comes with the pending counter. Resolve when the emulator
- * shell gives response. Never reject.
- *
- * Fulfill params:
- * result -- an array of emulator shell response lines.
- *
- * @param aCommands
- * A string array commands to be passed to emulator through adb shell.
- *
- * @return A deferred promise.
- */
-function runEmulatorShellCmdSafe(aCommands) {
- return new Promise(function(aResolve, aReject) {
- ++_pendingEmulatorShellCmdCount;
- runEmulatorShell(aCommands, function(aResult) {
- --_pendingEmulatorShellCmdCount;
-
- log("Emulator shell response: " + JSON.stringify(aResult));
- aResolve(aResult);
- });
- });
-}
-
-/**
- * Send emulator command with safe guard.
- *
- * We should only call |finish()| after all emulator command transactions
- * end, so here comes with the pending counter. Resolve when the emulator
- * gives positive response, and reject otherwise.
- *
- * Fulfill params:
- * result -- an array of emulator response lines.
- * Reject params:
- * result -- an array of emulator response lines.
- *
- * @param aCommand
- * A string command to be passed to emulator through its telnet console.
- *
- * @return A deferred promise.
- */
-function runEmulatorCmdSafe(aCommand) {
- log(aCommand);
- return new Promise(function(aResolve, aReject) {
- ++_pendingEmulatorCmdCount;
- runEmulatorCmd(aCommand, function(aResult) {
- --_pendingEmulatorCmdCount;
-
- log("Emulator console response: " + JSON.stringify(aResult));
- if (Array.isArray(aResult) &&
- aResult[aResult.length - 1] === "OK") {
- aResolve(aResult);
- } else {
- aReject(aResult);
- }
- });
- });
-}
-
-/**
- * Get mozSettings value specified by @aKey.
- *
- * Resolve if that mozSettings value is retrieved successfully, reject
- * otherwise.
- *
- * Fulfill params: The corresponding mozSettings value of the key.
- * Reject params: (none)
- *
- * @param aKey
- * A string.
- * @param aAllowError [optional]
- * A boolean value. If set to true, an error response won't be treated
- * as test failure. Default: false.
- *
- * @return A deferred promise.
- */
-function getSettings(aKey, aAllowError) {
- let request = window.navigator.mozSettings.createLock().get(aKey);
- return request.then(function resolve(aValue) {
- log("getSettings(" + aKey + ") - success");
- return aValue[aKey];
- }, function reject(aError) {
- ok(aAllowError, "getSettings(" + aKey + ") - error");
- });
-}
-
-/**
- * Set mozSettings values.
- *
- * Resolve if that mozSettings value is set successfully, reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aKey
- * A string key.
- * @param aValue
- * An object value.
- * @param aAllowError [optional]
- * A boolean value. If set to true, an error response won't be treated
- * as test failure. Default: false.
- *
- * @return A deferred promise.
- */
-function setSettings(aKey, aValue, aAllowError) {
- let settings = {};
- settings[aKey] = aValue;
- let lock = window.navigator.mozSettings.createLock();
- let request = lock.set(settings);
- let deferred = Promise.defer();
- lock.onsettingstransactionsuccess = function () {
- log("setSettings(" + JSON.stringify(settings) + ") - success");
- deferred.resolve();
- };
- lock.onsettingstransactionfailure = function () {
- ok(aAllowError, "setSettings(" + JSON.stringify(settings) + ") - error");
- // We resolve even though we've thrown an error, since the ok()
- // will do that.
- deferred.resolve();
- };
- return deferred.promise;
-}
-
-/**
- * Wait for observer event.
- *
- * Resolve if that topic event occurs. Never reject.
- *
- * Fulfill params: the subject passed.
- *
- * @param aTopic
- * A string topic name.
- *
- * @return A deferred promise.
- */
-function waitForObserverEvent(aTopic) {
- let obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
- let deferred = Promise.defer();
-
- obs.addObserver(function observer(subject, topic, data) {
- if (topic === aTopic) {
- obs.removeObserver(observer, aTopic);
- deferred.resolve(subject);
- }
- }, aTopic, false);
-
- return deferred.promise;
-}
-
-/**
- * Wait for one named event.
- *
- * Resolve if that named event occurs. Never reject.
- *
- * Fulfill params: the DOMEvent passed.
- *
- * @param aEventTarget
- * An EventTarget object.
- * @param aEventName
- * A string event name.
- * @param aMatchFun [optional]
- * A matching function returns true or false to filter the event.
- *
- * @return A deferred promise.
- */
-function waitForTargetEvent(aEventTarget, aEventName, aMatchFun) {
- return new Promise(function(aResolve, aReject) {
- aEventTarget.addEventListener(aEventName, function onevent(aEvent) {
- if (!aMatchFun || aMatchFun(aEvent)) {
- aEventTarget.removeEventListener(aEventName, onevent);
- ok(true, "Event '" + aEventName + "' got.");
- aResolve(aEvent);
- }
- });
- });
-}
-
-/**
- * Set the default data connection enabling state, wait for
- * "network-connection-state-changed" event and verify state.
- *
- * Fulfill params: instance of nsIRilNetworkInfo of the network connected.
- *
- * @param aEnabled
- * A boolean state.
- *
- * @return A deferred promise.
- */
-function setDataEnabledAndWait(aEnabled) {
- let promises = [];
- promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
- .then(function(aSubject) {
- ok(aSubject instanceof Ci.nsIRilNetworkInfo,
- "subject should be an instance of nsIRilNetworkInfo");
- is(aSubject.type, NETWORK_TYPE_MOBILE,
- "subject.type should be " + NETWORK_TYPE_MOBILE);
- is(aSubject.state,
- aEnabled ? Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED
- : Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
- "subject.state should be " + aEnabled ? "CONNECTED" : "DISCONNECTED");
-
- return aSubject;
- }));
- promises.push(setSettings(SETTINGS_KEY_DATA_ENABLED, aEnabled));
-
- return Promise.all(promises).then(aValues => aValues[0]);
-}
-
-/**
- * Setup a certain type of data connection, wait for
- * "network-connection-state-changed" event and verify state.
- *
- * Fulfill params: instance of nsIRilNetworkInfo of the network connected.
- *
- * @param aNetworkType
- * The mobile network type to setup.
- *
- * @return A deferred promise.
- */
-function setupDataCallAndWait(aNetworkType) {
- log("setupDataCallAndWait: " + aNetworkType);
-
- let promises = [];
- promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
- .then(function(aSubject) {
- ok(aSubject instanceof Ci.nsIRilNetworkInfo,
- "subject should be an instance of nsIRilNetworkInfo");
- is(aSubject.type, aNetworkType,
- "subject.type should be " + aNetworkType);
- is(aSubject.state, Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED,
- "subject.state should be CONNECTED");
-
- return aSubject;
- }));
- promises.push(radioInterface.setupDataCallByType(aNetworkType));
-
- return Promise.all(promises).then(aValues => aValues[0]);
-}
-
-/**
- * Deactivate a certain type of data connection, wait for
- * "network-connection-state-changed" event and verify state.
- *
- * Fulfill params: (none)
- *
- * @param aNetworkType
- * The mobile network type to deactivate.
- *
- * @return A deferred promise.
- */
-function deactivateDataCallAndWait(aNetworkType) {
- log("deactivateDataCallAndWait: " + aNetworkType);
-
- let promises = [];
- promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
- .then(function(aSubject) {
- ok(aSubject instanceof Ci.nsIRilNetworkInfo,
- "subject should be an instance of nsIRilNetworkInfo");
- is(aSubject.type, aNetworkType,
- "subject.type should be " + aNetworkType);
- is(aSubject.state, Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
- "subject.state should be DISCONNECTED");
- }));
- promises.push(radioInterface.deactivateDataCallByType(aNetworkType));
-
- return Promise.all(promises);
-}
-
-/**
- * Wait for pending emulator transactions and call |finish()|.
- */
-function cleanUp() {
- // Use ok here so that we have at least one test run.
- ok(true, ":: CLEANING UP ::");
-
- waitFor(finish, function() {
- return _pendingEmulatorShellCmdCount === 0 &&
- _pendingEmulatorCmdCount === 0;
- });
-}
-
-/**
- * Basic test routine helper.
- *
- * This helper does nothing but clean-ups.
- *
- * @param aTestCaseMain
- * A function that takes no parameter.
- */
-function startTestBase(aTestCaseMain) {
- Promise.resolve()
- .then(aTestCaseMain)
- .then(cleanUp, function(aException) {
- ok(false, "promise rejects during test: " + aException);
- cleanUp();
- });
-}
diff --git a/dom/system/gonk/tests/marionette/manifest.ini b/dom/system/gonk/tests/marionette/manifest.ini
deleted file mode 100644
index 528fe3baf..000000000
--- a/dom/system/gonk/tests/marionette/manifest.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[DEFAULT]
-run-if = buildapp == 'b2g'
-
-[test_geolocation.js]
-skip-if = true # Bug 808783
-[test_fakevolume.js]
-[test_ril_code_quality.py]
-[test_screen_state.js]
-[test_dsds_numRadioInterfaces.js]
-[test_data_connection.js]
-[test_network_active_changed.js]
-[test_multiple_data_connection.js]
-[test_data_connection_proxy.js]
-[test_network_interface_list_service.js]
-[test_all_network_info.js]
-[test_network_interface_mtu.js]
-skip-if = android_version < '19'
-[test_timezone_changes.js]
-skip-if = android_version < '19'
diff --git a/dom/system/gonk/tests/marionette/ril_jshint/README.md b/dom/system/gonk/tests/marionette/ril_jshint/README.md
deleted file mode 100644
index a63967d63..000000000
--- a/dom/system/gonk/tests/marionette/ril_jshint/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-Test RIL Code Quality
-=====================
-
-For more information, please refer to
-
-* Bug 880643 - B2G RIL: Add a code quality test on try server for RIL javascript code in gecko
-* Slide: https://speakerdeck.com/aknow/improve-code-quality-of-ril-code-by-jshint
-* Document: https://hackpad.com/Code-Quality-Test-For-RIL-Javascript-Code-In-Gecko-cz5j7YIGiw8
-
diff --git a/dom/system/gonk/tests/marionette/ril_jshint/jshint.js b/dom/system/gonk/tests/marionette/ril_jshint/jshint.js
deleted file mode 100644
index ec5263a5b..000000000
--- a/dom/system/gonk/tests/marionette/ril_jshint/jshint.js
+++ /dev/null
@@ -1,11096 +0,0 @@
-//2.1.3
-var JSHINT;
-(function () {
-var require;
-require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
-// shim for using process in browser
-
-var process = module.exports = {};
-
-process.nextTick = (function () {
- var canSetImmediate = typeof window !== 'undefined'
- && window.setImmediate;
- var canPost = typeof window !== 'undefined'
- && window.postMessage && window.addEventListener
- ;
-
- if (canSetImmediate) {
- return function (f) { return window.setImmediate(f) };
- }
-
- if (canPost) {
- var queue = [];
- window.addEventListener('message', function (ev) {
- if (ev.source === window && ev.data === 'process-tick') {
- ev.stopPropagation();
- if (queue.length > 0) {
- var fn = queue.shift();
- fn();
- }
- }
- }, true);
-
- return function nextTick(fn) {
- queue.push(fn);
- window.postMessage('process-tick', '*');
- };
- }
-
- return function nextTick(fn) {
- setTimeout(fn, 0);
- };
-})();
-
-process.title = 'browser';
-process.browser = true;
-process.env = {};
-process.argv = [];
-
-process.binding = function (name) {
- throw new Error('process.binding is not supported');
-}
-
-// TODO(shtylman)
-process.cwd = function () { return '/' };
-process.chdir = function (dir) {
- throw new Error('process.chdir is not supported');
-};
-
-},{}],2:[function(require,module,exports){
-(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
-
-var EventEmitter = exports.EventEmitter = process.EventEmitter;
-var isArray = typeof Array.isArray === 'function'
- ? Array.isArray
- : function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]'
- }
-;
-function indexOf (xs, x) {
- if (xs.indexOf) return xs.indexOf(x);
- for (var i = 0; i < xs.length; i++) {
- if (x === xs[i]) return i;
- }
- return -1;
-}
-
-// By default EventEmitters will print a warning if more than
-// 10 listeners are added to it. This is a useful default which
-// helps finding memory leaks.
-//
-// Obviously not all Emitters should be limited to 10. This function allows
-// that to be increased. Set to zero for unlimited.
-var defaultMaxListeners = 10;
-EventEmitter.prototype.setMaxListeners = function(n) {
- if (!this._events) this._events = {};
- this._events.maxListeners = n;
-};
-
-
-EventEmitter.prototype.emit = function(type) {
- // If there is no 'error' event listener then throw.
- if (type === 'error') {
- if (!this._events || !this._events.error ||
- (isArray(this._events.error) && !this._events.error.length))
- {
- if (arguments[1] instanceof Error) {
- throw arguments[1]; // Unhandled 'error' event
- } else {
- throw new Error("Uncaught, unspecified 'error' event.");
- }
- return false;
- }
- }
-
- if (!this._events) return false;
- var handler = this._events[type];
- if (!handler) return false;
-
- if (typeof handler == 'function') {
- switch (arguments.length) {
- // fast cases
- case 1:
- handler.call(this);
- break;
- case 2:
- handler.call(this, arguments[1]);
- break;
- case 3:
- handler.call(this, arguments[1], arguments[2]);
- break;
- // slower
- default:
- var args = Array.prototype.slice.call(arguments, 1);
- handler.apply(this, args);
- }
- return true;
-
- } else if (isArray(handler)) {
- var args = Array.prototype.slice.call(arguments, 1);
-
- var listeners = handler.slice();
- for (var i = 0, l = listeners.length; i < l; i++) {
- listeners[i].apply(this, args);
- }
- return true;
-
- } else {
- return false;
- }
-};
-
-// EventEmitter is defined in src/node_events.cc
-// EventEmitter.prototype.emit() is also defined there.
-EventEmitter.prototype.addListener = function(type, listener) {
- if ('function' !== typeof listener) {
- throw new Error('addListener only takes instances of Function');
- }
-
- if (!this._events) this._events = {};
-
- // To avoid recursion in the case that type == "newListeners"! Before
- // adding it to the listeners, first emit "newListeners".
- this.emit('newListener', type, listener);
-
- if (!this._events[type]) {
- // Optimize the case of one listener. Don't need the extra array object.
- this._events[type] = listener;
- } else if (isArray(this._events[type])) {
-
- // Check for listener leak
- if (!this._events[type].warned) {
- var m;
- if (this._events.maxListeners !== undefined) {
- m = this._events.maxListeners;
- } else {
- m = defaultMaxListeners;
- }
-
- if (m && m > 0 && this._events[type].length > m) {
- this._events[type].warned = true;
- console.error('(node) warning: possible EventEmitter memory ' +
- 'leak detected. %d listeners added. ' +
- 'Use emitter.setMaxListeners() to increase limit.',
- this._events[type].length);
- console.trace();
- }
- }
-
- // If we've already got an array, just append.
- this._events[type].push(listener);
- } else {
- // Adding the second element, need to change to array.
- this._events[type] = [this._events[type], listener];
- }
-
- return this;
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.once = function(type, listener) {
- var self = this;
- self.on(type, function g() {
- self.removeListener(type, g);
- listener.apply(this, arguments);
- });
-
- return this;
-};
-
-EventEmitter.prototype.removeListener = function(type, listener) {
- if ('function' !== typeof listener) {
- throw new Error('removeListener only takes instances of Function');
- }
-
- // does not use listeners(), so no side effect of creating _events[type]
- if (!this._events || !this._events[type]) return this;
-
- var list = this._events[type];
-
- if (isArray(list)) {
- var i = indexOf(list, listener);
- if (i < 0) return this;
- list.splice(i, 1);
- if (list.length == 0)
- delete this._events[type];
- } else if (this._events[type] === listener) {
- delete this._events[type];
- }
-
- return this;
-};
-
-EventEmitter.prototype.removeAllListeners = function(type) {
- if (arguments.length === 0) {
- this._events = {};
- return this;
- }
-
- // does not use listeners(), so no side effect of creating _events[type]
- if (type && this._events && this._events[type]) this._events[type] = null;
- return this;
-};
-
-EventEmitter.prototype.listeners = function(type) {
- if (!this._events) this._events = {};
- if (!this._events[type]) this._events[type] = [];
- if (!isArray(this._events[type])) {
- this._events[type] = [this._events[type]];
- }
- return this._events[type];
-};
-
-})(require("__browserify_process"))
-},{"__browserify_process":1}],3:[function(require,module,exports){
-(function(){// jshint -W001
-
-"use strict";
-
-// Identifiers provided by the ECMAScript standard.
-
-exports.reservedVars = {
- arguments : false,
- NaN : false
-};
-
-exports.ecmaIdentifiers = {
- Array : false,
- Boolean : false,
- Date : false,
- decodeURI : false,
- decodeURIComponent : false,
- encodeURI : false,
- encodeURIComponent : false,
- Error : false,
- "eval" : false,
- EvalError : false,
- Function : false,
- hasOwnProperty : false,
- isFinite : false,
- isNaN : false,
- JSON : false,
- Math : false,
- Map : false,
- Number : false,
- Object : false,
- parseInt : false,
- parseFloat : false,
- RangeError : false,
- ReferenceError : false,
- RegExp : false,
- Set : false,
- String : false,
- SyntaxError : false,
- TypeError : false,
- URIError : false,
- WeakMap : false
-};
-
-// Global variables commonly provided by a web browser environment.
-
-exports.browser = {
- ArrayBuffer : false,
- ArrayBufferView : false,
- Audio : false,
- Blob : false,
- addEventListener : false,
- applicationCache : false,
- atob : false,
- blur : false,
- btoa : false,
- clearInterval : false,
- clearTimeout : false,
- close : false,
- closed : false,
- DataView : false,
- DOMParser : false,
- defaultStatus : false,
- document : false,
- Element : false,
- ElementTimeControl : false,
- event : false,
- FileReader : false,
- Float32Array : false,
- Float64Array : false,
- FormData : false,
- focus : false,
- frames : false,
- getComputedStyle : false,
- HTMLElement : false,
- HTMLAnchorElement : false,
- HTMLBaseElement : false,
- HTMLBlockquoteElement: false,
- HTMLBodyElement : false,
- HTMLBRElement : false,
- HTMLButtonElement : false,
- HTMLCanvasElement : false,
- HTMLDirectoryElement : false,
- HTMLDivElement : false,
- HTMLDListElement : false,
- HTMLFieldSetElement : false,
- HTMLFontElement : false,
- HTMLFormElement : false,
- HTMLFrameElement : false,
- HTMLFrameSetElement : false,
- HTMLHeadElement : false,
- HTMLHeadingElement : false,
- HTMLHRElement : false,
- HTMLHtmlElement : false,
- HTMLIFrameElement : false,
- HTMLImageElement : false,
- HTMLInputElement : false,
- HTMLIsIndexElement : false,
- HTMLLabelElement : false,
- HTMLLayerElement : false,
- HTMLLegendElement : false,
- HTMLLIElement : false,
- HTMLLinkElement : false,
- HTMLMapElement : false,
- HTMLMenuElement : false,
- HTMLMetaElement : false,
- HTMLModElement : false,
- HTMLObjectElement : false,
- HTMLOListElement : false,
- HTMLOptGroupElement : false,
- HTMLOptionElement : false,
- HTMLParagraphElement : false,
- HTMLParamElement : false,
- HTMLPreElement : false,
- HTMLQuoteElement : false,
- HTMLScriptElement : false,
- HTMLSelectElement : false,
- HTMLStyleElement : false,
- HTMLTableCaptionElement: false,
- HTMLTableCellElement : false,
- HTMLTableColElement : false,
- HTMLTableElement : false,
- HTMLTableRowElement : false,
- HTMLTableSectionElement: false,
- HTMLTextAreaElement : false,
- HTMLTitleElement : false,
- HTMLUListElement : false,
- HTMLVideoElement : false,
- history : false,
- Int16Array : false,
- Int32Array : false,
- Int8Array : false,
- Image : false,
- length : false,
- localStorage : false,
- location : false,
- MessageChannel : false,
- MessageEvent : false,
- MessagePort : false,
- moveBy : false,
- moveTo : false,
- MutationObserver : false,
- name : false,
- Node : false,
- NodeFilter : false,
- navigator : false,
- onbeforeunload : true,
- onblur : true,
- onerror : true,
- onfocus : true,
- onload : true,
- onresize : true,
- onunload : true,
- open : false,
- openDatabase : false,
- opener : false,
- Option : false,
- parent : false,
- print : false,
- removeEventListener : false,
- resizeBy : false,
- resizeTo : false,
- screen : false,
- scroll : false,
- scrollBy : false,
- scrollTo : false,
- sessionStorage : false,
- setInterval : false,
- setTimeout : false,
- SharedWorker : false,
- status : false,
- SVGAElement : false,
- SVGAltGlyphDefElement: false,
- SVGAltGlyphElement : false,
- SVGAltGlyphItemElement: false,
- SVGAngle : false,
- SVGAnimateColorElement: false,
- SVGAnimateElement : false,
- SVGAnimateMotionElement: false,
- SVGAnimateTransformElement: false,
- SVGAnimatedAngle : false,
- SVGAnimatedBoolean : false,
- SVGAnimatedEnumeration: false,
- SVGAnimatedInteger : false,
- SVGAnimatedLength : false,
- SVGAnimatedLengthList: false,
- SVGAnimatedNumber : false,
- SVGAnimatedNumberList: false,
- SVGAnimatedPathData : false,
- SVGAnimatedPoints : false,
- SVGAnimatedPreserveAspectRatio: false,
- SVGAnimatedRect : false,
- SVGAnimatedString : false,
- SVGAnimatedTransformList: false,
- SVGAnimationElement : false,
- SVGCSSRule : false,
- SVGCircleElement : false,
- SVGClipPathElement : false,
- SVGColor : false,
- SVGColorProfileElement: false,
- SVGColorProfileRule : false,
- SVGComponentTransferFunctionElement: false,
- SVGCursorElement : false,
- SVGDefsElement : false,
- SVGDescElement : false,
- SVGDocument : false,
- SVGElement : false,
- SVGElementInstance : false,
- SVGElementInstanceList: false,
- SVGEllipseElement : false,
- SVGExternalResourcesRequired: false,
- SVGFEBlendElement : false,
- SVGFEColorMatrixElement: false,
- SVGFEComponentTransferElement: false,
- SVGFECompositeElement: false,
- SVGFEConvolveMatrixElement: false,
- SVGFEDiffuseLightingElement: false,
- SVGFEDisplacementMapElement: false,
- SVGFEDistantLightElement: false,
- SVGFEDropShadowElement: false,
- SVGFEFloodElement : false,
- SVGFEFuncAElement : false,
- SVGFEFuncBElement : false,
- SVGFEFuncGElement : false,
- SVGFEFuncRElement : false,
- SVGFEGaussianBlurElement: false,
- SVGFEImageElement : false,
- SVGFEMergeElement : false,
- SVGFEMergeNodeElement: false,
- SVGFEMorphologyElement: false,
- SVGFEOffsetElement : false,
- SVGFEPointLightElement: false,
- SVGFESpecularLightingElement: false,
- SVGFESpotLightElement: false,
- SVGFETileElement : false,
- SVGFETurbulenceElement: false,
- SVGFilterElement : false,
- SVGFilterPrimitiveStandardAttributes: false,
- SVGFitToViewBox : false,
- SVGFontElement : false,
- SVGFontFaceElement : false,
- SVGFontFaceFormatElement: false,
- SVGFontFaceNameElement: false,
- SVGFontFaceSrcElement: false,
- SVGFontFaceUriElement: false,
- SVGForeignObjectElement: false,
- SVGGElement : false,
- SVGGlyphElement : false,
- SVGGlyphRefElement : false,
- SVGGradientElement : false,
- SVGHKernElement : false,
- SVGICCColor : false,
- SVGImageElement : false,
- SVGLangSpace : false,
- SVGLength : false,
- SVGLengthList : false,
- SVGLineElement : false,
- SVGLinearGradientElement: false,
- SVGLocatable : false,
- SVGMPathElement : false,
- SVGMarkerElement : false,
- SVGMaskElement : false,
- SVGMatrix : false,
- SVGMetadataElement : false,
- SVGMissingGlyphElement: false,
- SVGNumber : false,
- SVGNumberList : false,
- SVGPaint : false,
- SVGPathElement : false,
- SVGPathSeg : false,
- SVGPathSegArcAbs : false,
- SVGPathSegArcRel : false,
- SVGPathSegClosePath : false,
- SVGPathSegCurvetoCubicAbs: false,
- SVGPathSegCurvetoCubicRel: false,
- SVGPathSegCurvetoCubicSmoothAbs: false,
- SVGPathSegCurvetoCubicSmoothRel: false,
- SVGPathSegCurvetoQuadraticAbs: false,
- SVGPathSegCurvetoQuadraticRel: false,
- SVGPathSegCurvetoQuadraticSmoothAbs: false,
- SVGPathSegCurvetoQuadraticSmoothRel: false,
- SVGPathSegLinetoAbs : false,
- SVGPathSegLinetoHorizontalAbs: false,
- SVGPathSegLinetoHorizontalRel: false,
- SVGPathSegLinetoRel : false,
- SVGPathSegLinetoVerticalAbs: false,
- SVGPathSegLinetoVerticalRel: false,
- SVGPathSegList : false,
- SVGPathSegMovetoAbs : false,
- SVGPathSegMovetoRel : false,
- SVGPatternElement : false,
- SVGPoint : false,
- SVGPointList : false,
- SVGPolygonElement : false,
- SVGPolylineElement : false,
- SVGPreserveAspectRatio: false,
- SVGRadialGradientElement: false,
- SVGRect : false,
- SVGRectElement : false,
- SVGRenderingIntent : false,
- SVGSVGElement : false,
- SVGScriptElement : false,
- SVGSetElement : false,
- SVGStopElement : false,
- SVGStringList : false,
- SVGStylable : false,
- SVGStyleElement : false,
- SVGSwitchElement : false,
- SVGSymbolElement : false,
- SVGTRefElement : false,
- SVGTSpanElement : false,
- SVGTests : false,
- SVGTextContentElement: false,
- SVGTextElement : false,
- SVGTextPathElement : false,
- SVGTextPositioningElement: false,
- SVGTitleElement : false,
- SVGTransform : false,
- SVGTransformList : false,
- SVGTransformable : false,
- SVGURIReference : false,
- SVGUnitTypes : false,
- SVGUseElement : false,
- SVGVKernElement : false,
- SVGViewElement : false,
- SVGViewSpec : false,
- SVGZoomAndPan : false,
- TimeEvent : false,
- top : false,
- Uint16Array : false,
- Uint32Array : false,
- Uint8Array : false,
- Uint8ClampedArray : false,
- WebSocket : false,
- window : false,
- Worker : false,
- XMLHttpRequest : false,
- XMLSerializer : false,
- XPathEvaluator : false,
- XPathException : false,
- XPathExpression : false,
- XPathNSResolver : false,
- XPathResult : false
-};
-
-exports.devel = {
- alert : false,
- confirm: false,
- console: false,
- Debug : false,
- opera : false,
- prompt : false
-};
-
-exports.worker = {
- importScripts: true,
- postMessage : true,
- self : true
-};
-
-// Widely adopted global names that are not part of ECMAScript standard
-exports.nonstandard = {
- escape : false,
- unescape: false
-};
-
-// Globals provided by popular JavaScript environments.
-
-exports.couch = {
- "require" : false,
- respond : false,
- getRow : false,
- emit : false,
- send : false,
- start : false,
- sum : false,
- log : false,
- exports : false,
- module : false,
- provides : false
-};
-
-exports.node = {
- __filename : false,
- __dirname : false,
- Buffer : false,
- DataView : false,
- console : false,
- exports : true, // In Node it is ok to exports = module.exports = foo();
- GLOBAL : false,
- global : false,
- module : false,
- process : false,
- require : false,
- setTimeout : false,
- clearTimeout : false,
- setInterval : false,
- clearInterval : false,
- setImmediate : false, // v0.9.1+
- clearImmediate: false // v0.9.1+
-};
-
-exports.phantom = {
- phantom : true,
- require : true,
- WebPage : true
-};
-
-exports.rhino = {
- defineClass : false,
- deserialize : false,
- gc : false,
- help : false,
- importPackage: false,
- "java" : false,
- load : false,
- loadClass : false,
- print : false,
- quit : false,
- readFile : false,
- readUrl : false,
- runCommand : false,
- seal : false,
- serialize : false,
- spawn : false,
- sync : false,
- toint32 : false,
- version : false
-};
-
-exports.wsh = {
- ActiveXObject : true,
- Enumerator : true,
- GetObject : true,
- ScriptEngine : true,
- ScriptEngineBuildVersion : true,
- ScriptEngineMajorVersion : true,
- ScriptEngineMinorVersion : true,
- VBArray : true,
- WSH : true,
- WScript : true,
- XDomainRequest : true
-};
-
-// Globals provided by popular JavaScript libraries.
-
-exports.dojo = {
- dojo : false,
- dijit : false,
- dojox : false,
- define : false,
- "require": false
-};
-
-exports.jquery = {
- "$" : false,
- jQuery : false
-};
-
-exports.mootools = {
- "$" : false,
- "$$" : false,
- Asset : false,
- Browser : false,
- Chain : false,
- Class : false,
- Color : false,
- Cookie : false,
- Core : false,
- Document : false,
- DomReady : false,
- DOMEvent : false,
- DOMReady : false,
- Drag : false,
- Element : false,
- Elements : false,
- Event : false,
- Events : false,
- Fx : false,
- Group : false,
- Hash : false,
- HtmlTable : false,
- Iframe : false,
- IframeShim : false,
- InputValidator: false,
- instanceOf : false,
- Keyboard : false,
- Locale : false,
- Mask : false,
- MooTools : false,
- Native : false,
- Options : false,
- OverText : false,
- Request : false,
- Scroller : false,
- Slick : false,
- Slider : false,
- Sortables : false,
- Spinner : false,
- Swiff : false,
- Tips : false,
- Type : false,
- typeOf : false,
- URI : false,
- Window : false
-};
-
-exports.prototypejs = {
- "$" : false,
- "$$" : false,
- "$A" : false,
- "$F" : false,
- "$H" : false,
- "$R" : false,
- "$break" : false,
- "$continue" : false,
- "$w" : false,
- Abstract : false,
- Ajax : false,
- Class : false,
- Enumerable : false,
- Element : false,
- Event : false,
- Field : false,
- Form : false,
- Hash : false,
- Insertion : false,
- ObjectRange : false,
- PeriodicalExecuter: false,
- Position : false,
- Prototype : false,
- Selector : false,
- Template : false,
- Toggle : false,
- Try : false,
- Autocompleter : false,
- Builder : false,
- Control : false,
- Draggable : false,
- Draggables : false,
- Droppables : false,
- Effect : false,
- Sortable : false,
- SortableObserver : false,
- Sound : false,
- Scriptaculous : false
-};
-
-exports.yui = {
- YUI : false,
- Y : false,
- YUI_config: false
-};
-
-
-})()
-},{}],4:[function(require,module,exports){
-"use strict";
-
-var state = {
- syntax: {},
-
- reset: function () {
- this.tokens = {
- prev: null,
- next: null,
- curr: null
- };
-
- this.option = {};
- this.ignored = {};
- this.directive = {};
- this.jsonMode = false;
- this.jsonWarnings = [];
- this.lines = [];
- this.tab = "";
- this.cache = {}; // Node.JS doesn't have Map. Sniff.
- }
-};
-
-exports.state = state;
-
-},{}],5:[function(require,module,exports){
-(function(){"use strict";
-
-exports.register = function (linter) {
- // Check for properties named __proto__. This special property was
- // deprecated and then re-introduced for ES6.
-
- linter.on("Identifier", function style_scanProto(data) {
- if (linter.getOption("proto")) {
- return;
- }
-
- if (data.name === "__proto__") {
- linter.warn("W103", {
- line: data.line,
- char: data.char,
- data: [ data.name ]
- });
- }
- });
-
- // Check for properties named __iterator__. This is a special property
- // available only in browsers with JavaScript 1.7 implementation.
-
- linter.on("Identifier", function style_scanIterator(data) {
- if (linter.getOption("iterator")) {
- return;
- }
-
- if (data.name === "__iterator__") {
- linter.warn("W104", {
- line: data.line,
- char: data.char,
- data: [ data.name ]
- });
- }
- });
-
- // Check for dangling underscores.
-
- linter.on("Identifier", function style_scanDangling(data) {
- if (!linter.getOption("nomen")) {
- return;
- }
-
- // Underscore.js
- if (data.name === "_") {
- return;
- }
-
- // In Node, __dirname and __filename should be ignored.
- if (linter.getOption("node")) {
- if (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) {
- return;
- }
- }
-
- if (/^(_+.*|.*_+)$/.test(data.name)) {
- linter.warn("W105", {
- line: data.line,
- char: data.from,
- data: [ "dangling '_'", data.name ]
- });
- }
- });
-
- // Check that all identifiers are using camelCase notation.
- // Exceptions: names like MY_VAR and _myVar.
-
- linter.on("Identifier", function style_scanCamelCase(data) {
- if (!linter.getOption("camelcase")) {
- return;
- }
-
- if (data.name.replace(/^_+/, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
- linter.warn("W106", {
- line: data.line,
- char: data.from,
- data: [ data.name ]
- });
- }
- });
-
- // Enforce consistency in style of quoting.
-
- linter.on("String", function style_scanQuotes(data) {
- var quotmark = linter.getOption("quotmark");
- var code;
-
- if (!quotmark) {
- return;
- }
-
- // If quotmark is set to 'single' warn about all double-quotes.
-
- if (quotmark === "single" && data.quote !== "'") {
- code = "W109";
- }
-
- // If quotmark is set to 'double' warn about all single-quotes.
-
- if (quotmark === "double" && data.quote !== "\"") {
- code = "W108";
- }
-
- // If quotmark is set to true, remember the first quotation style
- // and then warn about all others.
-
- if (quotmark === true) {
- if (!linter.getCache("quotmark")) {
- linter.setCache("quotmark", data.quote);
- }
-
- if (linter.getCache("quotmark") !== data.quote) {
- code = "W110";
- }
- }
-
- if (code) {
- linter.warn(code, {
- line: data.line,
- char: data.char,
- });
- }
- });
-
- linter.on("Number", function style_scanNumbers(data) {
- if (data.value.charAt(0) === ".") {
- // Warn about a leading decimal point.
- linter.warn("W008", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
-
- if (data.value.substr(data.value.length - 1) === ".") {
- // Warn about a trailing decimal point.
- linter.warn("W047", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
-
- if (/^00+/.test(data.value)) {
- // Multiple leading zeroes.
- linter.warn("W046", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
- });
-
- // Warn about script URLs.
-
- linter.on("String", function style_scanJavaScriptURLs(data) {
- var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
-
- if (linter.getOption("scripturl")) {
- return;
- }
-
- if (re.test(data.value)) {
- linter.warn("W107", {
- line: data.line,
- char: data.char
- });
- }
- });
-};
-})()
-},{}],6:[function(require,module,exports){
-/*
- * Regular expressions. Some of these are stupidly long.
- */
-
-/*jshint maxlen:1000 */
-
-"use string";
-
-// Unsafe comment or string (ax)
-exports.unsafeString =
- /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
-
-// Unsafe characters that are silently deleted by one or more browsers (cx)
-exports.unsafeChars =
- /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
-
-// Characters in strings that need escaping (nx and nxg)
-exports.needEsc =
- /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
-
-exports.needEscGlobal =
- /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
-
-// Star slash (lx)
-exports.starSlash = /\*\//;
-
-// Identifier (ix)
-exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
-
-// JavaScript URL (jx)
-exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
-
-// Catches /* falls through */ comments (ft)
-//exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
-exports.fallsThrough = /^\s*\/\/\s*Falls?\sthrough.*\s*$/;
-
-},{}],7:[function(require,module,exports){
-(function(global){/*global window, global*/
-var util = require("util")
-var assert = require("assert")
-
-var slice = Array.prototype.slice
-var console
-var times = {}
-
-if (typeof global !== "undefined" && global.console) {
- console = global.console
-} else if (typeof window !== "undefined" && window.console) {
- console = window.console
-} else {
- console = window.console = {}
-}
-
-var functions = [
- [log, "log"]
- , [info, "info"]
- , [warn, "warn"]
- , [error, "error"]
- , [time, "time"]
- , [timeEnd, "timeEnd"]
- , [trace, "trace"]
- , [dir, "dir"]
- , [assert, "assert"]
-]
-
-for (var i = 0; i < functions.length; i++) {
- var tuple = functions[i]
- var f = tuple[0]
- var name = tuple[1]
-
- if (!console[name]) {
- console[name] = f
- }
-}
-
-module.exports = console
-
-function log() {}
-
-function info() {
- console.log.apply(console, arguments)
-}
-
-function warn() {
- console.log.apply(console, arguments)
-}
-
-function error() {
- console.warn.apply(console, arguments)
-}
-
-function time(label) {
- times[label] = Date.now()
-}
-
-function timeEnd(label) {
- var time = times[label]
- if (!time) {
- throw new Error("No such label: " + label)
- }
-
- var duration = Date.now() - time
- console.log(label + ": " + duration + "ms")
-}
-
-function trace() {
- var err = new Error()
- err.name = "Trace"
- err.message = util.format.apply(null, arguments)
- console.error(err.stack)
-}
-
-function dir(object) {
- console.log(util.inspect(object) + "\n")
-}
-
-function assert(expression) {
- if (!expression) {
- var arr = slice.call(arguments, 1)
- assert.ok(false, util.format.apply(null, arr))
- }
-}
-
-})(window)
-},{"util":8,"assert":9}],10:[function(require,module,exports){
-(function(){/*
- * Lexical analysis and token construction.
- */
-
-"use strict";
-
-var _ = require("underscore");
-var events = require("events");
-var reg = require("./reg.js");
-var state = require("./state.js").state;
-
-// Some of these token types are from JavaScript Parser API
-// while others are specific to JSHint parser.
-// JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
-
-var Token = {
- Identifier: 1,
- Punctuator: 2,
- NumericLiteral: 3,
- StringLiteral: 4,
- Comment: 5,
- Keyword: 6,
- NullLiteral: 7,
- BooleanLiteral: 8,
- RegExp: 9
-};
-
-// This is auto generated from the unicode tables.
-// The tables are at:
-// http://www.fileformat.info/info/unicode/category/Lu/list.htm
-// http://www.fileformat.info/info/unicode/category/Ll/list.htm
-// http://www.fileformat.info/info/unicode/category/Lt/list.htm
-// http://www.fileformat.info/info/unicode/category/Lm/list.htm
-// http://www.fileformat.info/info/unicode/category/Lo/list.htm
-// http://www.fileformat.info/info/unicode/category/Nl/list.htm
-
-var unicodeLetterTable = [
- 170, 170, 181, 181, 186, 186, 192, 214,
- 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,
- 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,
- 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,
- 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,
- 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,
- 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,
- 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,
- 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,
- 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,
- 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,
- 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,
- 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,
- 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,
- 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,
- 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,
- 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,
- 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,
- 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,
- 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,
- 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,
- 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,
- 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,
- 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,
- 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,
- 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,
- 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,
- 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
- 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,
- 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,
- 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,
- 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,
- 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,
- 4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,
- 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,
- 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,
- 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,
- 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,
- 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,
- 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,
- 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,
- 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,
- 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,
- 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,
- 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,
- 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,
- 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,
- 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,
- 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,
- 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,
- 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
- 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,
- 11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,
- 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,
- 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,
- 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,
- 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,
- 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,
- 12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,
- 19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,
- 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,
- 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,
- 42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,
- 43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,
- 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,
- 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,
- 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,
- 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,
- 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,
- 43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,
- 43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,
- 55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,
- 64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,
- 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,
- 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,
- 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,
- 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,
- 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,
- 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,
- 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,
- 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,
- 66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,
- 66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,
- 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,
- 67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,
- 68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,
- 68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,
- 69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,
- 92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,
- 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,
- 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,
- 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,
- 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,
- 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,
- 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,
- 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,
- 131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,
- 177984, 177984, 178205, 178205, 194560, 195101
-];
-
-var identifierStartTable = [];
-
-for (var i = 0; i < 128; i++) {
- identifierStartTable[i] =
- i === 36 || // $
- i >= 65 && i <= 90 || // A-Z
- i === 95 || // _
- i >= 97 && i <= 122; // a-z
-}
-
-var identifierPartTable = [];
-
-for (var i = 0; i < 128; i++) {
- identifierPartTable[i] =
- identifierStartTable[i] || // $, _, A-Z, a-z
- i >= 48 && i <= 57; // 0-9
-}
-
-// Object that handles postponed lexing verifications that checks the parsed
-// environment state.
-
-function asyncTrigger() {
- var _checks = [];
-
- return {
- push: function (fn) {
- _checks.push(fn);
- },
-
- check: function () {
- for (var check in _checks) {
- _checks[check]();
- }
-
- _checks.splice(0, _checks.length);
- }
- };
-}
-
-/*
- * Lexer for JSHint.
- *
- * This object does a char-by-char scan of the provided source code
- * and produces a sequence of tokens.
- *
- * var lex = new Lexer("var i = 0;");
- * lex.start();
- * lex.token(); // returns the next token
- *
- * You have to use the token() method to move the lexer forward
- * but you don't have to use its return value to get tokens. In addition
- * to token() method returning the next token, the Lexer object also
- * emits events.
- *
- * lex.on("Identifier", function (data) {
- * if (data.name.indexOf("_") >= 0) {
- * // Produce a warning.
- * }
- * });
- *
- * Note that the token() method returns tokens in a JSLint-compatible
- * format while the event emitter uses a slightly modified version of
- * Mozilla's JavaScript Parser API. Eventually, we will move away from
- * JSLint format.
- */
-function Lexer(source) {
- var lines = source;
-
- if (typeof lines === "string") {
- lines = lines
- .replace(/\r\n/g, "\n")
- .replace(/\r/g, "\n")
- .split("\n");
- }
-
- // If the first line is a shebang (#!), make it a blank and move on.
- // Shebangs are used by Node scripts.
-
- if (lines[0] && lines[0].substr(0, 2) === "#!") {
- lines[0] = "";
- }
-
- this.emitter = new events.EventEmitter();
- this.source = source;
- this.lines = lines;
- this.prereg = true;
-
- this.line = 0;
- this.char = 1;
- this.from = 1;
- this.input = "";
-
- for (var i = 0; i < state.option.indent; i += 1) {
- state.tab += " ";
- }
-}
-
-Lexer.prototype = {
- _lines: [],
-
- get lines() {
- this._lines = state.lines;
- return this._lines;
- },
-
- set lines(val) {
- this._lines = val;
- state.lines = this._lines;
- },
-
- /*
- * Return the next i character without actually moving the
- * char pointer.
- */
- peek: function (i) {
- return this.input.charAt(i || 0);
- },
-
- /*
- * Move the char pointer forward i times.
- */
- skip: function (i) {
- i = i || 1;
- this.char += i;
- this.input = this.input.slice(i);
- },
-
- /*
- * Subscribe to a token event. The API for this method is similar
- * Underscore.js i.e. you can subscribe to multiple events with
- * one call:
- *
- * lex.on("Identifier Number", function (data) {
- * // ...
- * });
- */
- on: function (names, listener) {
- names.split(" ").forEach(function (name) {
- this.emitter.on(name, listener);
- }.bind(this));
- },
-
- /*
- * Trigger a token event. All arguments will be passed to each
- * listener.
- */
- trigger: function () {
- this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
- },
-
- /*
- * Postpone a token event. the checking condition is set as
- * last parameter, and the trigger function is called in a
- * stored callback. To be later called using the check() function
- * by the parser. This avoids parser's peek() to give the lexer
- * a false context.
- */
- triggerAsync: function (type, args, checks, fn) {
- checks.push(function () {
- if (fn()) {
- this.trigger(type, args);
- }
- }.bind(this));
- },
-
- /*
- * Extract a punctuator out of the next sequence of characters
- * or return 'null' if its not possible.
- *
- * This method's implementation was heavily influenced by the
- * scanPunctuator function in the Esprima parser's source code.
- */
- scanPunctuator: function () {
- var ch1 = this.peek();
- var ch2, ch3, ch4;
-
- switch (ch1) {
- // Most common single-character punctuators
- case ".":
- if ((/^[0-9]$/).test(this.peek(1))) {
- return null;
- }
- if (this.peek(1) === "." && this.peek(2) === ".") {
- return {
- type: Token.Punctuator,
- value: "..."
- };
- }
- /* falls through */
- case "(":
- case ")":
- case ";":
- case ",":
- case "{":
- case "}":
- case "[":
- case "]":
- case ":":
- case "~":
- case "?":
- return {
- type: Token.Punctuator,
- value: ch1
- };
-
- // A pound sign (for Node shebangs)
- case "#":
- return {
- type: Token.Punctuator,
- value: ch1
- };
-
- // We're at the end of input
- case "":
- return null;
- }
-
- // Peek more characters
-
- ch2 = this.peek(1);
- ch3 = this.peek(2);
- ch4 = this.peek(3);
-
- // 4-character punctuator: >>>=
-
- if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
- return {
- type: Token.Punctuator,
- value: ">>>="
- };
- }
-
- // 3-character punctuators: === !== >>> <<= >>=
-
- if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "==="
- };
- }
-
- if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "!=="
- };
- }
-
- if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
- return {
- type: Token.Punctuator,
- value: ">>>"
- };
- }
-
- if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "<<="
- };
- }
-
- if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: ">>="
- };
- }
-
- // Fat arrow punctuator
- if (ch1 === "=" && ch2 === ">") {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
-
- // 2-character punctuators: <= >= == != ++ -- << >> && ||
- // += -= *= %= &= |= ^= (but not /=, see below)
- if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
-
- if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
- if (ch2 === "=") {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
-
- return {
- type: Token.Punctuator,
- value: ch1
- };
- }
-
- // Special case: /=. We need to make sure that this is an
- // operator and not a regular expression.
-
- if (ch1 === "/") {
- if (ch2 === "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input)) {
- // /= is not a part of a regular expression, return it as a
- // punctuator.
- return {
- type: Token.Punctuator,
- value: "/="
- };
- }
-
- return {
- type: Token.Punctuator,
- value: "/"
- };
- }
-
- return null;
- },
-
- /*
- * Extract a comment out of the next sequence of characters and/or
- * lines or return 'null' if its not possible. Since comments can
- * span across multiple lines this method has to move the char
- * pointer.
- *
- * In addition to normal JavaScript comments (// and /*) this method
- * also recognizes JSHint- and JSLint-specific comments such as
- * /*jshint, /*jslint, /*globals and so on.
- */
- scanComments: function () {
- var ch1 = this.peek();
- var ch2 = this.peek(1);
- var rest = this.input.substr(2);
- var startLine = this.line;
- var startChar = this.char;
-
- // Create a comment token object and make sure it
- // has all the data JSHint needs to work with special
- // comments.
-
- function commentToken(label, body, opt) {
- var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
- var isSpecial = false;
- var value = label + body;
- var commentType = "plain";
- opt = opt || {};
-
- if (opt.isMultiline) {
- value += "*/";
- }
-
- special.forEach(function (str) {
- if (isSpecial) {
- return;
- }
-
- // Don't recognize any special comments other than jshint for single-line
- // comments. This introduced many problems with legit comments.
- if (label === "//" && str !== "jshint") {
- return;
- }
-
- if (body.substr(0, str.length) === str) {
- isSpecial = true;
- label = label + str;
- body = body.substr(str.length);
- }
-
- if (!isSpecial && body.charAt(0) === " " && body.substr(1, str.length) === str) {
- isSpecial = true;
- label = label + " " + str;
- body = body.substr(str.length + 1);
- }
-
- if (!isSpecial) {
- return;
- }
-
- switch (str) {
- case "member":
- commentType = "members";
- break;
- case "global":
- commentType = "globals";
- break;
- default:
- commentType = str;
- }
- });
-
- return {
- type: Token.Comment,
- commentType: commentType,
- value: value,
- body: body,
- isSpecial: isSpecial,
- isMultiline: opt.isMultiline || false,
- isMalformed: opt.isMalformed || false
- };
- }
-
- // End of unbegun comment. Raise an error and skip that input.
- if (ch1 === "*" && ch2 === "/") {
- this.trigger("error", {
- code: "E018",
- line: startLine,
- character: startChar
- });
-
- this.skip(2);
- return null;
- }
-
- // Comments must start either with // or /*
- if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
- return null;
- }
-
- // One-line comment
- if (ch2 === "/") {
- this.skip(this.input.length); // Skip to the EOL.
- return commentToken("//", rest);
- }
-
- var body = "";
-
- /* Multi-line comment */
- if (ch2 === "*") {
- this.skip(2);
-
- while (this.peek() !== "*" || this.peek(1) !== "/") {
- if (this.peek() === "") { // End of Line
- body += "\n";
-
- // If we hit EOF and our comment is still unclosed,
- // trigger an error and end the comment implicitly.
- if (!this.nextLine()) {
- this.trigger("error", {
- code: "E017",
- line: startLine,
- character: startChar
- });
-
- return commentToken("/*", body, {
- isMultiline: true,
- isMalformed: true
- });
- }
- } else {
- body += this.peek();
- this.skip();
- }
- }
-
- this.skip(2);
- return commentToken("/*", body, { isMultiline: true });
- }
- },
-
- /*
- * Extract a keyword out of the next sequence of characters or
- * return 'null' if its not possible.
- */
- scanKeyword: function () {
- var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
- var keywords = [
- "if", "in", "do", "var", "for", "new",
- "try", "let", "this", "else", "case",
- "void", "with", "enum", "while", "break",
- "catch", "throw", "const", "yield", "class",
- "super", "return", "typeof", "delete",
- "switch", "export", "import", "default",
- "finally", "extends", "function", "continue",
- "debugger", "instanceof"
- ];
-
- if (result && keywords.indexOf(result[0]) >= 0) {
- return {
- type: Token.Keyword,
- value: result[0]
- };
- }
-
- return null;
- },
-
- /*
- * Extract a JavaScript identifier out of the next sequence of
- * characters or return 'null' if its not possible. In addition,
- * to Identifier this method can also produce BooleanLiteral
- * (true/false) and NullLiteral (null).
- */
- scanIdentifier: function () {
- var id = "";
- var index = 0;
- var type, char;
-
- // Detects any character in the Unicode categories "Uppercase
- // letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter
- // (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or
- // "Letter number (Nl)".
- //
- // Both approach and unicodeLetterTable were borrowed from
- // Google's Traceur.
-
- function isUnicodeLetter(code) {
- for (var i = 0; i < unicodeLetterTable.length;) {
- if (code < unicodeLetterTable[i++]) {
- return false;
- }
-
- if (code <= unicodeLetterTable[i++]) {
- return true;
- }
- }
-
- return false;
- }
-
- function isHexDigit(str) {
- return (/^[0-9a-fA-F]$/).test(str);
- }
-
- var readUnicodeEscapeSequence = function () {
- /*jshint validthis:true */
- index += 1;
-
- if (this.peek(index) !== "u") {
- return null;
- }
-
- var ch1 = this.peek(index + 1);
- var ch2 = this.peek(index + 2);
- var ch3 = this.peek(index + 3);
- var ch4 = this.peek(index + 4);
- var code;
-
- if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
- code = parseInt(ch1 + ch2 + ch3 + ch4, 16);
-
- if (isUnicodeLetter(code)) {
- index += 5;
- return "\\u" + ch1 + ch2 + ch3 + ch4;
- }
-
- return null;
- }
-
- return null;
- }.bind(this);
-
- var getIdentifierStart = function () {
- /*jshint validthis:true */
- var chr = this.peek(index);
- var code = chr.charCodeAt(0);
-
- if (code === 92) {
- return readUnicodeEscapeSequence();
- }
-
- if (code < 128) {
- if (identifierStartTable[code]) {
- index += 1;
- return chr;
- }
-
- return null;
- }
-
- if (isUnicodeLetter(code)) {
- index += 1;
- return chr;
- }
-
- return null;
- }.bind(this);
-
- var getIdentifierPart = function () {
- /*jshint validthis:true */
- var chr = this.peek(index);
- var code = chr.charCodeAt(0);
-
- if (code === 92) {
- return readUnicodeEscapeSequence();
- }
-
- if (code < 128) {
- if (identifierPartTable[code]) {
- index += 1;
- return chr;
- }
-
- return null;
- }
-
- if (isUnicodeLetter(code)) {
- index += 1;
- return chr;
- }
-
- return null;
- }.bind(this);
-
- char = getIdentifierStart();
- if (char === null) {
- return null;
- }
-
- id = char;
- for (;;) {
- char = getIdentifierPart();
-
- if (char === null) {
- break;
- }
-
- id += char;
- }
-
- switch (id) {
- case "true":
- case "false":
- type = Token.BooleanLiteral;
- break;
- case "null":
- type = Token.NullLiteral;
- break;
- default:
- type = Token.Identifier;
- }
-
- return {
- type: type,
- value: id
- };
- },
-
- /*
- * Extract a numeric literal out of the next sequence of
- * characters or return 'null' if its not possible. This method
- * supports all numeric literals described in section 7.8.3
- * of the EcmaScript 5 specification.
- *
- * This method's implementation was heavily influenced by the
- * scanNumericLiteral function in the Esprima parser's source code.
- */
- scanNumericLiteral: function () {
- var index = 0;
- var value = "";
- var length = this.input.length;
- var char = this.peek(index);
- var bad;
-
- function isDecimalDigit(str) {
- return (/^[0-9]$/).test(str);
- }
-
- function isOctalDigit(str) {
- return (/^[0-7]$/).test(str);
- }
-
- function isHexDigit(str) {
- return (/^[0-9a-fA-F]$/).test(str);
- }
-
- function isIdentifierStart(ch) {
- return (ch === "$") || (ch === "_") || (ch === "\\") ||
- (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
- }
-
- // Numbers must start either with a decimal digit or a point.
-
- if (char !== "." && !isDecimalDigit(char)) {
- return null;
- }
-
- if (char !== ".") {
- value = this.peek(index);
- index += 1;
- char = this.peek(index);
-
- if (value === "0") {
- // Base-16 numbers.
- if (char === "x" || char === "X") {
- index += 1;
- value += char;
-
- while (index < length) {
- char = this.peek(index);
- if (!isHexDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
-
- if (value.length <= 2) { // 0x
- return {
- type: Token.NumericLiteral,
- value: value,
- isMalformed: true
- };
- }
-
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
-
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 16,
- isMalformed: false
- };
- }
-
- // Base-8 numbers.
- if (isOctalDigit(char)) {
- index += 1;
- value += char;
- bad = false;
-
- while (index < length) {
- char = this.peek(index);
-
- // Numbers like '019' (note the 9) are not valid octals
- // but we still parse them and mark as malformed.
-
- if (isDecimalDigit(char)) {
- bad = true;
- } else if (!isOctalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
-
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
-
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 8,
- isMalformed: false
- };
- }
-
- // Decimal numbers that start with '0' such as '09' are illegal
- // but we still parse them and return as malformed.
-
- if (isDecimalDigit(char)) {
- index += 1;
- value += char;
- }
- }
-
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- }
-
- // Decimal digits.
-
- if (char === ".") {
- value += char;
- index += 1;
-
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- }
-
- // Exponent part.
-
- if (char === "e" || char === "E") {
- value += char;
- index += 1;
- char = this.peek(index);
-
- if (char === "+" || char === "-") {
- value += this.peek(index);
- index += 1;
- }
-
- char = this.peek(index);
- if (isDecimalDigit(char)) {
- value += char;
- index += 1;
-
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- } else {
- return null;
- }
- }
-
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
-
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 10,
- isMalformed: !isFinite(value)
- };
- },
-
- /*
- * Extract a string out of the next sequence of characters and/or
- * lines or return 'null' if its not possible. Since strings can
- * span across multiple lines this method has to move the char
- * pointer.
- *
- * This method recognizes pseudo-multiline JavaScript strings:
- *
- * var str = "hello\
- * world";
- */
- scanStringLiteral: function (checks) {
- /*jshint loopfunc:true */
- var quote = this.peek();
-
- // String must start with a quote.
- if (quote !== "\"" && quote !== "'") {
- return null;
- }
-
- // In JSON strings must always use double quotes.
- this.triggerAsync("warning", {
- code: "W108",
- line: this.line,
- character: this.char // +1?
- }, checks, function () { return state.jsonMode && quote !== "\""; });
-
- var value = "";
- var startLine = this.line;
- var startChar = this.char;
- var allowNewLine = false;
-
- this.skip();
-
- while (this.peek() !== quote) {
- while (this.peek() === "") { // End Of Line
-
- // If an EOL is not preceded by a backslash, show a warning
- // and proceed like it was a legit multi-line string where
- // author simply forgot to escape the newline symbol.
- //
- // Another approach is to implicitly close a string on EOL
- // but it generates too many false positives.
-
- if (!allowNewLine) {
- this.trigger("warning", {
- code: "W112",
- line: this.line,
- character: this.char
- });
- } else {
- allowNewLine = false;
-
- // Otherwise show a warning if multistr option was not set.
- // For JSON, show warning no matter what.
-
- this.triggerAsync("warning", {
- code: "W043",
- line: this.line,
- character: this.char
- }, checks, function () { return !state.option.multistr; });
-
- this.triggerAsync("warning", {
- code: "W042",
- line: this.line,
- character: this.char
- }, checks, function () { return state.jsonMode && state.option.multistr; });
- }
-
- // If we get an EOF inside of an unclosed string, show an
- // error and implicitly close it at the EOF point.
-
- if (!this.nextLine()) {
- this.trigger("error", {
- code: "E029",
- line: startLine,
- character: startChar
- });
-
- return {
- type: Token.StringLiteral,
- value: value,
- isUnclosed: true,
- quote: quote
- };
- }
- }
-
- allowNewLine = false;
- var char = this.peek();
- var jump = 1; // A length of a jump, after we're done
- // parsing this character.
-
- if (char < " ") {
- // Warn about a control character in a string.
- this.trigger("warning", {
- code: "W113",
- line: this.line,
- character: this.char,
- data: [ "<non-printable>" ]
- });
- }
-
- // Special treatment for some escaped characters.
-
- if (char === "\\") {
- this.skip();
- char = this.peek();
-
- switch (char) {
- case "'":
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\'" ]
- }, checks, function () {return state.jsonMode; });
- break;
- case "b":
- char = "\b";
- break;
- case "f":
- char = "\f";
- break;
- case "n":
- char = "\n";
- break;
- case "r":
- char = "\r";
- break;
- case "t":
- char = "\t";
- break;
- case "0":
- char = "\0";
-
- // Octal literals fail in strict mode.
- // Check if the number is between 00 and 07.
- var n = parseInt(this.peek(1), 10);
- this.triggerAsync("warning", {
- code: "W115",
- line: this.line,
- character: this.char
- }, checks,
- function () { return n >= 0 && n <= 7 && state.directive["use strict"]; });
- break;
- case "u":
- char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));
- jump = 5;
- break;
- case "v":
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\v" ]
- }, checks, function () { return state.jsonMode; });
-
- char = "\v";
- break;
- case "x":
- var x = parseInt(this.input.substr(1, 2), 16);
-
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\x-" ]
- }, checks, function () { return state.jsonMode; });
-
- char = String.fromCharCode(x);
- jump = 3;
- break;
- case "\\":
- case "\"":
- case "/":
- break;
- case "":
- allowNewLine = true;
- char = "";
- break;
- case "!":
- if (value.slice(value.length - 2) === "<") {
- break;
- }
-
- /*falls through */
- default:
- // Weird escaping.
- this.trigger("warning", {
- code: "W044",
- line: this.line,
- character: this.char
- });
- }
- }
-
- value += char;
- this.skip(jump);
- }
-
- this.skip();
- return {
- type: Token.StringLiteral,
- value: value,
- isUnclosed: false,
- quote: quote
- };
- },
-
- /*
- * Extract a regular expression out of the next sequence of
- * characters and/or lines or return 'null' if its not possible.
- *
- * This method is platform dependent: it accepts almost any
- * regular expression values but then tries to compile and run
- * them using system's RegExp object. This means that there are
- * rare edge cases where one JavaScript engine complains about
- * your regular expression while others don't.
- */
- scanRegExp: function () {
- var index = 0;
- var length = this.input.length;
- var char = this.peek();
- var value = char;
- var body = "";
- var flags = [];
- var malformed = false;
- var isCharSet = false;
- var terminated;
-
- var scanUnexpectedChars = function () {
- // Unexpected control character
- if (char < " ") {
- malformed = true;
- this.trigger("warning", {
- code: "W048",
- line: this.line,
- character: this.char
- });
- }
-
- // Unexpected escaped character
- if (char === "<") {
- malformed = true;
- this.trigger("warning", {
- code: "W049",
- line: this.line,
- character: this.char,
- data: [ char ]
- });
- }
- }.bind(this);
-
- // Regular expressions must start with '/'
- if (!this.prereg || char !== "/") {
- return null;
- }
-
- index += 1;
- terminated = false;
-
- // Try to get everything in between slashes. A couple of
- // cases aside (see scanUnexpectedChars) we don't really
- // care whether the resulting expression is valid or not.
- // We will check that later using the RegExp object.
-
- while (index < length) {
- char = this.peek(index);
- value += char;
- body += char;
-
- if (isCharSet) {
- if (char === "]") {
- if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
- isCharSet = false;
- }
- }
-
- if (char === "\\") {
- index += 1;
- char = this.peek(index);
- body += char;
- value += char;
-
- scanUnexpectedChars();
- }
-
- index += 1;
- continue;
- }
-
- if (char === "\\") {
- index += 1;
- char = this.peek(index);
- body += char;
- value += char;
-
- scanUnexpectedChars();
-
- if (char === "/") {
- index += 1;
- continue;
- }
-
- if (char === "[") {
- index += 1;
- continue;
- }
- }
-
- if (char === "[") {
- isCharSet = true;
- index += 1;
- continue;
- }
-
- if (char === "/") {
- body = body.substr(0, body.length - 1);
- terminated = true;
- index += 1;
- break;
- }
-
- index += 1;
- }
-
- // A regular expression that was never closed is an
- // error from which we cannot recover.
-
- if (!terminated) {
- this.trigger("error", {
- code: "E015",
- line: this.line,
- character: this.from
- });
-
- return void this.trigger("fatal", {
- line: this.line,
- from: this.from
- });
- }
-
- // Parse flags (if any).
-
- while (index < length) {
- char = this.peek(index);
- if (!/[gim]/.test(char)) {
- break;
- }
- flags.push(char);
- value += char;
- index += 1;
- }
-
- // Check regular expression for correctness.
-
- try {
- new RegExp(body, flags.join(""));
- } catch (err) {
- malformed = true;
- this.trigger("error", {
- code: "E016",
- line: this.line,
- character: this.char,
- data: [ err.message ] // Platform dependent!
- });
- }
-
- return {
- type: Token.RegExp,
- value: value,
- flags: flags,
- isMalformed: malformed
- };
- },
-
- /*
- * Scan for any occurence of mixed tabs and spaces. If smarttabs option
- * is on, ignore tabs followed by spaces.
- *
- * Tabs followed by one space followed by a block comment are allowed.
- */
- scanMixedSpacesAndTabs: function () {
- var at, match;
-
- if (state.option.smarttabs) {
- // Negative look-behind for "//"
- match = this.input.match(/(\/\/|^\s?\*)? \t/);
- at = match && !match[1] ? 0 : -1;
- } else {
- at = this.input.search(/ \t|\t [^\*]/);
- }
-
- return at;
- },
-
- /*
- * Scan for characters that get silently deleted by one or more browsers.
- */
- scanUnsafeChars: function () {
- return this.input.search(reg.unsafeChars);
- },
-
- /*
- * Produce the next raw token or return 'null' if no tokens can be matched.
- * This method skips over all space characters.
- */
- next: function (checks) {
- this.from = this.char;
-
- // Move to the next non-space character.
- var start;
- if (/\s/.test(this.peek())) {
- start = this.char;
-
- while (/\s/.test(this.peek())) {
- this.from += 1;
- this.skip();
- }
-
- if (this.peek() === "") { // EOL
- if (!/^\s*$/.test(this.lines[this.line - 1]) && state.option.trailing) {
- this.trigger("warning", { code: "W102", line: this.line, character: start });
- }
- }
- }
-
- // Methods that work with multi-line structures and move the
- // character pointer.
-
- var match = this.scanComments() ||
- this.scanStringLiteral(checks);
-
- if (match) {
- return match;
- }
-
- // Methods that don't move the character pointer.
-
- match =
- this.scanRegExp() ||
- this.scanPunctuator() ||
- this.scanKeyword() ||
- this.scanIdentifier() ||
- this.scanNumericLiteral();
-
- if (match) {
- this.skip(match.value.length);
- return match;
- }
-
- // No token could be matched, give up.
-
- return null;
- },
-
- /*
- * Switch to the next line and reset all char pointers. Once
- * switched, this method also checks for mixed spaces and tabs
- * and other minor warnings.
- */
- nextLine: function () {
- var char;
-
- if (this.line >= this.lines.length) {
- return false;
- }
-
- this.input = this.lines[this.line];
- this.line += 1;
- this.char = 1;
- this.from = 1;
-
- char = this.scanMixedSpacesAndTabs();
- if (char >= 0) {
- this.trigger("warning", { code: "W099", line: this.line, character: char + 1 });
- }
-
- this.input = this.input.replace(/\t/g, state.tab);
- char = this.scanUnsafeChars();
-
- if (char >= 0) {
- this.trigger("warning", { code: "W100", line: this.line, character: char });
- }
-
- // If there is a limit on line length, warn when lines get too
- // long.
-
- if (state.option.maxlen && state.option.maxlen < this.input.length) {
- this.trigger("warning", { code: "W101", line: this.line, character: this.input.length });
- }
-
- return true;
- },
-
- /*
- * This is simply a synonym for nextLine() method with a friendlier
- * public name.
- */
- start: function () {
- this.nextLine();
- },
-
- /*
- * Produce the next token. This function is called by advance() to get
- * the next token. It retuns a token in a JSLint-compatible format.
- */
- token: function () {
- /*jshint loopfunc:true */
- var checks = asyncTrigger();
- var token;
-
-
- function isReserved(token, isProperty) {
- if (!token.reserved) {
- return false;
- }
-
- if (token.meta && token.meta.isFutureReservedWord) {
- // ES3 FutureReservedWord in an ES5 environment.
- if (state.option.inES5(true) && !token.meta.es5) {
- return false;
- }
-
- // Some ES5 FutureReservedWord identifiers are active only
- // within a strict mode environment.
- if (token.meta.strictOnly) {
- if (!state.option.strict && !state.directive["use strict"]) {
- return false;
- }
- }
-
- if (isProperty) {
- return false;
- }
- }
-
- return true;
- }
-
- // Produce a token object.
- var create = function (type, value, isProperty) {
- /*jshint validthis:true */
- var obj;
-
- if (type !== "(endline)" && type !== "(end)") {
- this.prereg = false;
- }
-
- if (type === "(punctuator)") {
- switch (value) {
- case ".":
- case ")":
- case "~":
- case "#":
- case "]":
- this.prereg = false;
- break;
- default:
- this.prereg = true;
- }
-
- obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
- }
-
- if (type === "(identifier)") {
- if (value === "return" || value === "case" || value === "typeof") {
- this.prereg = true;
- }
-
- if (_.has(state.syntax, value)) {
- obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
-
- // If this can't be a reserved keyword, reset the object.
- if (!isReserved(obj, isProperty && type === "(identifier)")) {
- obj = null;
- }
- }
- }
-
- if (!obj) {
- obj = Object.create(state.syntax[type]);
- }
-
- obj.identifier = (type === "(identifier)");
- obj.type = obj.type || type;
- obj.value = value;
- obj.line = this.line;
- obj.character = this.char;
- obj.from = this.from;
-
- if (isProperty && obj.identifier) {
- obj.isProperty = isProperty;
- }
-
- obj.check = checks.check;
-
- return obj;
- }.bind(this);
-
- for (;;) {
- if (!this.input.length) {
- return create(this.nextLine() ? "(endline)" : "(end)", "");
- }
-
- token = this.next(checks);
-
- if (!token) {
- if (this.input.length) {
- // Unexpected character.
- this.trigger("error", {
- code: "E024",
- line: this.line,
- character: this.char,
- data: [ this.peek() ]
- });
-
- this.input = "";
- }
-
- continue;
- }
-
- switch (token.type) {
- case Token.StringLiteral:
- this.triggerAsync("String", {
- line: this.line,
- char: this.char,
- from: this.from,
- value: token.value,
- quote: token.quote
- }, checks, function () { return true; });
-
- return create("(string)", token.value);
- case Token.Identifier:
- this.trigger("Identifier", {
- line: this.line,
- char: this.char,
- from: this.form,
- name: token.value,
- isProperty: state.tokens.curr.id === "."
- });
-
- /* falls through */
- case Token.Keyword:
- case Token.NullLiteral:
- case Token.BooleanLiteral:
- return create("(identifier)", token.value, state.tokens.curr.id === ".");
-
- case Token.NumericLiteral:
- if (token.isMalformed) {
- this.trigger("warning", {
- code: "W045",
- line: this.line,
- character: this.char,
- data: [ token.value ]
- });
- }
-
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "0x-" ]
- }, checks, function () { return token.base === 16 && state.jsonMode; });
-
- this.triggerAsync("warning", {
- code: "W115",
- line: this.line,
- character: this.char
- }, checks, function () {
- return state.directive["use strict"] && token.base === 8;
- });
-
- this.trigger("Number", {
- line: this.line,
- char: this.char,
- from: this.from,
- value: token.value,
- base: token.base,
- isMalformed: token.malformed
- });
-
- return create("(number)", token.value);
-
- case Token.RegExp:
- return create("(regexp)", token.value);
-
- case Token.Comment:
- state.tokens.curr.comment = true;
-
- if (token.isSpecial) {
- return {
- value: token.value,
- body: token.body,
- type: token.commentType,
- isSpecial: token.isSpecial,
- line: this.line,
- character: this.char,
- from: this.from
- };
- }
-
- break;
-
- case "":
- break;
-
- default:
- return create("(punctuator)", token.value);
- }
- }
- }
-};
-
-exports.Lexer = Lexer;
-
-})()
-},{"events":2,"./reg.js":6,"./state.js":4,"underscore":11}],"jshint":[function(require,module,exports){
-module.exports=require('E/GbHF');
-},{}],"E/GbHF":[function(require,module,exports){
-(function(){/*!
- * JSHint, by JSHint Community.
- *
- * This file (and this file only) is licensed under the same slightly modified
- * MIT license that JSLint is. It stops evil-doers everywhere:
- *
- * Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * The Software shall be used for Good, not Evil.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-/*jshint quotmark:double */
-/*global console:true */
-/*exported console */
-
-var _ = require("underscore");
-var events = require("events");
-var vars = require("../shared/vars.js");
-var messages = require("../shared/messages.js");
-var Lexer = require("./lex.js").Lexer;
-var reg = require("./reg.js");
-var state = require("./state.js").state;
-var style = require("./style.js");
-
-// We need this module here because environments such as IE and Rhino
-// don't necessarilly expose the 'console' API and browserify uses
-// it to log things. It's a sad state of affair, really.
-var console = require("console-browserify");
-
-// We build the application inside a function so that we produce only a singleton
-// variable. That function will be invoked immediately, and its return value is
-// the JSHINT function itself.
-
-var JSHINT = (function () {
- "use strict";
-
- var anonname, // The guessed name for anonymous functions.
- api, // Extension API
-
- // These are operators that should not be used with the ! operator.
- bang = {
- "<" : true,
- "<=" : true,
- "==" : true,
- "===": true,
- "!==": true,
- "!=" : true,
- ">" : true,
- ">=" : true,
- "+" : true,
- "-" : true,
- "*" : true,
- "/" : true,
- "%" : true
- },
-
- // These are the JSHint boolean options.
- boolOptions = {
- asi : true, // if automatic semicolon insertion should be tolerated
- bitwise : true, // if bitwise operators should not be allowed
- boss : true, // if advanced usage of assignments should be allowed
- browser : true, // if the standard browser globals should be predefined
- camelcase : true, // if identifiers should be required in camel case
- couch : true, // if CouchDB globals should be predefined
- curly : true, // if curly braces around all blocks should be required
- debug : true, // if debugger statements should be allowed
- devel : true, // if logging globals should be predefined (console, alert, etc.)
- dojo : true, // if Dojo Toolkit globals should be predefined
- eqeqeq : true, // if === should be required
- eqnull : true, // if == null comparisons should be tolerated
- es3 : true, // if ES3 syntax should be allowed
- es5 : true, // if ES5 syntax should be allowed (is now set per default)
- esnext : true, // if es.next specific syntax should be allowed
- moz : true, // if mozilla specific syntax should be allowed
- evil : true, // if eval should be allowed
- expr : true, // if ExpressionStatement should be allowed as Programs
- forin : true, // if for in statements must filter
- funcscope : true, // if only function scope should be used for scope tests
- gcl : true, // if JSHint should be compatible with Google Closure Linter
- globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
- immed : true, // if immediate invocations must be wrapped in parens
- iterator : true, // if the `__iterator__` property should be allowed
- jquery : true, // if jQuery globals should be predefined
- lastsemic : true, // if semicolons may be ommitted for the trailing
- // statements inside of a one-line blocks.
- laxbreak : true, // if line breaks should not be checked
- laxcomma : true, // if line breaks should not be checked around commas
- loopfunc : true, // if functions should be allowed to be defined within
- // loops
- mootools : true, // if MooTools globals should be predefined
- multistr : true, // allow multiline strings
- newcap : true, // if constructor names must be capitalized
- noarg : true, // if arguments.caller and arguments.callee should be
- // disallowed
- node : true, // if the Node.js environment globals should be
- // predefined
- noempty : true, // if empty blocks should be disallowed
- nonew : true, // if using `new` for side-effects should be disallowed
- nonstandard : true, // if non-standard (but widely adopted) globals should
- // be predefined
- nomen : true, // if names should be checked
- onevar : true, // if only one var statement per function should be
- // allowed
- passfail : true, // if the scan should stop on first error
- phantom : true, // if PhantomJS symbols should be allowed
- plusplus : true, // if increment/decrement should not be allowed
- proto : true, // if the `__proto__` property should be allowed
- prototypejs : true, // if Prototype and Scriptaculous globals should be
- // predefined
- rhino : true, // if the Rhino environment globals should be predefined
- undef : true, // if variables should be declared before used
- scripturl : true, // if script-targeted URLs should be tolerated
- shadow : true, // if variable shadowing should be tolerated
- smarttabs : true, // if smarttabs should be tolerated
- // (http://www.emacswiki.org/emacs/SmartTabs)
- strict : true, // require the "use strict"; pragma
- sub : true, // if all forms of subscript notation are tolerated
- supernew : true, // if `new function () { ... };` and `new Object;`
- // should be tolerated
- trailing : true, // if trailing whitespace rules apply
- validthis : true, // if 'this' inside a non-constructor function is valid.
- // This is a function scoped option only.
- withstmt : true, // if with statements should be allowed
- white : true, // if strict whitespace rules apply
- worker : true, // if Web Worker script symbols should be allowed
- wsh : true, // if the Windows Scripting Host environment globals
- // should be predefined
- yui : true, // YUI variables should be predefined
-
- // Obsolete options
- onecase : true, // if one case switch statements should be allowed
- regexp : true, // if the . should not be allowed in regexp literals
- regexdash : true // if unescaped first/last dash (-) inside brackets
- // should be tolerated
- },
-
- // These are the JSHint options that can take any value
- // (we use this object to detect invalid options)
- valOptions = {
- maxlen : false,
- indent : false,
- maxerr : false,
- predef : false,
- quotmark : false, //'single'|'double'|true
- scope : false,
- maxstatements: false, // {int} max statements per function
- maxdepth : false, // {int} max nested block depth per function
- maxparams : false, // {int} max params per function
- maxcomplexity: false, // {int} max cyclomatic complexity per function
- unused : true, // warn if variables are unused. Available options:
- // false - don't check for unused variables
- // true - "vars" + check last function param
- // "vars" - skip checking unused function params
- // "strict" - "vars" + check all function params
- latedef : false // warn if the variable is used before its definition
- // false - don't emit any warnings
- // true - warn if any variable is used before its definition
- // "nofunc" - warn for any variable but function declarations
- },
-
- // These are JSHint boolean options which are shared with JSLint
- // where the definition in JSHint is opposite JSLint
- invertedOptions = {
- bitwise : true,
- forin : true,
- newcap : true,
- nomen : true,
- plusplus: true,
- regexp : true,
- undef : true,
- white : true,
-
- // Inverted and renamed, use JSHint name here
- eqeqeq : true,
- onevar : true,
- strict : true
- },
-
- // These are JSHint boolean options which are shared with JSLint
- // where the name has been changed but the effect is unchanged
- renamedOptions = {
- eqeq : "eqeqeq",
- vars : "onevar",
- windows: "wsh",
- sloppy : "strict"
- },
-
- declared, // Globals that were declared using /*global ... */ syntax.
- exported, // Variables that are used outside of the current file.
-
- functionicity = [
- "closure", "exception", "global", "label",
- "outer", "unused", "var"
- ],
-
- funct, // The current function
- functions, // All of the functions
-
- global, // The global scope
- implied, // Implied globals
- inblock,
- indent,
- lookahead,
- lex,
- member,
- membersOnly,
- noreach,
- predefined, // Global variables defined by option
-
- scope, // The current scope
- stack,
- unuseds,
- urls,
- warnings,
-
- extraModules = [],
- emitter = new events.EventEmitter();
-
- function checkOption(name, t) {
- name = name.trim();
-
- if (/^[+-]W\d{3}$/g.test(name)) {
- return true;
- }
-
- if (valOptions[name] === undefined && boolOptions[name] === undefined) {
- if (t.type !== "jslint") {
- error("E001", t, name);
- return false;
- }
- }
-
- return true;
- }
-
- function isString(obj) {
- return Object.prototype.toString.call(obj) === "[object String]";
- }
-
- function isIdentifier(tkn, value) {
- if (!tkn)
- return false;
-
- if (!tkn.identifier || tkn.value !== value)
- return false;
-
- return true;
- }
-
- function isReserved(token) {
- if (!token.reserved) {
- return false;
- }
-
- if (token.meta && token.meta.isFutureReservedWord) {
- // ES3 FutureReservedWord in an ES5 environment.
- if (state.option.inES5(true) && !token.meta.es5) {
- return false;
- }
-
- // Some ES5 FutureReservedWord identifiers are active only
- // within a strict mode environment.
- if (token.meta.strictOnly) {
- if (!state.option.strict && !state.directive["use strict"]) {
- return false;
- }
- }
-
- if (token.isProperty) {
- return false;
- }
- }
-
- return true;
- }
-
- function supplant(str, data) {
- return str.replace(/\{([^{}]*)\}/g, function (a, b) {
- var r = data[b];
- return typeof r === "string" || typeof r === "number" ? r : a;
- });
- }
-
- function combine(t, o) {
- var n;
- for (n in o) {
- if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {
- t[n] = o[n];
- }
- }
- }
-
- function updatePredefined() {
- Object.keys(JSHINT.blacklist).forEach(function (key) {
- delete predefined[key];
- });
- }
-
- function assume() {
- if (state.option.es5) {
- warning("I003");
- }
- if (state.option.couch) {
- combine(predefined, vars.couch);
- }
-
- if (state.option.rhino) {
- combine(predefined, vars.rhino);
- }
-
- if (state.option.phantom) {
- combine(predefined, vars.phantom);
- }
-
- if (state.option.prototypejs) {
- combine(predefined, vars.prototypejs);
- }
-
- if (state.option.node) {
- combine(predefined, vars.node);
- }
-
- if (state.option.devel) {
- combine(predefined, vars.devel);
- }
-
- if (state.option.dojo) {
- combine(predefined, vars.dojo);
- }
-
- if (state.option.browser) {
- combine(predefined, vars.browser);
- }
-
- if (state.option.nonstandard) {
- combine(predefined, vars.nonstandard);
- }
-
- if (state.option.jquery) {
- combine(predefined, vars.jquery);
- }
-
- if (state.option.mootools) {
- combine(predefined, vars.mootools);
- }
-
- if (state.option.worker) {
- combine(predefined, vars.worker);
- }
-
- if (state.option.wsh) {
- combine(predefined, vars.wsh);
- }
-
- if (state.option.globalstrict && state.option.strict !== false) {
- state.option.strict = true;
- }
-
- if (state.option.yui) {
- combine(predefined, vars.yui);
- }
-
- // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
-
- state.option.inMoz = function (strict) {
- if (strict) {
- return state.option.moz && !state.option.esnext;
- }
- return state.option.moz;
- };
-
- state.option.inESNext = function (strict) {
- if (strict) {
- return !state.option.moz && state.option.esnext;
- }
- return state.option.moz || state.option.esnext;
- };
-
- state.option.inES5 = function (/* strict */) {
- return !state.option.es3;
- };
-
- state.option.inES3 = function (strict) {
- if (strict) {
- return !state.option.moz && !state.option.esnext && state.option.es3;
- }
- return state.option.es3;
- };
- }
-
- // Produce an error warning.
- function quit(code, line, chr) {
- var percentage = Math.floor((line / state.lines.length) * 100);
- var message = messages.errors[code].desc;
-
- throw {
- name: "JSHintError",
- line: line,
- character: chr,
- message: message + " (" + percentage + "% scanned).",
- raw: message
- };
- }
-
- function isundef(scope, code, token, a) {
- return JSHINT.undefs.push([scope, code, token, a]);
- }
-
- function warning(code, t, a, b, c, d) {
- var ch, l, w, msg;
-
- if (/^W\d{3}$/.test(code)) {
- if (state.ignored[code])
- return;
-
- msg = messages.warnings[code];
- } else if (/E\d{3}/.test(code)) {
- msg = messages.errors[code];
- } else if (/I\d{3}/.test(code)) {
- msg = messages.info[code];
- }
-
- t = t || state.tokens.next;
- if (t.id === "(end)") { // `~
- t = state.tokens.curr;
- }
-
- l = t.line || 0;
- ch = t.from || 0;
-
- w = {
- id: "(error)",
- raw: msg.desc,
- code: msg.code,
- evidence: state.lines[l - 1] || "",
- line: l,
- character: ch,
- scope: JSHINT.scope,
- a: a,
- b: b,
- c: c,
- d: d
- };
-
- w.reason = supplant(msg.desc, w);
- JSHINT.errors.push(w);
-
- if (state.option.passfail) {
- quit("E042", l, ch);
- }
-
- warnings += 1;
- if (warnings >= state.option.maxerr) {
- quit("E043", l, ch);
- }
-
- return w;
- }
-
- function warningAt(m, l, ch, a, b, c, d) {
- return warning(m, {
- line: l,
- from: ch
- }, a, b, c, d);
- }
-
- function error(m, t, a, b, c, d) {
- warning(m, t, a, b, c, d);
- }
-
- function errorAt(m, l, ch, a, b, c, d) {
- return error(m, {
- line: l,
- from: ch
- }, a, b, c, d);
- }
-
- // Tracking of "internal" scripts, like eval containing a static string
- function addInternalSrc(elem, src) {
- var i;
- i = {
- id: "(internal)",
- elem: elem,
- value: src
- };
- JSHINT.internals.push(i);
- return i;
- }
-
- function addlabel(t, type, tkn, islet) {
- // Define t in the current function in the current scope.
- if (type === "exception") {
- if (_.has(funct["(context)"], t)) {
- if (funct[t] !== true && !state.option.node) {
- warning("W002", state.tokens.next, t);
- }
- }
- }
-
- if (_.has(funct, t) && !funct["(global)"]) {
- if (funct[t] === true) {
- if (state.option.latedef) {
- if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
- !_.contains([funct[t], type], "unction")) {
- warning("W003", state.tokens.next, t);
- }
- }
- } else {
- if (!state.option.shadow && type !== "exception" ||
- (funct["(blockscope)"].getlabel(t))) {
- warning("W004", state.tokens.next, t);
- }
- }
- }
-
- // a double definition of a let variable in same block throws a TypeError
- //if (funct["(blockscope)"] && funct["(blockscope)"].current.has(t)) {
- // error("E044", state.tokens.next, t);
- //}
-
- // if the identifier is from a let, adds it only to the current blockscope
- if (islet) {
- funct["(blockscope)"].current.add(t, type, state.tokens.curr);
- } else {
-
- funct[t] = type;
-
- if (tkn) {
- funct["(tokens)"][t] = tkn;
- }
-
- if (funct["(global)"]) {
- global[t] = funct;
- if (_.has(implied, t)) {
- if (state.option.latedef) {
- if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
- !_.contains([funct[t], type], "unction")) {
- warning("W003", state.tokens.next, t);
- }
- }
-
- delete implied[t];
- }
- } else {
- scope[t] = funct;
- }
- }
- }
-
- function doOption() {
- var nt = state.tokens.next;
- var body = nt.body.split(",").map(function (s) { return s.trim(); });
- var predef = {};
-
- if (nt.type === "globals") {
- body.forEach(function (g) {
- g = g.split(":");
- var key = g[0];
- var val = g[1];
-
- if (key.charAt(0) === "-") {
- key = key.slice(1);
- val = false;
-
- JSHINT.blacklist[key] = key;
- updatePredefined();
- } else {
- predef[key] = (val === "true");
- }
- });
-
- combine(predefined, predef);
-
- for (var key in predef) {
- if (_.has(predef, key)) {
- declared[key] = nt;
- }
- }
- }
-
- if (nt.type === "exported") {
- body.forEach(function (e) {
- exported[e] = true;
- });
- }
-
- if (nt.type === "members") {
- membersOnly = membersOnly || {};
-
- body.forEach(function (m) {
- var ch1 = m.charAt(0);
- var ch2 = m.charAt(m.length - 1);
-
- if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
- m = m
- .substr(1, m.length - 2)
- .replace("\\b", "\b")
- .replace("\\t", "\t")
- .replace("\\n", "\n")
- .replace("\\v", "\v")
- .replace("\\f", "\f")
- .replace("\\r", "\r")
- .replace("\\\\", "\\")
- .replace("\\\"", "\"");
- }
-
- membersOnly[m] = false;
- });
- }
-
- var numvals = [
- "maxstatements",
- "maxparams",
- "maxdepth",
- "maxcomplexity",
- "maxerr",
- "maxlen",
- "indent"
- ];
-
- if (nt.type === "jshint" || nt.type === "jslint") {
- body.forEach(function (g) {
- g = g.split(":");
- var key = (g[0] || "").trim();
- var val = (g[1] || "").trim();
-
- if (!checkOption(key, nt)) {
- return;
- }
-
- if (numvals.indexOf(key) >= 0) {
-
- // GH988 - numeric options can be disabled by setting them to `false`
- if (val !== "false") {
- val = +val;
-
- if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
- error("E032", nt, g[1].trim());
- return;
- }
-
- if (key === "indent") {
- state.option["(explicitIndent)"] = true;
- }
- state.option[key] = val;
- } else {
- if (key === "indent") {
- state.option["(explicitIndent)"] = false;
- } else {
- state.option[key] = false;
- }
- }
-
- return;
- }
-
- if (key === "validthis") {
- // `validthis` is valid only within a function scope.
- if (funct["(global)"]) {
- error("E009");
- } else {
- if (val === "true" || val === "false") {
- state.option.validthis = (val === "true");
- } else {
- error("E002", nt);
- }
- }
- return;
- }
-
- if (key === "quotmark") {
- switch (val) {
- case "true":
- case "false":
- state.option.quotmark = (val === "true");
- break;
- case "double":
- case "single":
- state.option.quotmark = val;
- break;
- default:
- error("E002", nt);
- }
- return;
- }
-
- if (key === "unused") {
- switch (val) {
- case "true":
- state.option.unused = true;
- break;
- case "false":
- state.option.unused = false;
- break;
- case "vars":
- case "strict":
- state.option.unused = val;
- break;
- default:
- error("E002", nt);
- }
- return;
- }
-
- if (key === "latedef") {
- switch (val) {
- case "true":
- state.option.latedef = true;
- break;
- case "false":
- state.option.latedef = false;
- break;
- case "nofunc":
- state.option.latedef = "nofunc";
- break;
- default:
- error("E002", nt);
- }
- return;
- }
-
- var match = /^([+-])(W\d{3})$/g.exec(key);
- if (match) {
- // ignore for -W..., unignore for +W...
- state.ignored[match[2]] = (match[1] === "-");
- return;
- }
-
- var tn;
- if (val === "true" || val === "false") {
- if (nt.type === "jslint") {
- tn = renamedOptions[key] || key;
- state.option[tn] = (val === "true");
-
- if (invertedOptions[tn] !== undefined) {
- state.option[tn] = !state.option[tn];
- }
- } else {
- state.option[key] = (val === "true");
- }
-
- if (key === "newcap") {
- state.option["(explicitNewcap)"] = true;
- }
- return;
- }
-
- error("E002", nt);
- });
-
- assume();
- }
- }
-
- // We need a peek function. If it has an argument, it peeks that much farther
- // ahead. It is used to distinguish
- // for ( var i in ...
- // from
- // for ( var i = ...
-
- function peek(p) {
- var i = p || 0, j = 0, t;
-
- while (j <= i) {
- t = lookahead[j];
- if (!t) {
- t = lookahead[j] = lex.token();
- }
- j += 1;
- }
- return t;
- }
-
- // Produce the next token. It looks for programming errors.
-
- function advance(id, t) {
- switch (state.tokens.curr.id) {
- case "(number)":
- if (state.tokens.next.id === ".") {
- warning("W005", state.tokens.curr);
- }
- break;
- case "-":
- if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
- warning("W006");
- }
- break;
- case "+":
- if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
- warning("W007");
- }
- break;
- }
-
- if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
- anonname = state.tokens.curr.value;
- }
-
- if (id && state.tokens.next.id !== id) {
- if (t) {
- if (state.tokens.next.id === "(end)") {
- error("E019", t, t.id);
- } else {
- error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
- }
- } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
- warning("W116", state.tokens.next, id, state.tokens.next.value);
- }
- }
-
- state.tokens.prev = state.tokens.curr;
- state.tokens.curr = state.tokens.next;
- for (;;) {
- state.tokens.next = lookahead.shift() || lex.token();
-
- if (!state.tokens.next) { // No more tokens left, give up
- quit("E041", state.tokens.curr.line);
- }
-
- if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
- return;
- }
-
- if (state.tokens.next.check) {
- state.tokens.next.check();
- }
-
- if (state.tokens.next.isSpecial) {
- doOption();
- } else {
- if (state.tokens.next.id !== "(endline)") {
- break;
- }
- }
- }
- }
-
- // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
- // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
- // like .nud except that it is only used on the first token of a statement.
- // Having .fud makes it much easier to define statement-oriented languages like
- // JavaScript. I retained Pratt's nomenclature.
-
- // .nud Null denotation
- // .fud First null denotation
- // .led Left denotation
- // lbp Left binding power
- // rbp Right binding power
-
- // They are elements of the parsing method called Top Down Operator Precedence.
-
- function expression(rbp, initial) {
- var left, isArray = false, isObject = false, isLetExpr = false;
-
- // if current expression is a let expression
- if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.next, "let expressions");
- }
- isLetExpr = true;
- // create a new block scope we use only for the current expression
- funct["(blockscope)"].stack();
- advance("let");
- advance("(");
- state.syntax["let"].fud.call(state.syntax["let"].fud, false);
- advance(")");
- }
-
- if (state.tokens.next.id === "(end)")
- error("E006", state.tokens.curr);
-
- advance();
-
- if (initial) {
- anonname = "anonymous";
- funct["(verb)"] = state.tokens.curr.value;
- }
-
- if (initial === true && state.tokens.curr.fud) {
- left = state.tokens.curr.fud();
- } else {
- if (state.tokens.curr.nud) {
- left = state.tokens.curr.nud();
- } else {
- error("E030", state.tokens.curr, state.tokens.curr.id);
- }
-
- var end_of_expr = state.tokens.next.identifier &&
- !state.tokens.curr.led &&
- state.tokens.curr.line !== state.tokens.next.line;
- while (rbp < state.tokens.next.lbp && !end_of_expr) {
- isArray = state.tokens.curr.value === "Array";
- isObject = state.tokens.curr.value === "Object";
-
- // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
- // Line breaks in IfStatement heads exist to satisfy the checkJSHint
- // "Line too long." error.
- if (left && (left.value || (left.first && left.first.value))) {
- // If the left.value is not "new", or the left.first.value is a "."
- // then safely assume that this is not "new Array()" and possibly
- // not "new Object()"...
- if (left.value !== "new" ||
- (left.first && left.first.value && left.first.value === ".")) {
- isArray = false;
- // ...In the case of Object, if the left.value and state.tokens.curr.value
- // are not equal, then safely assume that this not "new Object()"
- if (left.value !== state.tokens.curr.value) {
- isObject = false;
- }
- }
- }
-
- advance();
-
- if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
- warning("W009", state.tokens.curr);
- }
-
- if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
- warning("W010", state.tokens.curr);
- }
-
- if (left && state.tokens.curr.led) {
- left = state.tokens.curr.led(left);
- } else {
- error("E033", state.tokens.curr, state.tokens.curr.id);
- }
- }
- }
- if (isLetExpr) {
- funct["(blockscope)"].unstack();
- }
- return left;
- }
-
-
-// Functions for conformance of style.
-
- function adjacent(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white) {
- if (left.character !== right.from && left.line === right.line) {
- left.from += (left.character - left.from);
- warning("W011", left, left.value);
- }
- }
- }
-
- function nobreak(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white && (left.character !== right.from || left.line !== right.line)) {
- warning("W012", right, right.value);
- }
- }
-
- function nospace(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white && !left.comment) {
- if (left.line === right.line) {
- adjacent(left, right);
- }
- }
- }
-
- function nonadjacent(left, right) {
- if (state.option.white) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
-
- if (left.value === ";" && right.value === ";") {
- return;
- }
-
- if (left.line === right.line && left.character === right.from) {
- left.from += (left.character - left.from);
- warning("W013", left, left.value);
- }
- }
- }
-
- function nobreaknonadjacent(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (!state.option.laxbreak && left.line !== right.line) {
- warning("W014", right, right.id);
- } else if (state.option.white) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (left.character === right.from) {
- left.from += (left.character - left.from);
- warning("W013", left, left.value);
- }
- }
- }
-
- function indentation(bias) {
- if (!state.option.white && !state.option["(explicitIndent)"]) {
- return;
- }
-
- if (state.tokens.next.id === "(end)") {
- return;
- }
-
- var i = indent + (bias || 0);
- if (state.tokens.next.from !== i) {
- warning("W015", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);
- }
- }
-
- function nolinebreak(t) {
- t = t || state.tokens.curr;
- if (t.line !== state.tokens.next.line) {
- warning("E022", t, t.value);
- }
- }
-
-
- function comma(opts) {
- opts = opts || {};
-
- if (!opts.peek) {
- if (state.tokens.curr.line !== state.tokens.next.line) {
- if (!state.option.laxcomma) {
- if (comma.first) {
- warning("I001");
- comma.first = false;
- }
- warning("W014", state.tokens.curr, state.tokens.next.value);
- }
- } else if (!state.tokens.curr.comment &&
- state.tokens.curr.character !== state.tokens.next.from && state.option.white) {
- state.tokens.curr.from += (state.tokens.curr.character - state.tokens.curr.from);
- warning("W011", state.tokens.curr, state.tokens.curr.value);
- }
-
- advance(",");
- }
-
- // TODO: This is a temporary solution to fight against false-positives in
- // arrays and objects with trailing commas (see GH-363). The best solution
- // would be to extract all whitespace rules out of parser.
-
- if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
-
- if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {
- // Keywords that cannot follow a comma operator.
- switch (state.tokens.next.value) {
- case "break":
- case "case":
- case "catch":
- case "continue":
- case "default":
- case "do":
- case "else":
- case "finally":
- case "for":
- case "if":
- case "in":
- case "instanceof":
- case "return":
- case "yield":
- case "switch":
- case "throw":
- case "try":
- case "var":
- case "let":
- case "while":
- case "with":
- error("E024", state.tokens.next, state.tokens.next.value);
- return false;
- }
- }
-
- if (state.tokens.next.type === "(punctuator)") {
- switch (state.tokens.next.value) {
- case "}":
- case "]":
- case ",":
- if (opts.allowTrailing) {
- return true;
- }
-
- /* falls through */
- case ")":
- error("E024", state.tokens.next, state.tokens.next.value);
- return false;
- }
- }
- return true;
- }
-
- // Functional constructors for making the symbols that will be inherited by
- // tokens.
-
- function symbol(s, p) {
- var x = state.syntax[s];
- if (!x || typeof x !== "object") {
- state.syntax[s] = x = {
- id: s,
- lbp: p,
- value: s
- };
- }
- return x;
- }
-
- function delim(s) {
- return symbol(s, 0);
- }
-
- function stmt(s, f) {
- var x = delim(s);
- x.identifier = x.reserved = true;
- x.fud = f;
- return x;
- }
-
- function blockstmt(s, f) {
- var x = stmt(s, f);
- x.block = true;
- return x;
- }
-
- function reserveName(x) {
- var c = x.id.charAt(0);
- if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
- x.identifier = x.reserved = true;
- }
- return x;
- }
-
- function prefix(s, f) {
- var x = symbol(s, 150);
- reserveName(x);
- x.nud = (typeof f === "function") ? f : function () {
- this.right = expression(150);
- this.arity = "unary";
- if (this.id === "++" || this.id === "--") {
- if (state.option.plusplus) {
- warning("W016", this, this.id);
- } else if ((!this.right.identifier || isReserved(this.right)) &&
- this.right.id !== "." && this.right.id !== "[") {
- warning("W017", this);
- }
- }
- return this;
- };
- return x;
- }
-
- function type(s, f) {
- var x = delim(s);
- x.type = s;
- x.nud = f;
- return x;
- }
-
- function reserve(name, func) {
- var x = type(name, func);
- x.identifier = true;
- x.reserved = true;
- return x;
- }
-
- function FutureReservedWord(name, meta) {
- var x = type(name, (meta && meta.nud) || function () {
- return this;
- });
-
- meta = meta || {};
- meta.isFutureReservedWord = true;
-
- x.value = name;
- x.identifier = true;
- x.reserved = true;
- x.meta = meta;
-
- return x;
- }
-
- function reservevar(s, v) {
- return reserve(s, function () {
- if (typeof v === "function") {
- v(this);
- }
- return this;
- });
- }
-
- function infix(s, f, p, w) {
- var x = symbol(s, p);
- reserveName(x);
- x.led = function (left) {
- if (!w) {
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- if (s === "in" && left.id === "!") {
- warning("W018", left, "!");
- }
- if (typeof f === "function") {
- return f(left, this);
- } else {
- this.left = left;
- this.right = expression(p);
- return this;
- }
- };
- return x;
- }
-
-
- function application(s) {
- var x = symbol(s, 42);
-
- x.led = function (left) {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "arrow function syntax (=>)");
- }
-
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
-
- this.left = left;
- this.right = doFunction(undefined, undefined, false, left);
- return this;
- };
- return x;
- }
-
- function relation(s, f) {
- var x = symbol(s, 100);
-
- x.led = function (left) {
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- var right = expression(100);
-
- if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
- warning("W019", this);
- } else if (f) {
- f.apply(this, [left, right]);
- }
-
- if (!left || !right) {
- quit("E041", state.tokens.curr.line);
- }
-
- if (left.id === "!") {
- warning("W018", left, "!");
- }
-
- if (right.id === "!") {
- warning("W018", right, "!");
- }
-
- this.left = left;
- this.right = right;
- return this;
- };
- return x;
- }
-
- function isPoorRelation(node) {
- return node &&
- ((node.type === "(number)" && +node.value === 0) ||
- (node.type === "(string)" && node.value === "") ||
- (node.type === "null" && !state.option.eqnull) ||
- node.type === "true" ||
- node.type === "false" ||
- node.type === "undefined");
- }
-
- function assignop(s) {
- symbol(s, 20).exps = true;
-
- return infix(s, function (left, that) {
- that.left = left;
-
- if (left) {
- if (predefined[left.value] === false &&
- scope[left.value]["(global)"] === true) {
- warning("W020", left);
- } else if (left["function"]) {
- warning("W021", left, left.value);
- }
-
- if (funct[left.value] === "const") {
- error("E013", left, left.value);
- }
-
- if (left.id === ".") {
- if (!left.left) {
- warning("E031", that);
- } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
- warning("E031", that);
- }
-
- that.right = expression(19);
- return that;
- } else if (left.id === "[") {
- if (state.tokens.curr.left.first) {
- state.tokens.curr.left.first.forEach(function (t) {
- if (funct[t.value] === "const") {
- error("E013", t, t.value);
- }
- });
- } else if (!left.left) {
- warning("E031", that);
- } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
- warning("E031", that);
- }
- that.right = expression(19);
- return that;
- } else if (left.identifier && !isReserved(left)) {
- if (funct[left.value] === "exception") {
- warning("W022", left);
- }
- that.right = expression(19);
- return that;
- }
-
- if (left === state.syntax["function"]) {
- warning("W023", state.tokens.curr);
- }
- }
-
- error("E031", that);
- }, 20);
- }
-
-
- function bitwise(s, f, p) {
- var x = symbol(s, p);
- reserveName(x);
- x.led = (typeof f === "function") ? f : function (left) {
- if (state.option.bitwise) {
- warning("W016", this, this.id);
- }
- this.left = left;
- this.right = expression(p);
- return this;
- };
- return x;
- }
-
-
- function bitwiseassignop(s) {
- symbol(s, 20).exps = true;
- return infix(s, function (left, that) {
- if (state.option.bitwise) {
- warning("W016", that, that.id);
- }
- nonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (left) {
- if (left.id === "." || left.id === "[" ||
- (left.identifier && !isReserved(left))) {
- expression(19);
- return that;
- }
- if (left === state.syntax["function"]) {
- warning("W023", state.tokens.curr);
- }
- return that;
- }
- error("E031", that);
- }, 20);
- }
-
-
- function suffix(s) {
- var x = symbol(s, 150);
-
- x.led = function (left) {
- if (state.option.plusplus) {
- warning("W016", this, this.id);
- } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
- warning("W017", this);
- }
-
- this.left = left;
- return this;
- };
- return x;
- }
-
- // fnparam means that this identifier is being defined as a function
- // argument (see identifier())
- // prop means that this identifier is that of an object property
-
- function optionalidentifier(fnparam, prop) {
- if (!state.tokens.next.identifier) {
- return;
- }
-
- advance();
-
- var curr = state.tokens.curr;
- var meta = curr.meta || {};
- var val = state.tokens.curr.value;
-
- if (!isReserved(curr)) {
- return val;
- }
-
- if (prop) {
- if (state.option.inES5() || meta.isFutureReservedWord) {
- return val;
- }
- }
-
- if (fnparam && val === "undefined") {
- return val;
- }
-
- // Display an info message about reserved words as properties
- // and ES5 but do it only once.
- if (prop && !api.getCache("displayed:I002")) {
- api.setCache("displayed:I002", true);
- warning("I002");
- }
-
- warning("W024", state.tokens.curr, state.tokens.curr.id);
- return val;
- }
-
- // fnparam means that this identifier is being defined as a function
- // argument
- // prop means that this identifier is that of an object property
- function identifier(fnparam, prop) {
- var i = optionalidentifier(fnparam, prop);
- if (i) {
- return i;
- }
- if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
- warning("W025");
- } else {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- }
-
-
- function reachable(s) {
- var i = 0, t;
- if (state.tokens.next.id !== ";" || noreach) {
- return;
- }
- for (;;) {
- t = peek(i);
- if (t.reach) {
- return;
- }
- if (t.id !== "(endline)") {
- if (t.id === "function") {
- if (!state.option.latedef) {
- break;
- }
-
- warning("W026", t);
- break;
- }
-
- warning("W027", t, t.value, s);
- break;
- }
- i += 1;
- }
- }
-
-
- function statement(noindent) {
- var values;
- var i = indent, r, s = scope, t = state.tokens.next;
-
- if (t.id === ";") {
- advance(";");
- return;
- }
-
- // Is this a labelled statement?
- var res = isReserved(t);
-
- // We're being more tolerant here: if someone uses
- // a FutureReservedWord as a label, we warn but proceed
- // anyway.
-
- if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
- warning("W024", t, t.id);
- res = false;
- }
-
- // detect a destructuring assignment
- if (_.has(["[", "{"], t.value)) {
- if (lookupBlockType().isDestAssign) {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring expression");
- }
- values = destructuringExpression();
- values.forEach(function (tok) {
- isundef(funct, "W117", tok.token, tok.id);
- });
- advance("=");
- destructuringExpressionMatch(values, expression(5, true));
- advance(";");
- return;
- }
- }
- if (t.identifier && !res && peek().id === ":") {
- advance();
- advance(":");
- scope = Object.create(s);
- addlabel(t.value, "label");
-
- if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
- warning("W028", state.tokens.next, t.value, state.tokens.next.value);
- }
-
- state.tokens.next.label = t.value;
- t = state.tokens.next;
- }
-
- // Is it a lonely block?
-
- if (t.id === "{") {
- // Is it a switch case block?
- //
- // switch (foo) {
- // case bar: { <= here.
- // ...
- // }
- // }
- var iscase = (funct["(verb)"] === "case" && state.tokens.curr.value === ":");
- block(true, true, false, false, iscase);
- return;
- }
-
- // Parse the statement.
-
- if (!noindent) {
- indentation();
- }
- r = expression(0, true);
-
- // Look for the final semicolon.
-
- if (!t.block) {
- if (!state.option.expr && (!r || !r.exps)) {
- warning("W030", state.tokens.curr);
- } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
- warning("W031", t);
- }
-
- if (state.tokens.next.id !== ";") {
- if (!state.option.asi) {
- // If this is the last statement in a block that ends on
- // the same line *and* option lastsemic is on, ignore the warning.
- // Otherwise, complain about missing semicolon.
- if (!state.option.lastsemic || state.tokens.next.id !== "}" ||
- state.tokens.next.line !== state.tokens.curr.line) {
- warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
- }
- }
- } else {
- adjacent(state.tokens.curr, state.tokens.next);
- advance(";");
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- }
-
- // Restore the indentation.
-
- indent = i;
- scope = s;
- return r;
- }
-
-
- function statements(startLine) {
- var a = [], p;
-
- while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
- if (state.tokens.next.id === ";") {
- p = peek();
-
- if (!p || (p.id !== "(" && p.id !== "[")) {
- warning("W032");
- }
-
- advance(";");
- } else {
- a.push(statement(startLine === state.tokens.next.line));
- }
- }
- return a;
- }
-
-
- /*
- * read all directives
- * recognizes a simple form of asi, but always
- * warns, if it is used
- */
- function directives() {
- var i, p, pn;
-
- for (;;) {
- if (state.tokens.next.id === "(string)") {
- p = peek(0);
- if (p.id === "(endline)") {
- i = 1;
- do {
- pn = peek(i);
- i = i + 1;
- } while (pn.id === "(endline)");
-
- if (pn.id !== ";") {
- if (pn.id !== "(string)" && pn.id !== "(number)" &&
- pn.id !== "(regexp)" && pn.identifier !== true &&
- pn.id !== "}") {
- break;
- }
- warning("W033", state.tokens.next);
- } else {
- p = pn;
- }
- } else if (p.id === "}") {
- // Directive with no other statements, warn about missing semicolon
- warning("W033", p);
- } else if (p.id !== ";") {
- break;
- }
-
- indentation();
- advance();
- if (state.directive[state.tokens.curr.value]) {
- warning("W034", state.tokens.curr, state.tokens.curr.value);
- }
-
- if (state.tokens.curr.value === "use strict") {
- if (!state.option["(explicitNewcap)"])
- state.option.newcap = true;
- state.option.undef = true;
- }
-
- // there's no directive negation, so always set to true
- state.directive[state.tokens.curr.value] = true;
-
- if (p.id === ";") {
- advance(";");
- }
- continue;
- }
- break;
- }
- }
-
-
- /*
- * Parses a single block. A block is a sequence of statements wrapped in
- * braces.
- *
- * ordinary - true for everything but function bodies and try blocks.
- * stmt - true if block can be a single statement (e.g. in if/for/while).
- * isfunc - true if block is a function body
- * isfatarrow -
- * iscase - true if block is a switch case block
- */
- function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
- var a,
- b = inblock,
- old_indent = indent,
- m,
- s = scope,
- t,
- line,
- d;
-
- inblock = ordinary;
-
- if (!ordinary || !state.option.funcscope)
- scope = Object.create(scope);
-
- nonadjacent(state.tokens.curr, state.tokens.next);
- t = state.tokens.next;
-
- var metrics = funct["(metrics)"];
- metrics.nestedBlockDepth += 1;
- metrics.verifyMaxNestedBlockDepthPerFunction();
-
- if (state.tokens.next.id === "{") {
- advance("{");
-
- // create a new block scope
- funct["(blockscope)"].stack();
-
- line = state.tokens.curr.line;
- if (state.tokens.next.id !== "}") {
- indent += state.option.indent;
- while (!ordinary && state.tokens.next.from > indent) {
- indent += state.option.indent;
- }
-
- if (isfunc) {
- m = {};
- for (d in state.directive) {
- if (_.has(state.directive, d)) {
- m[d] = state.directive[d];
- }
- }
- directives();
-
- if (state.option.strict && funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !state.directive["use strict"]) {
- warning("E007");
- }
- }
- }
-
- a = statements(line);
-
- metrics.statementCount += a.length;
-
- if (isfunc) {
- state.directive = m;
- }
-
- indent -= state.option.indent;
- if (line !== state.tokens.next.line) {
- indentation();
- }
- } else if (line !== state.tokens.next.line) {
- indentation();
- }
- advance("}", t);
-
- funct["(blockscope)"].unstack();
-
- indent = old_indent;
- } else if (!ordinary) {
- if (isfunc) {
- m = {};
- if (stmt && !isfatarrow && !state.option.inMoz(true)) {
- error("W118", state.tokens.curr, "function closure expressions");
- }
-
- if (!stmt) {
- for (d in state.directive) {
- if (_.has(state.directive, d)) {
- m[d] = state.directive[d];
- }
- }
- }
- expression(5);
-
- if (state.option.strict && funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !state.directive["use strict"]) {
- warning("E007");
- }
- }
- } else {
- error("E021", state.tokens.next, "{", state.tokens.next.value);
- }
- } else {
-
- // check to avoid let declaration not within a block
- funct["(nolet)"] = true;
-
- if (!stmt || state.option.curly) {
- warning("W116", state.tokens.next, "{", state.tokens.next.value);
- }
-
- noreach = true;
- indent += state.option.indent;
- // test indentation only if statement is in new line
- a = [statement(state.tokens.next.line === state.tokens.curr.line)];
- indent -= state.option.indent;
- noreach = false;
-
- delete funct["(nolet)"];
- }
- // If it is a "break" in switch case, don't clear and let it propagate out.
- if (!(iscase && funct["(verb)"] === "break")) funct["(verb)"] = null;
-
- if (!ordinary || !state.option.funcscope) scope = s;
- inblock = b;
- if (ordinary && state.option.noempty && (!a || a.length === 0)) {
- warning("W035");
- }
- metrics.nestedBlockDepth -= 1;
- return a;
- }
-
-
- function countMember(m) {
- if (membersOnly && typeof membersOnly[m] !== "boolean") {
- warning("W036", state.tokens.curr, m);
- }
- if (typeof member[m] === "number") {
- member[m] += 1;
- } else {
- member[m] = 1;
- }
- }
-
-
- function note_implied(tkn) {
- var name = tkn.value, line = tkn.line, a = implied[name];
- if (typeof a === "function") {
- a = false;
- }
-
- if (!a) {
- a = [line];
- implied[name] = a;
- } else if (a[a.length - 1] !== line) {
- a.push(line);
- }
- }
-
-
- // Build the syntax table by declaring the syntactic elements of the language.
-
- type("(number)", function () {
- return this;
- });
-
- type("(string)", function () {
- return this;
- });
-
- state.syntax["(identifier)"] = {
- type: "(identifier)",
- lbp: 0,
- identifier: true,
- nud: function () {
- var v = this.value,
- s = scope[v],
- f;
-
- if (typeof s === "function") {
- // Protection against accidental inheritance.
- s = undefined;
- } else if (typeof s === "boolean") {
- f = funct;
- funct = functions[0];
- addlabel(v, "var");
- s = funct;
- funct = f;
- }
- var block;
- if (_.has(funct, "(blockscope)")) {
- block = funct["(blockscope)"].getlabel(v);
- }
-
- // The name is in scope and defined in the current function.
- if (funct === s || block) {
- // Change 'unused' to 'var', and reject labels.
- // the name is in a block scope
- switch (block ? block[v]["(type)"] : funct[v]) {
- case "unused":
- if (block) block[v]["(type)"] = "var";
- else funct[v] = "var";
- break;
- case "unction":
- if (block) block[v]["(type)"] = "function";
- else funct[v] = "function";
- this["function"] = true;
- break;
- case "function":
- this["function"] = true;
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- break;
- }
- } else if (funct["(global)"]) {
- // The name is not defined in the function. If we are in the global
- // scope, then we have an undefined variable.
- //
- // Operators typeof and delete do not raise runtime errors even if
- // the base object of a reference is null so no need to display warning
- // if we're inside of typeof or delete.
-
- if (typeof predefined[v] !== "boolean") {
- // Attempting to subscript a null reference will throw an
- // error, even within the typeof and delete operators
- if (!(anonname === "typeof" || anonname === "delete") ||
- (state.tokens.next && (state.tokens.next.value === "." ||
- state.tokens.next.value === "["))) {
-
- // if we're in a list comprehension, variables are declared
- // locally and used before being defined. So we check
- // the presence of the given variable in the comp array
- // before declaring it undefined.
-
- if (!funct["(comparray)"].check(v)) {
- isundef(funct, "W117", state.tokens.curr, v);
- }
- }
- }
-
- note_implied(state.tokens.curr);
- } else {
- // If the name is already defined in the current
- // function, but not as outer, then there is a scope error.
-
- switch (funct[v]) {
- case "closure":
- case "function":
- case "var":
- case "unused":
- warning("W038", state.tokens.curr, v);
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- break;
- case "outer":
- case "global":
- break;
- default:
- // If the name is defined in an outer function, make an outer entry,
- // and if it was unused, make it var.
- if (s === true) {
- funct[v] = true;
- } else if (s === null) {
- warning("W039", state.tokens.curr, v);
- note_implied(state.tokens.curr);
- } else if (typeof s !== "object") {
- // Operators typeof and delete do not raise runtime errors even
- // if the base object of a reference is null so no need to
- //
- // display warning if we're inside of typeof or delete.
- // Attempting to subscript a null reference will throw an
- // error, even within the typeof and delete operators
- if (!(anonname === "typeof" || anonname === "delete") ||
- (state.tokens.next &&
- (state.tokens.next.value === "." || state.tokens.next.value === "["))) {
-
- isundef(funct, "W117", state.tokens.curr, v);
- }
- funct[v] = true;
- note_implied(state.tokens.curr);
- } else {
- switch (s[v]) {
- case "function":
- case "unction":
- this["function"] = true;
- s[v] = "closure";
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "var":
- case "unused":
- s[v] = "closure";
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "closure":
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- }
- }
- }
- }
- return this;
- },
- led: function () {
- error("E033", state.tokens.next, state.tokens.next.value);
- }
- };
-
- type("(regexp)", function () {
- return this;
- });
-
- // ECMAScript parser
-
- delim("(endline)");
- delim("(begin)");
- delim("(end)").reach = true;
- delim("(error)").reach = true;
- delim("}").reach = true;
- delim(")");
- delim("]");
- delim("\"").reach = true;
- delim("'").reach = true;
- delim(";");
- delim(":").reach = true;
- delim("#");
-
- reserve("else");
- reserve("case").reach = true;
- reserve("catch");
- reserve("default").reach = true;
- reserve("finally");
- reservevar("arguments", function (x) {
- if (state.directive["use strict"] && funct["(global)"]) {
- warning("E008", x);
- }
- });
- reservevar("eval");
- reservevar("false");
- reservevar("Infinity");
- reservevar("null");
- reservevar("this", function (x) {
- if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
- funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
- warning("W040", x);
- }
- });
- reservevar("true");
- reservevar("undefined");
-
- assignop("=", "assign", 20);
- assignop("+=", "assignadd", 20);
- assignop("-=", "assignsub", 20);
- assignop("*=", "assignmult", 20);
- assignop("/=", "assigndiv", 20).nud = function () {
- error("E014");
- };
- assignop("%=", "assignmod", 20);
-
- bitwiseassignop("&=", "assignbitand", 20);
- bitwiseassignop("|=", "assignbitor", 20);
- bitwiseassignop("^=", "assignbitxor", 20);
- bitwiseassignop("<<=", "assignshiftleft", 20);
- bitwiseassignop(">>=", "assignshiftright", 20);
- bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
- infix(",", function (left, that) {
- var expr;
- that.exprs = [left];
- if (!comma({peek: true})) {
- return that;
- }
- while (true) {
- if (!(expr = expression(5))) {
- break;
- }
- that.exprs.push(expr);
- if (state.tokens.next.value !== "," || !comma()) {
- break;
- }
- }
- return that;
- }, 5, true);
- infix("?", function (left, that) {
- that.left = left;
- that.right = expression(10);
- advance(":");
- that["else"] = expression(10);
- return that;
- }, 30);
-
- infix("||", "or", 40);
- infix("&&", "and", 50);
- bitwise("|", "bitor", 70);
- bitwise("^", "bitxor", 80);
- bitwise("&", "bitand", 90);
- relation("==", function (left, right) {
- var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
-
- if (!eqnull && state.option.eqeqeq)
- warning("W116", this, "===", "==");
- else if (isPoorRelation(left))
- warning("W041", this, "===", left.value);
- else if (isPoorRelation(right))
- warning("W041", this, "===", right.value);
-
- return this;
- });
- relation("===");
- relation("!=", function (left, right) {
- var eqnull = state.option.eqnull &&
- (left.value === "null" || right.value === "null");
-
- if (!eqnull && state.option.eqeqeq) {
- warning("W116", this, "!==", "!=");
- } else if (isPoorRelation(left)) {
- warning("W041", this, "!==", left.value);
- } else if (isPoorRelation(right)) {
- warning("W041", this, "!==", right.value);
- }
- return this;
- });
- relation("!==");
- relation("<");
- relation(">");
- relation("<=");
- relation(">=");
- bitwise("<<", "shiftleft", 120);
- bitwise(">>", "shiftright", 120);
- bitwise(">>>", "shiftrightunsigned", 120);
- infix("in", "in", 120);
- infix("instanceof", "instanceof", 120);
- infix("+", function (left, that) {
- var right = expression(130);
- if (left && right && left.id === "(string)" && right.id === "(string)") {
- left.value += right.value;
- left.character = right.character;
- if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
- warning("W050", left);
- }
- return left;
- }
- that.left = left;
- that.right = right;
- return that;
- }, 130);
- prefix("+", "num");
- prefix("+++", function () {
- warning("W007");
- this.right = expression(150);
- this.arity = "unary";
- return this;
- });
- infix("+++", function (left) {
- warning("W007");
- this.left = left;
- this.right = expression(130);
- return this;
- }, 130);
- infix("-", "sub", 130);
- prefix("-", "neg");
- prefix("---", function () {
- warning("W006");
- this.right = expression(150);
- this.arity = "unary";
- return this;
- });
- infix("---", function (left) {
- warning("W006");
- this.left = left;
- this.right = expression(130);
- return this;
- }, 130);
- infix("*", "mult", 140);
- infix("/", "div", 140);
- infix("%", "mod", 140);
-
- suffix("++", "postinc");
- prefix("++", "preinc");
- state.syntax["++"].exps = true;
-
- suffix("--", "postdec");
- prefix("--", "predec");
- state.syntax["--"].exps = true;
- prefix("delete", function () {
- var p = expression(5);
- if (!p || (p.id !== "." && p.id !== "[")) {
- warning("W051");
- }
- this.first = p;
- return this;
- }).exps = true;
-
- prefix("~", function () {
- if (state.option.bitwise) {
- warning("W052", this, "~");
- }
- expression(150);
- return this;
- });
-
- prefix("...", function () {
- if (!state.option.inESNext()) {
- warning("W104", this, "spread/rest operator");
- }
- if (!state.tokens.next.identifier) {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- expression(150);
- return this;
- });
-
- prefix("!", function () {
- this.right = expression(150);
- this.arity = "unary";
-
- if (!this.right) { // '!' followed by nothing? Give up.
- quit("E041", this.line || 0);
- }
-
- if (bang[this.right.id] === true) {
- warning("W018", this, "!");
- }
- return this;
- });
-
- prefix("typeof", "typeof");
- prefix("new", function () {
- var c = expression(155), i;
- if (c && c.id !== "function") {
- if (c.identifier) {
- c["new"] = true;
- switch (c.value) {
- case "Number":
- case "String":
- case "Boolean":
- case "Math":
- case "JSON":
- warning("W053", state.tokens.prev, c.value);
- break;
- case "Function":
- if (!state.option.evil) {
- warning("W054");
- }
- break;
- case "Date":
- case "RegExp":
- break;
- default:
- if (c.id !== "function") {
- i = c.value.substr(0, 1);
- if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) {
- warning("W055", state.tokens.curr);
- }
- }
- }
- } else {
- if (c.id !== "." && c.id !== "[" && c.id !== "(") {
- warning("W056", state.tokens.curr);
- }
- }
- } else {
- if (!state.option.supernew)
- warning("W057", this);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id !== "(" && !state.option.supernew) {
- warning("W058", state.tokens.curr, state.tokens.curr.value);
- }
- this.first = c;
- return this;
- });
- state.syntax["new"].exps = true;
-
- prefix("void").exps = true;
-
- infix(".", function (left, that) {
- adjacent(state.tokens.prev, state.tokens.curr);
- nobreak();
- var m = identifier(false, true);
-
- if (typeof m === "string") {
- countMember(m);
- }
-
- that.left = left;
- that.right = m;
-
- if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
- warning("W001");
- }
-
- if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
- if (state.option.noarg)
- warning("W059", left, m);
- else if (state.directive["use strict"])
- error("E008");
- } else if (!state.option.evil && left && left.value === "document" &&
- (m === "write" || m === "writeln")) {
- warning("W060", left);
- }
-
- if (!state.option.evil && (m === "eval" || m === "execScript")) {
- warning("W061");
- }
-
- return that;
- }, 160, true);
-
- infix("(", function (left, that) {
- if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
- nobreak(state.tokens.prev, state.tokens.curr);
- }
-
- nospace();
- if (state.option.immed && left && !left.immed && left.id === "function") {
- warning("W062");
- }
-
- var n = 0;
- var p = [];
-
- if (left) {
- if (left.type === "(identifier)") {
- if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
- if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
- if (left.value === "Math") {
- warning("W063", left);
- } else if (state.option.newcap) {
- warning("W064", left);
- }
- }
- }
- }
- }
-
- if (state.tokens.next.id !== ")") {
- for (;;) {
- p[p.length] = expression(10);
- n += 1;
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
-
- advance(")");
- nospace(state.tokens.prev, state.tokens.curr);
-
- if (typeof left === "object") {
- if (left.value === "parseInt" && n === 1) {
- warning("W065", state.tokens.curr);
- }
- if (!state.option.evil) {
- if (left.value === "eval" || left.value === "Function" ||
- left.value === "execScript") {
- warning("W061", left);
-
- if (p[0] && [0].id === "(string)") {
- addInternalSrc(left, p[0].value);
- }
- } else if (p[0] && p[0].id === "(string)" &&
- (left.value === "setTimeout" ||
- left.value === "setInterval")) {
- warning("W066", left);
- addInternalSrc(left, p[0].value);
-
- // window.setTimeout/setInterval
- } else if (p[0] && p[0].id === "(string)" &&
- left.value === "." &&
- left.left.value === "window" &&
- (left.right === "setTimeout" ||
- left.right === "setInterval")) {
- warning("W066", left);
- addInternalSrc(left, p[0].value);
- }
- }
- if (!left.identifier && left.id !== "." && left.id !== "[" &&
- left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
- left.id !== "?") {
- warning("W067", left);
- }
- }
-
- that.left = left;
- return that;
- }, 155, true).exps = true;
-
- prefix("(", function () {
- nospace();
- var bracket, brackets = [];
- var pn, pn1, i = 0;
-
- do {
- pn = peek(i);
- i += 1;
- pn1 = peek(i);
- i += 1;
- } while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");
-
- if (state.tokens.next.id === "function") {
- state.tokens.next.immed = true;
- }
-
- var exprs = [];
-
- if (state.tokens.next.id !== ")") {
- for (;;) {
- if (pn1.value === "=>" && state.tokens.next.value === "{") {
- bracket = state.tokens.next;
- bracket.left = destructuringExpression();
- brackets.push(bracket);
- for (var t in bracket.left) {
- exprs.push(bracket.left[t].token);
- }
- } else {
- exprs.push(expression(5));
- }
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
-
- advance(")", this);
- nospace(state.tokens.prev, state.tokens.curr);
- if (state.option.immed && exprs[0] && exprs[0].id === "function") {
- if (state.tokens.next.id !== "(" &&
- (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
- warning("W068", this);
- }
- }
-
- if (state.tokens.next.value === "=>") {
- return exprs;
- }
- if (!exprs.length) {
- return;
- }
- exprs[exprs.length - 1].paren = true;
- if (exprs.length > 1) {
- return Object.create(state.syntax[","], { exprs: { value: exprs } });
- }
- return exprs[0];
- });
-
- application("=>");
-
- infix("[", function (left, that) {
- nobreak(state.tokens.prev, state.tokens.curr);
- nospace();
- var e = expression(5), s;
- if (e && e.type === "(string)") {
- if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
- warning("W061", that);
- }
-
- countMember(e.value);
- if (!state.option.sub && reg.identifier.test(e.value)) {
- s = state.syntax[e.value];
- if (!s || !isReserved(s)) {
- warning("W069", state.tokens.prev, e.value);
- }
- }
- }
- advance("]", that);
-
- if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
- warning("W001");
- }
-
- nospace(state.tokens.prev, state.tokens.curr);
- that.left = left;
- that.right = e;
- return that;
- }, 160, true);
-
- function comprehensiveArrayExpression() {
- var res = {};
- res.exps = true;
- funct["(comparray)"].stack();
-
- res.right = expression(5);
- advance("for");
- if (state.tokens.next.value === "each") {
- advance("each");
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "for each");
- }
- }
- advance("(");
- funct["(comparray)"].setState("define");
- res.left = expression(5);
- advance(")");
- if (state.tokens.next.value === "if") {
- advance("if");
- advance("(");
- funct["(comparray)"].setState("filter");
- res.filter = expression(5);
- advance(")");
- }
- advance("]");
- funct["(comparray)"].unstack();
- return res;
- }
-
- prefix("[", function () {
- var blocktype = lookupBlockType(true);
- if (blocktype.isCompArray) {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "array comprehension");
- }
- return comprehensiveArrayExpression();
- } else if (blocktype.isDestAssign && !state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring assignment");
- }
- var b = state.tokens.curr.line !== state.tokens.next.line;
- this.first = [];
- if (b) {
- indent += state.option.indent;
- if (state.tokens.next.from === indent + state.option.indent) {
- indent += state.option.indent;
- }
- }
- while (state.tokens.next.id !== "(end)") {
- while (state.tokens.next.id === ",") {
- if (!state.option.inES5())
- warning("W070");
- advance(",");
- }
- if (state.tokens.next.id === "]") {
- break;
- }
- if (b && state.tokens.curr.line !== state.tokens.next.line) {
- indentation();
- }
- this.first.push(expression(10));
- if (state.tokens.next.id === ",") {
- comma({ allowTrailing: true });
- if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
- warning("W070", state.tokens.curr);
- break;
- }
- } else {
- break;
- }
- }
- if (b) {
- indent -= state.option.indent;
- indentation();
- }
- advance("]", this);
- return this;
- }, 160);
-
-
- function property_name() {
- var id = optionalidentifier(false, true);
-
- if (!id) {
- if (state.tokens.next.id === "(string)") {
- id = state.tokens.next.value;
- advance();
- } else if (state.tokens.next.id === "(number)") {
- id = state.tokens.next.value.toString();
- advance();
- }
- }
-
- if (id === "hasOwnProperty") {
- warning("W001");
- }
-
- return id;
- }
-
-
- function functionparams(parsed) {
- var curr, next;
- var params = [];
- var ident;
- var tokens = [];
- var t;
-
- if (parsed) {
- if (parsed instanceof Array) {
- for (var i in parsed) {
- curr = parsed[i];
- if (_.contains(["{", "["], curr.id)) {
- for (t in curr.left) {
- t = tokens[t];
- if (t.id) {
- params.push(t.id);
- addlabel(t.id, "unused", t.token);
- }
- }
- } else if (curr.value === "...") {
- if (!state.option.inESNext()) {
- warning("W104", curr, "spread/rest operator");
- }
- continue;
- } else {
- addlabel(curr.value, "unused", curr);
- }
- }
- return params;
- } else {
- if (parsed.identifier === true) {
- addlabel(parsed.value, "unused", parsed);
- return [parsed];
- }
- }
- }
-
- next = state.tokens.next;
-
- advance("(");
- nospace();
-
- if (state.tokens.next.id === ")") {
- advance(")");
- return;
- }
-
- for (;;) {
- if (_.contains(["{", "["], state.tokens.next.id)) {
- tokens = destructuringExpression();
- for (t in tokens) {
- t = tokens[t];
- if (t.id) {
- params.push(t.id);
- addlabel(t.id, "unused", t.token);
- }
- }
- } else if (state.tokens.next.value === "...") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.next, "spread/rest operator");
- }
- advance("...");
- nospace();
- ident = identifier(true);
- params.push(ident);
- addlabel(ident, "unused", state.tokens.curr);
- } else {
- ident = identifier(true);
- params.push(ident);
- addlabel(ident, "unused", state.tokens.curr);
- }
- if (state.tokens.next.id === ",") {
- comma();
- } else {
- advance(")", next);
- nospace(state.tokens.prev, state.tokens.curr);
- return params;
- }
- }
- }
-
-
- function doFunction(name, statement, generator, fatarrowparams) {
- var f;
- var oldOption = state.option;
- var oldIgnored = state.ignored;
- var oldScope = scope;
-
- state.option = Object.create(state.option);
- state.ignored = Object.create(state.ignored);
- scope = Object.create(scope);
-
- funct = {
- "(name)" : name || "\"" + anonname + "\"",
- "(line)" : state.tokens.next.line,
- "(character)" : state.tokens.next.character,
- "(context)" : funct,
- "(breakage)" : 0,
- "(loopage)" : 0,
- "(metrics)" : createMetrics(state.tokens.next),
- "(scope)" : scope,
- "(statement)" : statement,
- "(tokens)" : {},
- "(blockscope)": funct["(blockscope)"],
- "(comparray)" : funct["(comparray)"]
- };
-
- if (generator) {
- funct["(generator)"] = true;
- }
-
- f = funct;
- state.tokens.curr.funct = funct;
-
- functions.push(funct);
-
- if (name) {
- addlabel(name, "function");
- }
-
- funct["(params)"] = functionparams(fatarrowparams);
-
- funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
-
- block(false, true, true, fatarrowparams ? true:false);
-
- if (generator && funct["(generator)"] !== "yielded") {
- error("E047", state.tokens.curr);
- }
-
- funct["(metrics)"].verifyMaxStatementsPerFunction();
- funct["(metrics)"].verifyMaxComplexityPerFunction();
- funct["(unusedOption)"] = state.option.unused;
-
- scope = oldScope;
- state.option = oldOption;
- state.ignored = oldIgnored;
- funct["(last)"] = state.tokens.curr.line;
- funct["(lastcharacter)"] = state.tokens.curr.character;
- funct = funct["(context)"];
-
- return f;
- }
-
- function createMetrics(functionStartToken) {
- return {
- statementCount: 0,
- nestedBlockDepth: -1,
- ComplexityCount: 1,
- verifyMaxStatementsPerFunction: function () {
- if (state.option.maxstatements &&
- this.statementCount > state.option.maxstatements) {
- warning("W071", functionStartToken, this.statementCount);
- }
- },
-
- verifyMaxParametersPerFunction: function (params) {
- params = params || [];
-
- if (state.option.maxparams && params.length > state.option.maxparams) {
- warning("W072", functionStartToken, params.length);
- }
- },
-
- verifyMaxNestedBlockDepthPerFunction: function () {
- if (state.option.maxdepth &&
- this.nestedBlockDepth > 0 &&
- this.nestedBlockDepth === state.option.maxdepth + 1) {
- warning("W073", null, this.nestedBlockDepth);
- }
- },
-
- verifyMaxComplexityPerFunction: function () {
- var max = state.option.maxcomplexity;
- var cc = this.ComplexityCount;
- if (max && cc > max) {
- warning("W074", functionStartToken, cc);
- }
- }
- };
- }
-
- function increaseComplexityCount() {
- funct["(metrics)"].ComplexityCount += 1;
- }
-
- // Parse assignments that were found instead of conditionals.
- // For example: if (a = 1) { ... }
-
- function checkCondAssignment(expr) {
- var id = expr.id;
- if (id === ",") {
- expr = expr.exprs[expr.exprs.length - 1];
- id = expr.id;
- }
- switch (id) {
- case "=":
- case "+=":
- case "-=":
- case "*=":
- case "%=":
- case "&=":
- case "|=":
- case "^=":
- case "/=":
- if (!expr.paren && !state.option.boss) {
- warning("W084");
- }
- }
- }
-
-
- (function (x) {
- x.nud = function (isclassdef) {
- var b, f, i, p, t, g;
- var props = {}; // All properties, including accessors
- var tag = "";
-
- function saveProperty(name, tkn) {
- if (props[name] && _.has(props, name))
- warning("W075", state.tokens.next, i);
- else
- props[name] = {};
-
- props[name].basic = true;
- props[name].basictkn = tkn;
- }
-
- function saveSetter(name, tkn) {
- if (props[name] && _.has(props, name)) {
- if (props[name].basic || props[name].setter)
- warning("W075", state.tokens.next, i);
- } else {
- props[name] = {};
- }
-
- props[name].setter = true;
- props[name].setterToken = tkn;
- }
-
- function saveGetter(name) {
- if (props[name] && _.has(props, name)) {
- if (props[name].basic || props[name].getter)
- warning("W075", state.tokens.next, i);
- } else {
- props[name] = {};
- }
-
- props[name].getter = true;
- props[name].getterToken = state.tokens.curr;
- }
-
- b = state.tokens.curr.line !== state.tokens.next.line;
- if (b) {
- indent += state.option.indent;
- if (state.tokens.next.from === indent + state.option.indent) {
- indent += state.option.indent;
- }
- }
-
- for (;;) {
- if (state.tokens.next.id === "}") {
- break;
- }
-
- if (b) {
- indentation();
- }
-
- if (isclassdef && state.tokens.next.value === "static") {
- advance("static");
- tag = "static ";
- }
-
- if (state.tokens.next.value === "get" && peek().id !== ":") {
- advance("get");
-
- if (!state.option.inES5(!isclassdef)) {
- error("E034");
- }
-
- i = property_name();
- if (!i) {
- error("E035");
- }
-
- // It is a Syntax Error if PropName of MethodDefinition is
- // "constructor" and SpecialMethod of MethodDefinition is true.
- if (isclassdef && i === "constructor") {
- error("E049", state.tokens.next, "class getter method", i);
- }
-
- saveGetter(tag + i);
- t = state.tokens.next;
- adjacent(state.tokens.curr, state.tokens.next);
- f = doFunction();
- p = f["(params)"];
-
- if (p) {
- warning("W076", t, p[0], i);
- }
-
- adjacent(state.tokens.curr, state.tokens.next);
- } else if (state.tokens.next.value === "set" && peek().id !== ":") {
- advance("set");
-
- if (!state.option.inES5(!isclassdef)) {
- error("E034");
- }
-
- i = property_name();
- if (!i) {
- error("E035");
- }
-
- // It is a Syntax Error if PropName of MethodDefinition is
- // "constructor" and SpecialMethod of MethodDefinition is true.
- if (isclassdef && i === "constructor") {
- error("E049", state.tokens.next, "class setter method", i);
- }
-
- saveSetter(tag + i, state.tokens.next);
- t = state.tokens.next;
- adjacent(state.tokens.curr, state.tokens.next);
- f = doFunction();
- p = f["(params)"];
-
- if (!p || p.length !== 1) {
- warning("W077", t, i);
- }
- } else {
- g = false;
- if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.next, "generator functions");
- }
- advance("*");
- g = true;
- }
- i = property_name();
- saveProperty(tag + i, state.tokens.next);
-
- if (typeof i !== "string") {
- break;
- }
-
- if (state.tokens.next.value === "(") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "concise methods");
- }
- doFunction(i, undefined, g);
- } else if (!isclassdef) {
- advance(":");
- nonadjacent(state.tokens.curr, state.tokens.next);
- expression(10);
- }
- }
- // It is a Syntax Error if PropName of MethodDefinition is "prototype".
- if (isclassdef && i === "prototype") {
- error("E049", state.tokens.next, "class method", i);
- }
-
- countMember(i);
- if (isclassdef) {
- tag = "";
- continue;
- }
- if (state.tokens.next.id === ",") {
- comma({ allowTrailing: true, property: true });
- if (state.tokens.next.id === ",") {
- warning("W070", state.tokens.curr);
- } else if (state.tokens.next.id === "}" && !state.option.inES5(true)) {
- warning("W070", state.tokens.curr);
- }
- } else {
- break;
- }
- }
- if (b) {
- indent -= state.option.indent;
- indentation();
- }
- advance("}", this);
-
- // Check for lonely setters if in the ES5 mode.
- if (state.option.inES5()) {
- for (var name in props) {
- if (_.has(props, name) && props[name].setter && !props[name].getter) {
- warning("W078", props[name].setterToken);
- }
- }
- }
- return this;
- };
- x.fud = function () {
- error("E036", state.tokens.curr);
- };
- }(delim("{")));
-
- function destructuringExpression() {
- var id, ids;
- var identifiers = [];
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring expression");
- }
- var nextInnerDE = function () {
- var ident;
- if (_.contains(["[", "{"], state.tokens.next.value)) {
- ids = destructuringExpression();
- for (var id in ids) {
- id = ids[id];
- identifiers.push({ id: id.id, token: id.token });
- }
- } else if (state.tokens.next.value === ",") {
- identifiers.push({ id: null, token: state.tokens.curr });
- } else {
- ident = identifier();
- if (ident)
- identifiers.push({ id: ident, token: state.tokens.curr });
- }
- };
- if (state.tokens.next.value === "[") {
- advance("[");
- nextInnerDE();
- while (state.tokens.next.value !== "]") {
- advance(",");
- nextInnerDE();
- }
- advance("]");
- } else if (state.tokens.next.value === "{") {
- advance("{");
- id = identifier();
- if (state.tokens.next.value === ":") {
- advance(":");
- nextInnerDE();
- } else {
- identifiers.push({ id: id, token: state.tokens.curr });
- }
- while (state.tokens.next.value !== "}") {
- advance(",");
- id = identifier();
- if (state.tokens.next.value === ":") {
- advance(":");
- nextInnerDE();
- } else {
- identifiers.push({ id: id, token: state.tokens.curr });
- }
- }
- advance("}");
- }
- return identifiers;
- }
- function destructuringExpressionMatch(tokens, value) {
- if (value.first) {
- _.zip(tokens, value.first).forEach(function (val) {
- var token = val[0];
- var value = val[1];
- if (token && value) {
- token.first = value;
- } else if (token && token.first && !value) {
- warning("W080", token.first, token.first.value);
- } /* else {
- XXX value is discarded: wouldn't it need a warning ?
- } */
- });
- }
- }
-
- var conststatement = stmt("const", function (prefix) {
- var tokens, value;
- // state variable to know if it is a lone identifier, or a destructuring statement.
- var lone;
-
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "const");
- }
-
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id) {
- addlabel(t.id, "const");
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
-
- this.first = this.first.concat(names);
-
- if (state.tokens.next.id !== "=") {
- warning("E012", state.tokens.curr, state.tokens.curr.value);
- }
-
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- error("E037", state.tokens.next, state.tokens.next.value);
- }
- value = expression(5);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
-
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- return this;
- });
- conststatement.exps = true;
- var varstatement = stmt("var", function (prefix) {
- // JavaScript does not have block scope. It only has function scope. So,
- // declaring a variable in a block can have unexpected consequences.
- var tokens, lone, value;
-
- if (funct["(onevar)"] && state.option.onevar) {
- warning("W081");
- } else if (!funct["(global)"]) {
- funct["(onevar)"] = true;
- }
-
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (state.option.inESNext() && funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id) {
- addlabel(t.id, "unused", t.token);
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
-
- this.first = this.first.concat(names);
-
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- error("E038", state.tokens.next, state.tokens.next.value);
- }
- value = expression(5);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
-
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- return this;
- });
- varstatement.exps = true;
- var letstatement = stmt("let", function (prefix) {
- var tokens, lone, value, letblock;
-
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "let");
- }
-
- if (state.tokens.next.value === "(") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.next, "let block");
- }
- advance("(");
- funct["(blockscope)"].stack();
- letblock = true;
- } else if (funct["(nolet)"]) {
- error("E048", state.tokens.curr);
- }
-
- if (funct["(onevar)"] && state.option.onevar) {
- warning("W081");
- } else if (!funct["(global)"]) {
- funct["(onevar)"] = true;
- }
-
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr.value } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (state.option.inESNext() && funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id && !funct["(nolet)"]) {
- addlabel(t.id, "unused", t.token, true);
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
-
- this.first = this.first.concat(names);
-
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- error("E037", state.tokens.next, state.tokens.next.value);
- }
- value = expression(5);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
-
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- if (letblock) {
- advance(")");
- block(true, true);
- this.block = true;
- funct["(blockscope)"].unstack();
- }
-
- return this;
- });
- letstatement.exps = true;
-
- blockstmt("class", function () {
- return classdef.call(this, true);
- });
-
- function classdef(stmt) {
- /*jshint validthis:true */
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "class");
- }
- if (stmt) {
- // BindingIdentifier
- this.name = identifier();
- addlabel(this.name, "unused", state.tokens.curr);
- } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
- // BindingIdentifier(opt)
- this.name = identifier();
- }
- classtail(this);
- return this;
- }
-
- function classtail(c) {
- var strictness = state.directive["use strict"];
-
- // ClassHeritage(opt)
- if (state.tokens.next.value === "extends") {
- advance("extends");
- c.heritage = expression(10);
- }
-
- // A ClassBody is always strict code.
- state.directive["use strict"] = true;
- advance("{");
- // ClassBody(opt)
- c.body = state.syntax["{"].nud(true);
- state.directive["use strict"] = strictness;
- }
-
- blockstmt("function", function () {
- var generator = false;
- if (state.tokens.next.value === "*") {
- advance("*");
- if (state.option.inESNext(true)) {
- generator = true;
- } else {
- warning("W119", state.tokens.curr, "function*");
- }
- }
- if (inblock) {
- warning("W082", state.tokens.curr);
-
- }
- var i = identifier();
- if (funct[i] === "const") {
- warning("E011", null, i);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- addlabel(i, "unction", state.tokens.curr);
-
- doFunction(i, { statement: true }, generator);
- if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {
- error("E039");
- }
- return this;
- });
-
- prefix("function", function () {
- var generator = false;
- if (state.tokens.next.value === "*") {
- if (!state.option.inESNext()) {
- warning("W119", state.tokens.curr, "function*");
- }
- advance("*");
- generator = true;
- }
- var i = optionalidentifier();
- if (i || state.option.gcl) {
- adjacent(state.tokens.curr, state.tokens.next);
- } else {
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- doFunction(i, undefined, generator);
- if (!state.option.loopfunc && funct["(loopage)"]) {
- warning("W083");
- }
- return this;
- });
-
- blockstmt("if", function () {
- var t = state.tokens.next;
- increaseComplexityCount();
- state.condition = true;
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- state.condition = false;
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- if (state.tokens.next.id === "else") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("else");
- if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
- statement(true);
- } else {
- block(true, true);
- }
- }
- return this;
- });
-
- blockstmt("try", function () {
- var b;
-
- function doCatch() {
- var oldScope = scope;
- var e;
-
- advance("catch");
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("(");
-
- scope = Object.create(oldScope);
-
- e = state.tokens.next.value;
- if (state.tokens.next.type !== "(identifier)") {
- e = null;
- warning("E030", state.tokens.next, e);
- }
-
- advance();
-
- funct = {
- "(name)" : "(catch)",
- "(line)" : state.tokens.next.line,
- "(character)": state.tokens.next.character,
- "(context)" : funct,
- "(breakage)" : funct["(breakage)"],
- "(loopage)" : funct["(loopage)"],
- "(scope)" : scope,
- "(statement)": false,
- "(metrics)" : createMetrics(state.tokens.next),
- "(catch)" : true,
- "(tokens)" : {},
- "(blockscope)": funct["(blockscope)"],
- "(comparray)": funct["(comparray)"]
- };
-
- if (e) {
- addlabel(e, "exception");
- }
-
- if (state.tokens.next.value === "if") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "catch filter");
- }
- advance("if");
- expression(0);
- }
-
- advance(")");
-
- state.tokens.curr.funct = funct;
- functions.push(funct);
-
- block(false);
-
- scope = oldScope;
-
- funct["(last)"] = state.tokens.curr.line;
- funct["(lastcharacter)"] = state.tokens.curr.character;
- funct = funct["(context)"];
- }
-
- block(false);
-
- while (state.tokens.next.id === "catch") {
- increaseComplexityCount();
- if (b && (!state.option.inMoz(true))) {
- warning("W118", state.tokens.next, "multiple catch blocks");
- }
- doCatch();
- b = true;
- }
-
- if (state.tokens.next.id === "finally") {
- advance("finally");
- block(false);
- return;
- }
-
- if (!b) {
- error("E021", state.tokens.next, "catch", state.tokens.next.value);
- }
-
- return this;
- });
-
- blockstmt("while", function () {
- var t = state.tokens.next;
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- return this;
- }).labelled = true;
-
- blockstmt("with", function () {
- var t = state.tokens.next;
- if (state.directive["use strict"]) {
- error("E010", state.tokens.curr);
- } else if (!state.option.withstmt) {
- warning("W085", state.tokens.curr);
- }
-
- advance("(");
- nonadjacent(this, t);
- nospace();
- expression(0);
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
-
- return this;
- });
-
- blockstmt("switch", function () {
- var t = state.tokens.next,
- g = false;
- funct["(breakage)"] += 1;
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- t = state.tokens.next;
- advance("{");
- nonadjacent(state.tokens.curr, state.tokens.next);
- indent += state.option.indent;
- this.cases = [];
-
- for (;;) {
- switch (state.tokens.next.id) {
- case "case":
- switch (funct["(verb)"]) {
- case "yield":
- case "break":
- case "case":
- case "continue":
- case "return":
- case "switch":
- case "throw":
- break;
- default:
- // You can tell JSHint that you don't use break intentionally by
- // adding a comment /* falls through */ on a line just before
- // the next `case`.
- if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
- warning("W086", state.tokens.curr, "case");
- }
- }
- indentation(-state.option.indent);
- advance("case");
- this.cases.push(expression(20));
- increaseComplexityCount();
- g = true;
- advance(":");
- funct["(verb)"] = "case";
- break;
- case "default":
- switch (funct["(verb)"]) {
- case "yield":
- case "break":
- case "continue":
- case "return":
- case "throw":
- break;
- default:
- // Do not display a warning if 'default' is the first statement or if
- // there is a special /* falls through */ comment.
- if (this.cases.length) {
- if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
- warning("W086", state.tokens.curr, "default");
- }
- }
- }
- indentation(-state.option.indent);
- advance("default");
- g = true;
- advance(":");
- break;
- case "}":
- indent -= state.option.indent;
- indentation();
- advance("}", t);
- funct["(breakage)"] -= 1;
- funct["(verb)"] = undefined;
- return;
- case "(end)":
- error("E023", state.tokens.next, "}");
- return;
- default:
- if (g) {
- switch (state.tokens.curr.id) {
- case ",":
- error("E040");
- return;
- case ":":
- g = false;
- statements();
- break;
- default:
- error("E025", state.tokens.curr);
- return;
- }
- } else {
- if (state.tokens.curr.id === ":") {
- advance(":");
- error("E024", state.tokens.curr, ":");
- statements();
- } else {
- error("E021", state.tokens.next, "case", state.tokens.next.value);
- return;
- }
- }
- }
- }
- }).labelled = true;
-
- stmt("debugger", function () {
- if (!state.option.debug) {
- warning("W087");
- }
- return this;
- }).exps = true;
-
- (function () {
- var x = stmt("do", function () {
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
-
- this.first = block(true, true);
- advance("while");
- var t = state.tokens.next;
- nonadjacent(state.tokens.curr, t);
- advance("(");
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- return this;
- });
- x.labelled = true;
- x.exps = true;
- }());
-
- blockstmt("for", function () {
- var s, t = state.tokens.next;
- var letscope = false;
- var foreachtok = null;
-
- if (t.value === "each") {
- foreachtok = t;
- advance("each");
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "for each");
- }
- }
-
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
- advance("(");
- nonadjacent(this, t);
- nospace();
-
- // what kind of for(…) statement it is? for(…of…)? for(…in…)? for(…;…;…)?
- var nextop; // contains the token of the "in" or "of" operator
- var i = 0;
- var inof = ["in", "of"];
- do {
- nextop = peek(i);
- ++i;
- } while (!_.contains(inof, nextop.value) && nextop.value !== ";" &&
- nextop.type !== "(end)");
-
- // if we're in a for (… in|of …) statement
- if (_.contains(inof, nextop.value)) {
- if (!state.option.inESNext() && nextop.value === "of") {
- error("W104", nextop, "for of");
- }
- if (state.tokens.next.id === "var") {
- advance("var");
- state.syntax["var"].fud.call(state.syntax["var"].fud, true);
- } else if (state.tokens.next.id === "let") {
- advance("let");
- // create a new block scope
- letscope = true;
- funct["(blockscope)"].stack();
- state.syntax["let"].fud.call(state.syntax["let"].fud, true);
- } else {
- switch (funct[state.tokens.next.value]) {
- case "unused":
- funct[state.tokens.next.value] = "var";
- break;
- case "var":
- break;
- default:
- if (!funct["(blockscope)"].getlabel(state.tokens.next.value))
- warning("W088", state.tokens.next, state.tokens.next.value);
- }
- advance();
- }
- advance(nextop.value);
- expression(20);
- advance(")", t);
- s = block(true, true);
- if (state.option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
- s[0].value !== "if")) {
- warning("W089", this);
- }
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- } else {
- if (foreachtok) {
- error("E045", foreachtok);
- }
- if (state.tokens.next.id !== ";") {
- if (state.tokens.next.id === "var") {
- advance("var");
- state.syntax["var"].fud.call(state.syntax["var"].fud);
- } else if (state.tokens.next.id === "let") {
- advance("let");
- // create a new block scope
- letscope = true;
- funct["(blockscope)"].stack();
- state.syntax["let"].fud.call(state.syntax["let"].fud);
- } else {
- for (;;) {
- expression(0, "for");
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
- }
- nolinebreak(state.tokens.curr);
- advance(";");
- if (state.tokens.next.id !== ";") {
- checkCondAssignment(expression(0));
- }
- nolinebreak(state.tokens.curr);
- advance(";");
- if (state.tokens.next.id === ";") {
- error("E021", state.tokens.next, ")", ";");
- }
- if (state.tokens.next.id !== ")") {
- for (;;) {
- expression(0, "for");
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
-
- }
- // unstack loop blockscope
- if (letscope) {
- funct["(blockscope)"].unstack();
- }
- return this;
- }).labelled = true;
-
-
- stmt("break", function () {
- var v = state.tokens.next.value;
-
- if (funct["(breakage)"] === 0)
- warning("W052", state.tokens.next, this.value);
-
- if (!state.option.asi)
- nolinebreak(this);
-
- if (state.tokens.next.id !== ";") {
- if (state.tokens.curr.line === state.tokens.next.line) {
- if (funct[v] !== "label") {
- warning("W090", state.tokens.next, v);
- } else if (scope[v] !== funct) {
- warning("W091", state.tokens.next, v);
- }
- this.first = state.tokens.next;
- advance();
- }
- }
- reachable("break");
- return this;
- }).exps = true;
-
-
- stmt("continue", function () {
- var v = state.tokens.next.value;
-
- if (funct["(breakage)"] === 0)
- warning("W052", state.tokens.next, this.value);
-
- if (!state.option.asi)
- nolinebreak(this);
-
- if (state.tokens.next.id !== ";") {
- if (state.tokens.curr.line === state.tokens.next.line) {
- if (funct[v] !== "label") {
- warning("W090", state.tokens.next, v);
- } else if (scope[v] !== funct) {
- warning("W091", state.tokens.next, v);
- }
- this.first = state.tokens.next;
- advance();
- }
- } else if (!funct["(loopage)"]) {
- warning("W052", state.tokens.next, this.value);
- }
- reachable("continue");
- return this;
- }).exps = true;
-
-
- stmt("return", function () {
- if (this.line === state.tokens.next.line) {
- if (state.tokens.next.id === "(regexp)")
- warning("W092");
-
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(0);
-
- if (this.first &&
- this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
- warningAt("W093", this.first.line, this.first.character);
- }
- }
- } else {
- if (state.tokens.next.type === "(punctuator)" &&
- ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) {
- nolinebreak(this); // always warn (Line breaking error)
- }
- }
- reachable("return");
- return this;
- }).exps = true;
-
- stmt("yield", function () {
- if (state.option.inESNext(true) && funct["(generator)"] !== true) {
- error("E046", state.tokens.curr, "yield");
- } else if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "yield");
- }
- funct["(generator)"] = "yielded";
- if (this.line === state.tokens.next.line) {
- if (state.tokens.next.id === "(regexp)")
- warning("W092");
-
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(0);
-
- if (this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
- warningAt("W093", this.first.line, this.first.character);
- }
- }
- } else if (!state.option.asi) {
- nolinebreak(this); // always warn (Line breaking error)
- }
- return this;
- }).exps = true;
-
-
- stmt("throw", function () {
- nolinebreak(this);
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(20);
- reachable("throw");
- return this;
- }).exps = true;
-
- // Future Reserved Words
-
- FutureReservedWord("abstract");
- FutureReservedWord("boolean");
- FutureReservedWord("byte");
- FutureReservedWord("char");
- FutureReservedWord("class", { es5: true, nud: classdef });
- FutureReservedWord("double");
- FutureReservedWord("enum", { es5: true });
- FutureReservedWord("export", { es5: true });
- FutureReservedWord("extends", { es5: true });
- FutureReservedWord("final");
- FutureReservedWord("float");
- FutureReservedWord("goto");
- FutureReservedWord("implements", { es5: true, strictOnly: true });
- FutureReservedWord("import", { es5: true });
- FutureReservedWord("int");
- FutureReservedWord("interface", { es5: true, strictOnly: true });
- FutureReservedWord("long");
- FutureReservedWord("native");
- FutureReservedWord("package", { es5: true, strictOnly: true });
- FutureReservedWord("private", { es5: true, strictOnly: true });
- FutureReservedWord("protected", { es5: true, strictOnly: true });
- FutureReservedWord("public", { es5: true, strictOnly: true });
- FutureReservedWord("short");
- FutureReservedWord("static", { es5: true, strictOnly: true });
- FutureReservedWord("super", { es5: true });
- FutureReservedWord("synchronized");
- FutureReservedWord("throws");
- FutureReservedWord("transient");
- FutureReservedWord("volatile");
-
- // this function is used to determine wether a squarebracket or a curlybracket
- // expression is a comprehension array, destructuring assignment or a json value.
-
- var lookupBlockType = function () {
- var pn, pn1;
- var i = 0;
- var bracketStack = 0;
- var ret = {};
- if (_.contains(["[", "{"], state.tokens.curr.value))
- bracketStack += 1;
- if (_.contains(["[", "{"], state.tokens.next.value))
- bracketStack += 1;
- if (_.contains(["]", "}"], state.tokens.next.value))
- bracketStack -= 1;
- do {
- pn = peek(i);
- pn1 = peek(i + 1);
- i = i + 1;
- if (_.contains(["[", "{"], pn.value)) {
- bracketStack += 1;
- } else if (_.contains(["]", "}"], pn.value)) {
- bracketStack -= 1;
- }
- if (pn.identifier && pn.value === "for" && bracketStack === 1) {
- ret.isCompArray = true;
- ret.notJson = true;
- break;
- }
- if (_.contains(["}", "]"], pn.value) && pn1.value === "=") {
- ret.isDestAssign = true;
- ret.notJson = true;
- break;
- }
- if (pn.value === ";") {
- ret.isBlock = true;
- ret.notJson = true;
- }
- } while (bracketStack > 0 && pn.id !== "(end)" && i < 15);
- return ret;
- };
-
- // Check whether this function has been reached for a destructuring assign with undeclared values
- function destructuringAssignOrJsonValue() {
- // lookup for the assignment (esnext only)
- // if it has semicolons, it is a block, so go parse it as a block
- // or it's not a block, but there are assignments, check for undeclared variables
-
- var block = lookupBlockType();
- if (block.notJson) {
- if (!state.option.inESNext() && block.isDestAssign) {
- warning("W104", state.tokens.curr, "destructuring assignment");
- }
- statements();
- // otherwise parse json value
- } else {
- state.option.laxbreak = true;
- state.jsonMode = true;
- jsonValue();
- }
- }
-
- // array comprehension parsing function
- // parses and defines the three states of the list comprehension in order
- // to avoid defining global variables, but keeping them to the list comprehension scope
- // only. The order of the states are as follows:
- // * "use" which will be the returned iterative part of the list comprehension
- // * "define" which will define the variables local to the list comprehension
- // * "filter" which will help filter out values
-
- var arrayComprehension = function () {
- var CompArray = function () {
- this.mode = "use";
- this.variables = [];
- };
- var _carrays = [];
- var _current;
- function declare(v) {
- var l = _current.variables.filter(function (elt) {
- // if it has, change its undef state
- if (elt.value === v) {
- elt.undef = false;
- return v;
- }
- }).length;
- return l !== 0;
- }
- function use(v) {
- var l = _current.variables.filter(function (elt) {
- // and if it has been defined
- if (elt.value === v && !elt.undef) {
- if (elt.unused === true) {
- elt.unused = false;
- }
- return v;
- }
- }).length;
- // otherwise we warn about it
- return (l === 0);
- }
- return {stack: function () {
- _current = new CompArray();
- _carrays.push(_current);
- },
- unstack: function () {
- _current.variables.filter(function (v) {
- if (v.unused)
- warning("W098", v.token, v.value);
- if (v.undef)
- isundef(v.funct, "W117", v.token, v.value);
- });
- _carrays.splice(_carrays[_carrays.length - 1], 1);
- _current = _carrays[_carrays.length - 1];
- },
- setState: function (s) {
- if (_.contains(["use", "define", "filter"], s))
- _current.mode = s;
- },
- check: function (v) {
- // When we are in "use" state of the list comp, we enqueue that var
- if (_current && _current.mode === "use") {
- _current.variables.push({funct: funct,
- token: state.tokens.curr,
- value: v,
- undef: true,
- unused: false});
- return true;
- // When we are in "define" state of the list comp,
- } else if (_current && _current.mode === "define") {
- // check if the variable has been used previously
- if (!declare(v)) {
- _current.variables.push({funct: funct,
- token: state.tokens.curr,
- value: v,
- undef: false,
- unused: true});
- }
- return true;
- // When we are in "filter" state,
- } else if (_current && _current.mode === "filter") {
- // we check whether current variable has been declared
- if (use(v)) {
- // if not we warn about it
- isundef(funct, "W117", state.tokens.curr, v);
- }
- return true;
- }
- return false;
- }
- };
- };
-
-
- // Parse JSON
-
- function jsonValue() {
-
- function jsonObject() {
- var o = {}, t = state.tokens.next;
- advance("{");
- if (state.tokens.next.id !== "}") {
- for (;;) {
- if (state.tokens.next.id === "(end)") {
- error("E026", state.tokens.next, t.line);
- } else if (state.tokens.next.id === "}") {
- warning("W094", state.tokens.curr);
- break;
- } else if (state.tokens.next.id === ",") {
- error("E028", state.tokens.next);
- } else if (state.tokens.next.id !== "(string)") {
- warning("W095", state.tokens.next, state.tokens.next.value);
- }
- if (o[state.tokens.next.value] === true) {
- warning("W075", state.tokens.next, state.tokens.next.value);
- } else if ((state.tokens.next.value === "__proto__" &&
- !state.option.proto) || (state.tokens.next.value === "__iterator__" &&
- !state.option.iterator)) {
- warning("W096", state.tokens.next, state.tokens.next.value);
- } else {
- o[state.tokens.next.value] = true;
- }
- advance();
- advance(":");
- jsonValue();
- if (state.tokens.next.id !== ",") {
- break;
- }
- advance(",");
- }
- }
- advance("}");
- }
-
- function jsonArray() {
- var t = state.tokens.next;
- advance("[");
- if (state.tokens.next.id !== "]") {
- for (;;) {
- if (state.tokens.next.id === "(end)") {
- error("E027", state.tokens.next, t.line);
- } else if (state.tokens.next.id === "]") {
- warning("W094", state.tokens.curr);
- break;
- } else if (state.tokens.next.id === ",") {
- error("E028", state.tokens.next);
- }
- jsonValue();
- if (state.tokens.next.id !== ",") {
- break;
- }
- advance(",");
- }
- }
- advance("]");
- }
-
- switch (state.tokens.next.id) {
- case "{":
- jsonObject();
- break;
- case "[":
- jsonArray();
- break;
- case "true":
- case "false":
- case "null":
- case "(number)":
- case "(string)":
- advance();
- break;
- case "-":
- advance("-");
- if (state.tokens.curr.character !== state.tokens.next.from) {
- warning("W011", state.tokens.curr);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- advance("(number)");
- break;
- default:
- error("E003", state.tokens.next);
- }
- }
-
- var blockScope = function () {
- var _current = {};
- var _variables = [_current];
-
- function _checkBlockLabels() {
- for (var t in _current) {
- if (_current[t]["(type)"] === "unused") {
- if (state.option.unused) {
- var tkn = _current[t]["(token)"];
- var line = tkn.line;
- var chr = tkn.character;
- warningAt("W098", line, chr, t);
- }
- }
- }
- }
-
- return {
- stack: function () {
- _current = {};
- _variables.push(_current);
- },
-
- unstack: function () {
- _checkBlockLabels();
- _variables.splice(_variables.length - 1, 1);
- _current = _.last(_variables);
- },
-
- getlabel: function (l) {
- for (var i = _variables.length - 1 ; i >= 0; --i) {
- if (_.has(_variables[i], l)) {
- return _variables[i];
- }
- }
- },
-
- current: {
- has: function (t) {
- return _.has(_current, t);
- },
- add: function (t, type, tok) {
- _current[t] = { "(type)" : type,
- "(token)": tok };
- }
- }
- };
- };
-
- // The actual JSHINT function itself.
- var itself = function (s, o, g) {
- var a, i, k, x;
- var optionKeys;
- var newOptionObj = {};
- var newIgnoredObj = {};
-
- state.reset();
-
- if (o && o.scope) {
- JSHINT.scope = o.scope;
- } else {
- JSHINT.errors = [];
- JSHINT.undefs = [];
- JSHINT.internals = [];
- JSHINT.blacklist = {};
- JSHINT.scope = "(main)";
- }
-
- predefined = Object.create(null);
- combine(predefined, vars.ecmaIdentifiers);
- combine(predefined, vars.reservedVars);
-
- combine(predefined, g || {});
-
- declared = Object.create(null);
- exported = Object.create(null);
-
- if (o) {
- a = o.predef;
- if (a) {
- if (!Array.isArray(a) && typeof a === "object") {
- a = Object.keys(a);
- }
-
- a.forEach(function (item) {
- var slice, prop;
-
- if (item[0] === "-") {
- slice = item.slice(1);
- JSHINT.blacklist[slice] = slice;
- } else {
- prop = Object.getOwnPropertyDescriptor(o.predef, item);
- predefined[item] = prop ? prop.value : false;
- }
- });
- }
-
- optionKeys = Object.keys(o);
- for (x = 0; x < optionKeys.length; x++) {
- if (/^-W\d{3}$/g.test(optionKeys[x])) {
- newIgnoredObj[optionKeys[x].slice(1)] = true;
- } else {
- newOptionObj[optionKeys[x]] = o[optionKeys[x]];
-
- if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
- newOptionObj["(explicitNewcap)"] = true;
-
- if (optionKeys[x] === "indent")
- newOptionObj["(explicitIndent)"] = o[optionKeys[x]] === false ? false : true;
- }
- }
- }
-
- state.option = newOptionObj;
- state.ignored = newIgnoredObj;
-
- state.option.indent = state.option.indent || 4;
- state.option.maxerr = state.option.maxerr || 50;
-
- indent = 1;
- global = Object.create(predefined);
- scope = global;
- funct = {
- "(global)": true,
- "(name)": "(global)",
- "(scope)": scope,
- "(breakage)": 0,
- "(loopage)": 0,
- "(tokens)": {},
- "(metrics)": createMetrics(state.tokens.next),
- "(blockscope)": blockScope(),
- "(comparray)": arrayComprehension()
- };
- functions = [funct];
- urls = [];
- stack = null;
- member = {};
- membersOnly = null;
- implied = {};
- inblock = false;
- lookahead = [];
- warnings = 0;
- unuseds = [];
-
- if (!isString(s) && !Array.isArray(s)) {
- errorAt("E004", 0);
- return false;
- }
-
- api = {
- get isJSON() {
- return state.jsonMode;
- },
-
- getOption: function (name) {
- return state.option[name] || null;
- },
-
- getCache: function (name) {
- return state.cache[name];
- },
-
- setCache: function (name, value) {
- state.cache[name] = value;
- },
-
- warn: function (code, data) {
- warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));
- },
-
- on: function (names, listener) {
- names.split(" ").forEach(function (name) {
- emitter.on(name, listener);
- }.bind(this));
- }
- };
-
- emitter.removeAllListeners();
- (extraModules || []).forEach(function (func) {
- func(api);
- });
-
- state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
-
- lex = new Lexer(s);
-
- lex.on("warning", function (ev) {
- warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
- });
-
- lex.on("error", function (ev) {
- errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
- });
-
- lex.on("fatal", function (ev) {
- quit("E041", ev.line, ev.from);
- });
-
- lex.on("Identifier", function (ev) {
- emitter.emit("Identifier", ev);
- });
-
- lex.on("String", function (ev) {
- emitter.emit("String", ev);
- });
-
- lex.on("Number", function (ev) {
- emitter.emit("Number", ev);
- });
-
- lex.start();
-
- // Check options
- for (var name in o) {
- if (_.has(o, name)) {
- checkOption(name, state.tokens.curr);
- }
- }
-
- assume();
-
- // combine the passed globals after we've assumed all our options
- combine(predefined, g || {});
-
- //reset values
- comma.first = true;
-
- try {
- advance();
- switch (state.tokens.next.id) {
- case "{":
- case "[":
- destructuringAssignOrJsonValue();
- break;
- default:
- directives();
-
- if (state.directive["use strict"]) {
- if (!state.option.globalstrict && !state.option.node) {
- warning("W097", state.tokens.prev);
- }
- }
-
- statements();
- }
- advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined);
- funct["(blockscope)"].unstack();
-
- var markDefined = function (name, context) {
- do {
- if (typeof context[name] === "string") {
- // JSHINT marks unused variables as 'unused' and
- // unused function declaration as 'unction'. This
- // code changes such instances back 'var' and
- // 'closure' so that the code in JSHINT.data()
- // doesn't think they're unused.
-
- if (context[name] === "unused")
- context[name] = "var";
- else if (context[name] === "unction")
- context[name] = "closure";
-
- return true;
- }
-
- context = context["(context)"];
- } while (context);
-
- return false;
- };
-
- var clearImplied = function (name, line) {
- if (!implied[name])
- return;
-
- var newImplied = [];
- for (var i = 0; i < implied[name].length; i += 1) {
- if (implied[name][i] !== line)
- newImplied.push(implied[name][i]);
- }
-
- if (newImplied.length === 0)
- delete implied[name];
- else
- implied[name] = newImplied;
- };
-
- var warnUnused = function (name, tkn, type, unused_opt) {
- var line = tkn.line;
- var chr = tkn.character;
-
- if (unused_opt === undefined) {
- unused_opt = state.option.unused;
- }
-
- if (unused_opt === true) {
- unused_opt = "last-param";
- }
-
- var warnable_types = {
- "vars": ["var"],
- "last-param": ["var", "param"],
- "strict": ["var", "param", "last-param"]
- };
-
- if (unused_opt) {
- if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
- warningAt("W098", line, chr, name);
- }
- }
-
- unuseds.push({
- name: name,
- line: line,
- character: chr
- });
- };
-
- var checkUnused = function (func, key) {
- var type = func[key];
- var tkn = func["(tokens)"][key];
-
- if (key.charAt(0) === "(")
- return;
-
- if (type !== "unused" && type !== "unction")
- return;
-
- // Params are checked separately from other variables.
- if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
- return;
-
- // Variable is in global scope and defined as exported.
- if (func["(global)"] && _.has(exported, key)) {
- return;
- }
-
- warnUnused(key, tkn, "var");
- };
-
- // Check queued 'x is not defined' instances to see if they're still undefined.
- for (i = 0; i < JSHINT.undefs.length; i += 1) {
- k = JSHINT.undefs[i].slice(0);
-
- if (markDefined(k[2].value, k[0])) {
- clearImplied(k[2].value, k[2].line);
- } else if (state.option.undef) {
- warning.apply(warning, k.slice(1));
- }
- }
-
- functions.forEach(function (func) {
- if (func["(unusedOption)"] === false) {
- return;
- }
-
- for (var key in func) {
- if (_.has(func, key)) {
- checkUnused(func, key);
- }
- }
-
- if (!func["(params)"])
- return;
-
- var params = func["(params)"].slice();
- var param = params.pop();
- var type, unused_opt;
-
- while (param) {
- type = func[param];
- unused_opt = func["(unusedOption)"] || state.option.unused;
- unused_opt = unused_opt === true ? "last-param" : unused_opt;
-
- // 'undefined' is a special case for (function (window, undefined) { ... })();
- // patterns.
-
- if (param === "undefined")
- return;
-
- if (type === "unused" || type === "unction") {
- warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]);
- } else if (unused_opt === "last-param") {
- return;
- }
-
- param = params.pop();
- }
- });
-
- for (var key in declared) {
- if (_.has(declared, key) && !_.has(global, key)) {
- warnUnused(key, declared[key], "var");
- }
- }
-
- } catch (err) {
- if (err && err.name === "JSHintError") {
- var nt = state.tokens.next || {};
- JSHINT.errors.push({
- scope : "(main)",
- raw : err.raw,
- reason : err.message,
- line : err.line || nt.line,
- character : err.character || nt.from
- }, null);
- } else {
- throw err;
- }
- }
-
- // Loop over the listed "internals", and check them as well.
-
- if (JSHINT.scope === "(main)") {
- o = o || {};
-
- for (i = 0; i < JSHINT.internals.length; i += 1) {
- k = JSHINT.internals[i];
- o.scope = k.elem;
- itself(k.value, o, g);
- }
- }
-
- return JSHINT.errors.length === 0;
- };
-
- // Modules.
- itself.addModule = function (func) {
- extraModules.push(func);
- };
-
- itself.addModule(style.register);
-
- // Data summary.
- itself.data = function () {
- var data = {
- functions: [],
- options: state.option
- };
- var implieds = [];
- var members = [];
- var fu, f, i, j, n, globals;
-
- if (itself.errors.length) {
- data.errors = itself.errors;
- }
-
- if (state.jsonMode) {
- data.json = true;
- }
-
- for (n in implied) {
- if (_.has(implied, n)) {
- implieds.push({
- name: n,
- line: implied[n]
- });
- }
- }
-
- if (implieds.length > 0) {
- data.implieds = implieds;
- }
-
- if (urls.length > 0) {
- data.urls = urls;
- }
-
- globals = Object.keys(scope);
- if (globals.length > 0) {
- data.globals = globals;
- }
-
- for (i = 1; i < functions.length; i += 1) {
- f = functions[i];
- fu = {};
-
- for (j = 0; j < functionicity.length; j += 1) {
- fu[functionicity[j]] = [];
- }
-
- for (j = 0; j < functionicity.length; j += 1) {
- if (fu[functionicity[j]].length === 0) {
- delete fu[functionicity[j]];
- }
- }
-
- fu.name = f["(name)"];
- fu.param = f["(params)"];
- fu.line = f["(line)"];
- fu.character = f["(character)"];
- fu.last = f["(last)"];
- fu.lastcharacter = f["(lastcharacter)"];
- data.functions.push(fu);
- }
-
- if (unuseds.length > 0) {
- data.unused = unuseds;
- }
-
- members = [];
- for (n in member) {
- if (typeof member[n] === "number") {
- data.member = member;
- break;
- }
- }
-
- return data;
- };
-
- itself.jshint = itself;
-
- return itself;
-}());
-
-// Make JSHINT a Node module, if possible.
-if (typeof exports === "object" && exports) {
- exports.JSHINT = JSHINT;
-}
-
-})()
-},{"events":2,"../shared/vars.js":3,"./lex.js":10,"./reg.js":6,"./state.js":4,"../shared/messages.js":12,"./style.js":5,"console-browserify":7,"underscore":11}],12:[function(require,module,exports){
-(function(){"use strict";
-
-var _ = require("underscore");
-
-var errors = {
- // JSHint options
- E001: "Bad option: '{a}'.",
- E002: "Bad option value.",
-
- // JSHint input
- E003: "Expected a JSON value.",
- E004: "Input is neither a string nor an array of strings.",
- E005: "Input is empty.",
- E006: "Unexpected early end of program.",
-
- // Strict mode
- E007: "Missing \"use strict\" statement.",
- E008: "Strict violation.",
- E009: "Option 'validthis' can't be used in a global scope.",
- E010: "'with' is not allowed in strict mode.",
-
- // Constants
- E011: "const '{a}' has already been declared.",
- E012: "const '{a}' is initialized to 'undefined'.",
- E013: "Attempting to override '{a}' which is a constant.",
-
- // Regular expressions
- E014: "A regular expression literal can be confused with '/='.",
- E015: "Unclosed regular expression.",
- E016: "Invalid regular expression.",
-
- // Tokens
- E017: "Unclosed comment.",
- E018: "Unbegun comment.",
- E019: "Unmatched '{a}'.",
- E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
- E021: "Expected '{a}' and instead saw '{b}'.",
- E022: "Line breaking error '{a}'.",
- E023: "Missing '{a}'.",
- E024: "Unexpected '{a}'.",
- E025: "Missing ':' on a case clause.",
- E026: "Missing '}' to match '{' from line {a}.",
- E027: "Missing ']' to match '[' form line {a}.",
- E028: "Illegal comma.",
- E029: "Unclosed string.",
-
- // Everything else
- E030: "Expected an identifier and instead saw '{a}'.",
- E031: "Bad assignment.", // FIXME: Rephrase
- E032: "Expected a small integer or 'false' and instead saw '{a}'.",
- E033: "Expected an operator and instead saw '{a}'.",
- E034: "get/set are ES5 features.",
- E035: "Missing property name.",
- E036: "Expected to see a statement and instead saw a block.",
- E037: "Constant {a} was not declared correctly.",
- E038: "Variable {a} was not declared correctly.",
- E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
- E040: "Each value should have its own case label.",
- E041: "Unrecoverable syntax error.",
- E042: "Stopping.",
- E043: "Too many errors.",
- E044: "'{a}' is already defined and can't be redefined.",
- E045: "Invalid for each loop.",
- E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
- E047: "A generator function shall contain a yield statement.",
- E048: "Let declaration not directly within block.",
- E049: "A {a} cannot be named '{b}'."
-};
-
-var warnings = {
- W001: "'hasOwnProperty' is a really bad name.",
- W002: "Value of '{a}' may be overwritten in IE.",
- W003: "'{a}' was used before it was defined.",
- W004: "'{a}' is already defined.",
- W005: "A dot following a number can be confused with a decimal point.",
- W006: "Confusing minuses.",
- W007: "Confusing pluses.",
- W008: "A leading decimal point can be confused with a dot: '{a}'.",
- W009: "The array literal notation [] is preferrable.",
- W010: "The object literal notation {} is preferrable.",
- W011: "Unexpected space after '{a}'.",
- W012: "Unexpected space before '{a}'.",
- W013: "Missing space after '{a}'.",
- W014: "Bad line breaking before '{a}'.",
- W015: "Expected '{a}' to have an indentation at {b} instead at {c}.",
- W016: "Unexpected use of '{a}'.",
- W017: "Bad operand.",
- W018: "Confusing use of '{a}'.",
- W019: "Use the isNaN function to compare with NaN.",
- W020: "Read only.",
- W021: "'{a}' is a function.",
- W022: "Do not assign to the exception parameter.",
- W023: "Expected an identifier in an assignment and instead saw a function invocation.",
- W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
- W025: "Missing name in function declaration.",
- W026: "Inner functions should be listed at the top of the outer function.",
- W027: "Unreachable '{a}' after '{b}'.",
- W028: "Label '{a}' on {b} statement.",
- W030: "Expected an assignment or function call and instead saw an expression.",
- W031: "Do not use 'new' for side effects.",
- W032: "Unnecessary semicolon.",
- W033: "Missing semicolon.",
- W034: "Unnecessary directive \"{a}\".",
- W035: "Empty block.",
- W036: "Unexpected /*member '{a}'.",
- W037: "'{a}' is a statement label.",
- W038: "'{a}' used out of scope.",
- W039: "'{a}' is not allowed.",
- W040: "Possible strict violation.",
- W041: "Use '{a}' to compare with '{b}'.",
- W042: "Avoid EOL escaping.",
- W043: "Bad escaping of EOL. Use option multistr if needed.",
- W044: "Bad or unnecessary escaping.",
- W045: "Bad number '{a}'.",
- W046: "Don't use extra leading zeros '{a}'.",
- W047: "A trailing decimal point can be confused with a dot: '{a}'.",
- W048: "Unexpected control character in regular expression.",
- W049: "Unexpected escaped character '{a}' in regular expression.",
- W050: "JavaScript URL.",
- W051: "Variables should not be deleted.",
- W052: "Unexpected '{a}'.",
- W053: "Do not use {a} as a constructor.",
- W054: "The Function constructor is a form of eval.",
- W055: "A constructor name should start with an uppercase letter.",
- W056: "Bad constructor.",
- W057: "Weird construction. Is 'new' unnecessary?",
- W058: "Missing '()' invoking a constructor.",
- W059: "Avoid arguments.{a}.",
- W060: "document.write can be a form of eval.",
- W061: "eval can be harmful.",
- W062: "Wrap an immediate function invocation in parens " +
- "to assist the reader in understanding that the expression " +
- "is the result of a function, and not the function itself.",
- W063: "Math is not a function.",
- W064: "Missing 'new' prefix when invoking a constructor.",
- W065: "Missing radix parameter.",
- W066: "Implied eval. Consider passing a function instead of a string.",
- W067: "Bad invocation.",
- W068: "Wrapping non-IIFE function literals in parens is unnecessary.",
- W069: "['{a}'] is better written in dot notation.",
- W070: "Extra comma. (it breaks older versions of IE)",
- W071: "This function has too many statements. ({a})",
- W072: "This function has too many parameters. ({a})",
- W073: "Blocks are nested too deeply. ({a})",
- W074: "This function's cyclomatic complexity is too high. ({a})",
- W075: "Duplicate key '{a}'.",
- W076: "Unexpected parameter '{a}' in get {b} function.",
- W077: "Expected a single parameter in set {a} function.",
- W078: "Setter is defined without getter.",
- W079: "Redefinition of '{a}'.",
- W080: "It's not necessary to initialize '{a}' to 'undefined'.",
- W081: "Too many var statements.",
- W082: "Function declarations should not be placed in blocks. " +
- "Use a function expression or move the statement to the top of " +
- "the outer function.",
- W083: "Don't make functions within a loop.",
- W084: "Expected a conditional expression and instead saw an assignment.",
- W085: "Don't use 'with'.",
- W086: "Expected a 'break' statement before '{a}'.",
- W087: "Forgotten 'debugger' statement?",
- W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
- W089: "The body of a for in should be wrapped in an if statement to filter " +
- "unwanted properties from the prototype.",
- W090: "'{a}' is not a statement label.",
- W091: "'{a}' is out of scope.",
- W092: "Wrap the /regexp/ literal in parens to disambiguate the slash operator.",
- W093: "Did you mean to return a conditional instead of an assignment?",
- W094: "Unexpected comma.",
- W095: "Expected a string and instead saw {a}.",
- W096: "The '{a}' key may produce unexpected results.",
- W097: "Use the function form of \"use strict\".",
- W098: "'{a}' is defined but never used.",
- W099: "Mixed spaces and tabs.",
- W100: "This character may get silently deleted by one or more browsers.",
- W101: "Line is too long.",
- W102: "Trailing whitespace.",
- W103: "The '{a}' property is deprecated.",
- W104: "'{a}' is only available in JavaScript 1.7.",
- W105: "Unexpected {a} in '{b}'.",
- W106: "Identifier '{a}' is not in camel case.",
- W107: "Script URL.",
- W108: "Strings must use doublequote.",
- W109: "Strings must use singlequote.",
- W110: "Mixed double and single quotes.",
- W112: "Unclosed string.",
- W113: "Control character in string: {a}.",
- W114: "Avoid {a}.",
- W115: "Octal literals are not allowed in strict mode.",
- W116: "Expected '{a}' and instead saw '{b}'.",
- W117: "'{a}' is not defined.",
- W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
- W119: "'{a}' is only available in ES6 (use esnext option)."
-};
-
-var info = {
- I001: "Comma warnings can be turned off with 'laxcomma'.",
- I002: "Reserved words as properties can be used under the 'es5' option.",
- I003: "ES5 option is now set per default"
-};
-
-exports.errors = {};
-exports.warnings = {};
-exports.info = {};
-
-_.each(errors, function (desc, code) {
- exports.errors[code] = { code: code, desc: desc };
-});
-
-_.each(warnings, function (desc, code) {
- exports.warnings[code] = { code: code, desc: desc };
-});
-
-_.each(info, function (desc, code) {
- exports.info[code] = { code: code, desc: desc };
-});
-
-})()
-},{"underscore":11}],8:[function(require,module,exports){
-var events = require('events');
-
-exports.isArray = isArray;
-exports.isDate = function(obj){return Object.prototype.toString.call(obj) === '[object Date]'};
-exports.isRegExp = function(obj){return Object.prototype.toString.call(obj) === '[object RegExp]'};
-
-
-exports.print = function () {};
-exports.puts = function () {};
-exports.debug = function() {};
-
-exports.inspect = function(obj, showHidden, depth, colors) {
- var seen = [];
-
- var stylize = function(str, styleType) {
- // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
- var styles =
- { 'bold' : [1, 22],
- 'italic' : [3, 23],
- 'underline' : [4, 24],
- 'inverse' : [7, 27],
- 'white' : [37, 39],
- 'grey' : [90, 39],
- 'black' : [30, 39],
- 'blue' : [34, 39],
- 'cyan' : [36, 39],
- 'green' : [32, 39],
- 'magenta' : [35, 39],
- 'red' : [31, 39],
- 'yellow' : [33, 39] };
-
- var style =
- { 'special': 'cyan',
- 'number': 'blue',
- 'boolean': 'yellow',
- 'undefined': 'grey',
- 'null': 'bold',
- 'string': 'green',
- 'date': 'magenta',
- // "name": intentionally not styling
- 'regexp': 'red' }[styleType];
-
- if (style) {
- return '\033[' + styles[style][0] + 'm' + str +
- '\033[' + styles[style][1] + 'm';
- } else {
- return str;
- }
- };
- if (! colors) {
- stylize = function(str, styleType) { return str; };
- }
-
- function format(value, recurseTimes) {
- // Provide a hook for user-specified inspect functions.
- // Check that value is an object with an inspect function on it
- if (value && typeof value.inspect === 'function' &&
- // Filter out the util module, it's inspect function is special
- value !== exports &&
- // Also filter out any prototype objects using the circular check.
- !(value.constructor && value.constructor.prototype === value)) {
- return value.inspect(recurseTimes);
- }
-
- // Primitive types cannot have properties
- switch (typeof value) {
- case 'undefined':
- return stylize('undefined', 'undefined');
-
- case 'string':
- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
- .replace(/'/g, "\\'")
- .replace(/\\"/g, '"') + '\'';
- return stylize(simple, 'string');
-
- case 'number':
- return stylize('' + value, 'number');
-
- case 'boolean':
- return stylize('' + value, 'boolean');
- }
- // For some reason typeof null is "object", so special case here.
- if (value === null) {
- return stylize('null', 'null');
- }
-
- // Look up the keys of the object.
- var visible_keys = Object_keys(value);
- var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;
-
- // Functions without properties can be shortcutted.
- if (typeof value === 'function' && keys.length === 0) {
- if (isRegExp(value)) {
- return stylize('' + value, 'regexp');
- } else {
- var name = value.name ? ': ' + value.name : '';
- return stylize('[Function' + name + ']', 'special');
- }
- }
-
- // Dates without properties can be shortcutted
- if (isDate(value) && keys.length === 0) {
- return stylize(value.toUTCString(), 'date');
- }
-
- var base, type, braces;
- // Determine the object type
- if (isArray(value)) {
- type = 'Array';
- braces = ['[', ']'];
- } else {
- type = 'Object';
- braces = ['{', '}'];
- }
-
- // Make functions say that they are functions
- if (typeof value === 'function') {
- var n = value.name ? ': ' + value.name : '';
- base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
- } else {
- base = '';
- }
-
- // Make dates with properties first say the date
- if (isDate(value)) {
- base = ' ' + value.toUTCString();
- }
-
- if (keys.length === 0) {
- return braces[0] + base + braces[1];
- }
-
- if (recurseTimes < 0) {
- if (isRegExp(value)) {
- return stylize('' + value, 'regexp');
- } else {
- return stylize('[Object]', 'special');
- }
- }
-
- seen.push(value);
-
- var output = keys.map(function(key) {
- var name, str;
- if (value.__lookupGetter__) {
- if (value.__lookupGetter__(key)) {
- if (value.__lookupSetter__(key)) {
- str = stylize('[Getter/Setter]', 'special');
- } else {
- str = stylize('[Getter]', 'special');
- }
- } else {
- if (value.__lookupSetter__(key)) {
- str = stylize('[Setter]', 'special');
- }
- }
- }
- if (visible_keys.indexOf(key) < 0) {
- name = '[' + key + ']';
- }
- if (!str) {
- if (seen.indexOf(value[key]) < 0) {
- if (recurseTimes === null) {
- str = format(value[key]);
- } else {
- str = format(value[key], recurseTimes - 1);
- }
- if (str.indexOf('\n') > -1) {
- if (isArray(value)) {
- str = str.split('\n').map(function(line) {
- return ' ' + line;
- }).join('\n').substr(2);
- } else {
- str = '\n' + str.split('\n').map(function(line) {
- return ' ' + line;
- }).join('\n');
- }
- }
- } else {
- str = stylize('[Circular]', 'special');
- }
- }
- if (typeof name === 'undefined') {
- if (type === 'Array' && key.match(/^\d+$/)) {
- return str;
- }
- name = JSON.stringify('' + key);
- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
- name = name.substr(1, name.length - 2);
- name = stylize(name, 'name');
- } else {
- name = name.replace(/'/g, "\\'")
- .replace(/\\"/g, '"')
- .replace(/(^"|"$)/g, "'");
- name = stylize(name, 'string');
- }
- }
-
- return name + ': ' + str;
- });
-
- seen.pop();
-
- var numLinesEst = 0;
- var length = output.reduce(function(prev, cur) {
- numLinesEst++;
- if (cur.indexOf('\n') >= 0) numLinesEst++;
- return prev + cur.length + 1;
- }, 0);
-
- if (length > 50) {
- output = braces[0] +
- (base === '' ? '' : base + '\n ') +
- ' ' +
- output.join(',\n ') +
- ' ' +
- braces[1];
-
- } else {
- output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
- }
-
- return output;
- }
- return format(obj, (typeof depth === 'undefined' ? 2 : depth));
-};
-
-
-function isArray(ar) {
- return ar instanceof Array ||
- Array.isArray(ar) ||
- (ar && ar !== Object.prototype && isArray(ar.__proto__));
-}
-
-
-function isRegExp(re) {
- return re instanceof RegExp ||
- (typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]');
-}
-
-
-function isDate(d) {
- if (d instanceof Date) return true;
- if (typeof d !== 'object') return false;
- var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype);
- var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__);
- return JSON.stringify(proto) === JSON.stringify(properties);
-}
-
-function pad(n) {
- return n < 10 ? '0' + n.toString(10) : n.toString(10);
-}
-
-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
- 'Oct', 'Nov', 'Dec'];
-
-// 26 Feb 16:19:34
-function timestamp() {
- var d = new Date();
- var time = [pad(d.getHours()),
- pad(d.getMinutes()),
- pad(d.getSeconds())].join(':');
- return [d.getDate(), months[d.getMonth()], time].join(' ');
-}
-
-exports.log = function (msg) {};
-
-exports.pump = null;
-
-var Object_keys = Object.keys || function (obj) {
- var res = [];
- for (var key in obj) res.push(key);
- return res;
-};
-
-var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) {
- var res = [];
- for (var key in obj) {
- if (Object.hasOwnProperty.call(obj, key)) res.push(key);
- }
- return res;
-};
-
-var Object_create = Object.create || function (prototype, properties) {
- // from es5-shim
- var object;
- if (prototype === null) {
- object = { '__proto__' : null };
- }
- else {
- if (typeof prototype !== 'object') {
- throw new TypeError(
- 'typeof prototype[' + (typeof prototype) + '] != \'object\''
- );
- }
- var Type = function () {};
- Type.prototype = prototype;
- object = new Type();
- object.__proto__ = prototype;
- }
- if (typeof properties !== 'undefined' && Object.defineProperties) {
- Object.defineProperties(object, properties);
- }
- return object;
-};
-
-exports.inherits = function(ctor, superCtor) {
- ctor.super_ = superCtor;
- ctor.prototype = Object_create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
-};
-
-var formatRegExp = /%[sdj%]/g;
-exports.format = function(f) {
- if (typeof f !== 'string') {
- var objects = [];
- for (var i = 0; i < arguments.length; i++) {
- objects.push(exports.inspect(arguments[i]));
- }
- return objects.join(' ');
- }
-
- var i = 1;
- var args = arguments;
- var len = args.length;
- var str = String(f).replace(formatRegExp, function(x) {
- if (x === '%%') return '%';
- if (i >= len) return x;
- switch (x) {
- case '%s': return String(args[i++]);
- case '%d': return Number(args[i++]);
- case '%j': return JSON.stringify(args[i++]);
- default:
- return x;
- }
- });
- for(var x = args[i]; i < len; x = args[++i]){
- if (x === null || typeof x !== 'object') {
- str += ' ' + x;
- } else {
- str += ' ' + exports.inspect(x);
- }
- }
- return str;
-};
-
-},{"events":2}],9:[function(require,module,exports){
-(function(){// UTILITY
-var util = require('util');
-var Buffer = require("buffer").Buffer;
-var pSlice = Array.prototype.slice;
-
-function objectKeys(object) {
- if (Object.keys) return Object.keys(object);
- var result = [];
- for (var name in object) {
- if (Object.prototype.hasOwnProperty.call(object, name)) {
- result.push(name);
- }
- }
- return result;
-}
-
-// 1. The assert module provides functions that throw
-// AssertionError's when particular conditions are not met. The
-// assert module must conform to the following interface.
-
-var assert = module.exports = ok;
-
-// 2. The AssertionError is defined in assert.
-// new assert.AssertionError({ message: message,
-// actual: actual,
-// expected: expected })
-
-assert.AssertionError = function AssertionError(options) {
- this.name = 'AssertionError';
- this.message = options.message;
- this.actual = options.actual;
- this.expected = options.expected;
- this.operator = options.operator;
- var stackStartFunction = options.stackStartFunction || fail;
-
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, stackStartFunction);
- }
-};
-util.inherits(assert.AssertionError, Error);
-
-function replacer(key, value) {
- if (value === undefined) {
- return '' + value;
- }
- if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
- return value.toString();
- }
- if (typeof value === 'function' || value instanceof RegExp) {
- return value.toString();
- }
- return value;
-}
-
-function truncate(s, n) {
- if (typeof s == 'string') {
- return s.length < n ? s : s.slice(0, n);
- } else {
- return s;
- }
-}
-
-assert.AssertionError.prototype.toString = function() {
- if (this.message) {
- return [this.name + ':', this.message].join(' ');
- } else {
- return [
- this.name + ':',
- truncate(JSON.stringify(this.actual, replacer), 128),
- this.operator,
- truncate(JSON.stringify(this.expected, replacer), 128)
- ].join(' ');
- }
-};
-
-// assert.AssertionError instanceof Error
-
-assert.AssertionError.__proto__ = Error.prototype;
-
-// At present only the three keys mentioned above are used and
-// understood by the spec. Implementations or sub modules can pass
-// other keys to the AssertionError's constructor - they will be
-// ignored.
-
-// 3. All of the following functions must throw an AssertionError
-// when a corresponding condition is not met, with a message that
-// may be undefined if not provided. All assertion methods provide
-// both the actual and expected values to the assertion error for
-// display purposes.
-
-function fail(actual, expected, message, operator, stackStartFunction) {
- throw new assert.AssertionError({
- message: message,
- actual: actual,
- expected: expected,
- operator: operator,
- stackStartFunction: stackStartFunction
- });
-}
-
-// EXTENSION! allows for well behaved errors defined elsewhere.
-assert.fail = fail;
-
-// 4. Pure assertion tests whether a value is truthy, as determined
-// by !!guard.
-// assert.ok(guard, message_opt);
-// This statement is equivalent to assert.equal(true, guard,
-// message_opt);. To test strictly for the value true, use
-// assert.strictEqual(true, guard, message_opt);.
-
-function ok(value, message) {
- if (!!!value) fail(value, true, message, '==', assert.ok);
-}
-assert.ok = ok;
-
-// 5. The equality assertion tests shallow, coercive equality with
-// ==.
-// assert.equal(actual, expected, message_opt);
-
-assert.equal = function equal(actual, expected, message) {
- if (actual != expected) fail(actual, expected, message, '==', assert.equal);
-};
-
-// 6. The non-equality assertion tests for whether two objects are not equal
-// with != assert.notEqual(actual, expected, message_opt);
-
-assert.notEqual = function notEqual(actual, expected, message) {
- if (actual == expected) {
- fail(actual, expected, message, '!=', assert.notEqual);
- }
-};
-
-// 7. The equivalence assertion tests a deep equality relation.
-// assert.deepEqual(actual, expected, message_opt);
-
-assert.deepEqual = function deepEqual(actual, expected, message) {
- if (!_deepEqual(actual, expected)) {
- fail(actual, expected, message, 'deepEqual', assert.deepEqual);
- }
-};
-
-function _deepEqual(actual, expected) {
- // 7.1. All identical values are equivalent, as determined by ===.
- if (actual === expected) {
- return true;
-
- } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
- if (actual.length != expected.length) return false;
-
- for (var i = 0; i < actual.length; i++) {
- if (actual[i] !== expected[i]) return false;
- }
-
- return true;
-
- // 7.2. If the expected value is a Date object, the actual value is
- // equivalent if it is also a Date object that refers to the same time.
- } else if (actual instanceof Date && expected instanceof Date) {
- return actual.getTime() === expected.getTime();
-
- // 7.3. Other pairs that do not both pass typeof value == 'object',
- // equivalence is determined by ==.
- } else if (typeof actual != 'object' && typeof expected != 'object') {
- return actual == expected;
-
- // 7.4. For all other Object pairs, including Array objects, equivalence is
- // determined by having the same number of owned properties (as verified
- // with Object.prototype.hasOwnProperty.call), the same set of keys
- // (although not necessarily the same order), equivalent values for every
- // corresponding key, and an identical 'prototype' property. Note: this
- // accounts for both named and indexed properties on Arrays.
- } else {
- return objEquiv(actual, expected);
- }
-}
-
-function isUndefinedOrNull(value) {
- return value === null || value === undefined;
-}
-
-function isArguments(object) {
- return Object.prototype.toString.call(object) == '[object Arguments]';
-}
-
-function objEquiv(a, b) {
- if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
- return false;
- // an identical 'prototype' property.
- if (a.prototype !== b.prototype) return false;
- //~~~I've managed to break Object.keys through screwy arguments passing.
- // Converting to array solves the problem.
- if (isArguments(a)) {
- if (!isArguments(b)) {
- return false;
- }
- a = pSlice.call(a);
- b = pSlice.call(b);
- return _deepEqual(a, b);
- }
- try {
- var ka = objectKeys(a),
- kb = objectKeys(b),
- key, i;
- } catch (e) {//happens when one is a string literal and the other isn't
- return false;
- }
- // having the same number of owned properties (keys incorporates
- // hasOwnProperty)
- if (ka.length != kb.length)
- return false;
- //the same set of keys (although not necessarily the same order),
- ka.sort();
- kb.sort();
- //~~~cheap key test
- for (i = ka.length - 1; i >= 0; i--) {
- if (ka[i] != kb[i])
- return false;
- }
- //equivalent values for every corresponding key, and
- //~~~possibly expensive deep test
- for (i = ka.length - 1; i >= 0; i--) {
- key = ka[i];
- if (!_deepEqual(a[key], b[key])) return false;
- }
- return true;
-}
-
-// 8. The non-equivalence assertion tests for any deep inequality.
-// assert.notDeepEqual(actual, expected, message_opt);
-
-assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
- if (_deepEqual(actual, expected)) {
- fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
- }
-};
-
-// 9. The strict equality assertion tests strict equality, as determined by ===.
-// assert.strictEqual(actual, expected, message_opt);
-
-assert.strictEqual = function strictEqual(actual, expected, message) {
- if (actual !== expected) {
- fail(actual, expected, message, '===', assert.strictEqual);
- }
-};
-
-// 10. The strict non-equality assertion tests for strict inequality, as
-// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
-
-assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
- if (actual === expected) {
- fail(actual, expected, message, '!==', assert.notStrictEqual);
- }
-};
-
-function expectedException(actual, expected) {
- if (!actual || !expected) {
- return false;
- }
-
- if (expected instanceof RegExp) {
- return expected.test(actual);
- } else if (actual instanceof expected) {
- return true;
- } else if (expected.call({}, actual) === true) {
- return true;
- }
-
- return false;
-}
-
-function _throws(shouldThrow, block, expected, message) {
- var actual;
-
- if (typeof expected === 'string') {
- message = expected;
- expected = null;
- }
-
- try {
- block();
- } catch (e) {
- actual = e;
- }
-
- message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
- (message ? ' ' + message : '.');
-
- if (shouldThrow && !actual) {
- fail('Missing expected exception' + message);
- }
-
- if (!shouldThrow && expectedException(actual, expected)) {
- fail('Got unwanted exception' + message);
- }
-
- if ((shouldThrow && actual && expected &&
- !expectedException(actual, expected)) || (!shouldThrow && actual)) {
- throw actual;
- }
-}
-
-// 11. Expected to throw an error:
-// assert.throws(block, Error_opt, message_opt);
-
-assert.throws = function(block, /*optional*/error, /*optional*/message) {
- _throws.apply(this, [true].concat(pSlice.call(arguments)));
-};
-
-// EXTENSION! This is annoying to write outside this module.
-assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
- _throws.apply(this, [false].concat(pSlice.call(arguments)));
-};
-
-assert.ifError = function(err) { if (err) {throw err;}};
-
-})()
-},{"util":8,"buffer":13}],11:[function(require,module,exports){
-(function(){// Underscore.js 1.4.4
-// http://underscorejs.org
-// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore may be freely distributed under the MIT license.
-
-(function() {
-
- // Baseline setup
- // --------------
-
- // Establish the root object, `window` in the browser, or `global` on the server.
- var root = this;
-
- // Save the previous value of the `_` variable.
- var previousUnderscore = root._;
-
- // Establish the object that gets returned to break out of a loop iteration.
- var breaker = {};
-
- // Save bytes in the minified (but not gzipped) version:
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
-
- // Create quick reference variables for speed access to core prototypes.
- var push = ArrayProto.push,
- slice = ArrayProto.slice,
- concat = ArrayProto.concat,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty;
-
- // All **ECMAScript 5** native function implementations that we hope to use
- // are declared here.
- var
- nativeForEach = ArrayProto.forEach,
- nativeMap = ArrayProto.map,
- nativeReduce = ArrayProto.reduce,
- nativeReduceRight = ArrayProto.reduceRight,
- nativeFilter = ArrayProto.filter,
- nativeEvery = ArrayProto.every,
- nativeSome = ArrayProto.some,
- nativeIndexOf = ArrayProto.indexOf,
- nativeLastIndexOf = ArrayProto.lastIndexOf,
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind;
-
- // Create a safe reference to the Underscore object for use below.
- var _ = function(obj) {
- if (obj instanceof _) return obj;
- if (!(this instanceof _)) return new _(obj);
- this._wrapped = obj;
- };
-
- // Export the Underscore object for **Node.js**, with
- // backwards-compatibility for the old `require()` API. If we're in
- // the browser, add `_` as a global object via a string identifier,
- // for Closure Compiler "advanced" mode.
- if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
- exports = module.exports = _;
- }
- exports._ = _;
- } else {
- root._ = _;
- }
-
- // Current version.
- _.VERSION = '1.4.4';
-
- // Collection Functions
- // --------------------
-
- // The cornerstone, an `each` implementation, aka `forEach`.
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
- var each = _.each = _.forEach = function(obj, iterator, context) {
- if (obj == null) return;
- if (nativeForEach && obj.forEach === nativeForEach) {
- obj.forEach(iterator, context);
- } else if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- if (iterator.call(context, obj[i], i, obj) === breaker) return;
- }
- } else {
- for (var key in obj) {
- if (_.has(obj, key)) {
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
- }
- }
- }
- };
-
- // Return the results of applying the iterator to each element.
- // Delegates to **ECMAScript 5**'s native `map` if available.
- _.map = _.collect = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
- each(obj, function(value, index, list) {
- results[results.length] = iterator.call(context, value, index, list);
- });
- return results;
- };
-
- var reduceError = 'Reduce of empty array with no initial value';
-
- // **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduce && obj.reduce === nativeReduce) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
- }
- each(obj, function(value, index, list) {
- if (!initial) {
- memo = value;
- initial = true;
- } else {
- memo = iterator.call(context, memo, value, index, list);
- }
- });
- if (!initial) throw new TypeError(reduceError);
- return memo;
- };
-
- // The right-associative version of reduce, also known as `foldr`.
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
- }
- var length = obj.length;
- if (length !== +length) {
- var keys = _.keys(obj);
- length = keys.length;
- }
- each(obj, function(value, index, list) {
- index = keys ? keys[--length] : --length;
- if (!initial) {
- memo = obj[index];
- initial = true;
- } else {
- memo = iterator.call(context, memo, obj[index], index, list);
- }
- });
- if (!initial) throw new TypeError(reduceError);
- return memo;
- };
-
- // Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, iterator, context) {
- var result;
- any(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) {
- result = value;
- return true;
- }
- });
- return result;
- };
-
- // Return all the elements that pass a truth test.
- // Delegates to **ECMAScript 5**'s native `filter` if available.
- // Aliased as `select`.
- _.filter = _.select = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
- each(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
-
- // Return all the elements for which a truth test fails.
- _.reject = function(obj, iterator, context) {
- return _.filter(obj, function(value, index, list) {
- return !iterator.call(context, value, index, list);
- }, context);
- };
-
- // Determine whether all of the elements match a truth test.
- // Delegates to **ECMAScript 5**'s native `every` if available.
- // Aliased as `all`.
- _.every = _.all = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
- var result = true;
- if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
- each(obj, function(value, index, list) {
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- };
-
- // Determine if at least one element in the object matches a truth test.
- // Delegates to **ECMAScript 5**'s native `some` if available.
- // Aliased as `any`.
- var any = _.some = _.any = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
- var result = false;
- if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
- each(obj, function(value, index, list) {
- if (result || (result = iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- };
-
- // Determine if the array or object contains a given value (using `===`).
- // Aliased as `include`.
- _.contains = _.include = function(obj, target) {
- if (obj == null) return false;
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
- return any(obj, function(value) {
- return value === target;
- });
- };
-
- // Invoke a method (with arguments) on every item in a collection.
- _.invoke = function(obj, method) {
- var args = slice.call(arguments, 2);
- var isFunc = _.isFunction(method);
- return _.map(obj, function(value) {
- return (isFunc ? method : value[method]).apply(value, args);
- });
- };
-
- // Convenience version of a common use case of `map`: fetching a property.
- _.pluck = function(obj, key) {
- return _.map(obj, function(value){ return value[key]; });
- };
-
- // Convenience version of a common use case of `filter`: selecting only objects
- // containing specific `key:value` pairs.
- _.where = function(obj, attrs, first) {
- if (_.isEmpty(attrs)) return first ? null : [];
- return _[first ? 'find' : 'filter'](obj, function(value) {
- for (var key in attrs) {
- if (attrs[key] !== value[key]) return false;
- }
- return true;
- });
- };
-
- // Convenience version of a common use case of `find`: getting the first object
- // containing specific `key:value` pairs.
- _.findWhere = function(obj, attrs) {
- return _.where(obj, attrs, true);
- };
-
- // Return the maximum element or (element-based computation).
- // Can't optimize arrays of integers longer than 65,535 elements.
- // See: https://bugs.webkit.org/show_bug.cgi?id=80797
- _.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.max.apply(Math, obj);
- }
- if (!iterator && _.isEmpty(obj)) return -Infinity;
- var result = {computed : -Infinity, value: -Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed >= result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Return the minimum element (or element-based computation).
- _.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.min.apply(Math, obj);
- }
- if (!iterator && _.isEmpty(obj)) return Infinity;
- var result = {computed : Infinity, value: Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed < result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Shuffle an array.
- _.shuffle = function(obj) {
- var rand;
- var index = 0;
- var shuffled = [];
- each(obj, function(value) {
- rand = _.random(index++);
- shuffled[index - 1] = shuffled[rand];
- shuffled[rand] = value;
- });
- return shuffled;
- };
-
- // An internal function to generate lookup iterators.
- var lookupIterator = function(value) {
- return _.isFunction(value) ? value : function(obj){ return obj[value]; };
- };
-
- // Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, value, context) {
- var iterator = lookupIterator(value);
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value : value,
- index : index,
- criteria : iterator.call(context, value, index, list)
- };
- }).sort(function(left, right) {
- var a = left.criteria;
- var b = right.criteria;
- if (a !== b) {
- if (a > b || a === void 0) return 1;
- if (a < b || b === void 0) return -1;
- }
- return left.index < right.index ? -1 : 1;
- }), 'value');
- };
-
- // An internal function used for aggregate "group by" operations.
- var group = function(obj, value, context, behavior) {
- var result = {};
- var iterator = lookupIterator(value || _.identity);
- each(obj, function(value, index) {
- var key = iterator.call(context, value, index, obj);
- behavior(result, key, value);
- });
- return result;
- };
-
- // Groups the object's values by a criterion. Pass either a string attribute
- // to group by, or a function that returns the criterion.
- _.groupBy = function(obj, value, context) {
- return group(obj, value, context, function(result, key, value) {
- (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
- });
- };
-
- // Counts instances of an object that group by a certain criterion. Pass
- // either a string attribute to count by, or a function that returns the
- // criterion.
- _.countBy = function(obj, value, context) {
- return group(obj, value, context, function(result, key) {
- if (!_.has(result, key)) result[key] = 0;
- result[key]++;
- });
- };
-
- // Use a comparator function to figure out the smallest index at which
- // an object should be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iterator, context) {
- iterator = iterator == null ? _.identity : lookupIterator(iterator);
- var value = iterator.call(context, obj);
- var low = 0, high = array.length;
- while (low < high) {
- var mid = (low + high) >>> 1;
- iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
- }
- return low;
- };
-
- // Safely convert anything iterable into a real, live array.
- _.toArray = function(obj) {
- if (!obj) return [];
- if (_.isArray(obj)) return slice.call(obj);
- if (obj.length === +obj.length) return _.map(obj, _.identity);
- return _.values(obj);
- };
-
- // Return the number of elements in an object.
- _.size = function(obj) {
- if (obj == null) return 0;
- return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
- };
-
- // Array Functions
- // ---------------
-
- // Get the first element of an array. Passing **n** will return the first N
- // values in the array. Aliased as `head` and `take`. The **guard** check
- // allows it to work with `_.map`.
- _.first = _.head = _.take = function(array, n, guard) {
- if (array == null) return void 0;
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
- };
-
- // Returns everything but the last entry of the array. Especially useful on
- // the arguments object. Passing **n** will return all the values in
- // the array, excluding the last N. The **guard** check allows it to work with
- // `_.map`.
- _.initial = function(array, n, guard) {
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
- };
-
- // Get the last element of an array. Passing **n** will return the last N
- // values in the array. The **guard** check allows it to work with `_.map`.
- _.last = function(array, n, guard) {
- if (array == null) return void 0;
- if ((n != null) && !guard) {
- return slice.call(array, Math.max(array.length - n, 0));
- } else {
- return array[array.length - 1];
- }
- };
-
- // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
- // Especially useful on the arguments object. Passing an **n** will return
- // the rest N values in the array. The **guard**
- // check allows it to work with `_.map`.
- _.rest = _.tail = _.drop = function(array, n, guard) {
- return slice.call(array, (n == null) || guard ? 1 : n);
- };
-
- // Trim out all falsy values from an array.
- _.compact = function(array) {
- return _.filter(array, _.identity);
- };
-
- // Internal implementation of a recursive `flatten` function.
- var flatten = function(input, shallow, output) {
- each(input, function(value) {
- if (_.isArray(value)) {
- shallow ? push.apply(output, value) : flatten(value, shallow, output);
- } else {
- output.push(value);
- }
- });
- return output;
- };
-
- // Return a completely flattened version of an array.
- _.flatten = function(array, shallow) {
- return flatten(array, shallow, []);
- };
-
- // Return a version of the array that does not contain the specified value(s).
- _.without = function(array) {
- return _.difference(array, slice.call(arguments, 1));
- };
-
- // Produce a duplicate-free version of the array. If the array has already
- // been sorted, you have the option of using a faster algorithm.
- // Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted, iterator, context) {
- if (_.isFunction(isSorted)) {
- context = iterator;
- iterator = isSorted;
- isSorted = false;
- }
- var initial = iterator ? _.map(array, iterator, context) : array;
- var results = [];
- var seen = [];
- each(initial, function(value, index) {
- if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
- seen.push(value);
- results.push(array[index]);
- }
- });
- return results;
- };
-
- // Produce an array that contains the union: each distinct element from all of
- // the passed-in arrays.
- _.union = function() {
- return _.uniq(concat.apply(ArrayProto, arguments));
- };
-
- // Produce an array that contains every item shared between all the
- // passed-in arrays.
- _.intersection = function(array) {
- var rest = slice.call(arguments, 1);
- return _.filter(_.uniq(array), function(item) {
- return _.every(rest, function(other) {
- return _.indexOf(other, item) >= 0;
- });
- });
- };
-
- // Take the difference between one array and a number of other arrays.
- // Only the elements present in just the first array will remain.
- _.difference = function(array) {
- var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
- return _.filter(array, function(value){ return !_.contains(rest, value); });
- };
-
- // Zip together multiple lists into a single array -- elements that share
- // an index go together.
- _.zip = function() {
- var args = slice.call(arguments);
- var length = _.max(_.pluck(args, 'length'));
- var results = new Array(length);
- for (var i = 0; i < length; i++) {
- results[i] = _.pluck(args, "" + i);
- }
- return results;
- };
-
- // Converts lists into objects. Pass either a single array of `[key, value]`
- // pairs, or two parallel arrays of the same length -- one of keys, and one of
- // the corresponding values.
- _.object = function(list, values) {
- if (list == null) return {};
- var result = {};
- for (var i = 0, l = list.length; i < l; i++) {
- if (values) {
- result[list[i]] = values[i];
- } else {
- result[list[i][0]] = list[i][1];
- }
- }
- return result;
- };
-
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
- // we need this function. Return the position of the first occurrence of an
- // item in an array, or -1 if the item is not included in the array.
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
- // If the array is large and already in sort order, pass `true`
- // for **isSorted** to use binary search.
- _.indexOf = function(array, item, isSorted) {
- if (array == null) return -1;
- var i = 0, l = array.length;
- if (isSorted) {
- if (typeof isSorted == 'number') {
- i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
- } else {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
- }
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
- for (; i < l; i++) if (array[i] === item) return i;
- return -1;
- };
-
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
- _.lastIndexOf = function(array, item, from) {
- if (array == null) return -1;
- var hasIndex = from != null;
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
- return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
- }
- var i = (hasIndex ? from : array.length);
- while (i--) if (array[i] === item) return i;
- return -1;
- };
-
- // Generate an integer Array containing an arithmetic progression. A port of
- // the native Python `range()` function. See
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
- _.range = function(start, stop, step) {
- if (arguments.length <= 1) {
- stop = start || 0;
- start = 0;
- }
- step = arguments[2] || 1;
-
- var len = Math.max(Math.ceil((stop - start) / step), 0);
- var idx = 0;
- var range = new Array(len);
-
- while(idx < len) {
- range[idx++] = start;
- start += step;
- }
-
- return range;
- };
-
- // Function (ahem) Functions
- // ------------------
-
- // Create a function bound to a given object (assigning `this`, and arguments,
- // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
- // available.
- _.bind = function(func, context) {
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- var args = slice.call(arguments, 2);
- return function() {
- return func.apply(context, args.concat(slice.call(arguments)));
- };
- };
-
- // Partially apply a function by creating a version that has had some of its
- // arguments pre-filled, without changing its dynamic `this` context.
- _.partial = function(func) {
- var args = slice.call(arguments, 1);
- return function() {
- return func.apply(this, args.concat(slice.call(arguments)));
- };
- };
-
- // Bind all of an object's methods to that object. Useful for ensuring that
- // all callbacks defined on an object belong to it.
- _.bindAll = function(obj) {
- var funcs = slice.call(arguments, 1);
- if (funcs.length === 0) funcs = _.functions(obj);
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
- return obj;
- };
-
- // Memoize an expensive function by storing its results.
- _.memoize = function(func, hasher) {
- var memo = {};
- hasher || (hasher = _.identity);
- return function() {
- var key = hasher.apply(this, arguments);
- return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
- };
- };
-
- // Delays a function for the given number of milliseconds, and then calls
- // it with the arguments supplied.
- _.delay = function(func, wait) {
- var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(null, args); }, wait);
- };
-
- // Defers a function, scheduling it to run after the current call stack has
- // cleared.
- _.defer = function(func) {
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
- };
-
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time.
- _.throttle = function(func, wait) {
- var context, args, timeout, result;
- var previous = 0;
- var later = function() {
- previous = new Date;
- timeout = null;
- result = func.apply(context, args);
- };
- return function() {
- var now = new Date;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0) {
- clearTimeout(timeout);
- timeout = null;
- previous = now;
- result = func.apply(context, args);
- } else if (!timeout) {
- timeout = setTimeout(later, remaining);
- }
- return result;
- };
- };
-
- // Returns a function, that, as long as it continues to be invoked, will not
- // be triggered. The function will be called after it stops being called for
- // N milliseconds. If `immediate` is passed, trigger the function on the
- // leading edge, instead of the trailing.
- _.debounce = function(func, wait, immediate) {
- var timeout, result;
- return function() {
- var context = this, args = arguments;
- var later = function() {
- timeout = null;
- if (!immediate) result = func.apply(context, args);
- };
- var callNow = immediate && !timeout;
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- if (callNow) result = func.apply(context, args);
- return result;
- };
- };
-
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- memo = func.apply(this, arguments);
- func = null;
- return memo;
- };
- };
-
- // Returns the first function passed as an argument to the second,
- // allowing you to adjust arguments, run code before and after, and
- // conditionally execute the original function.
- _.wrap = function(func, wrapper) {
- return function() {
- var args = [func];
- push.apply(args, arguments);
- return wrapper.apply(this, args);
- };
- };
-
- // Returns a function that is the composition of a list of functions, each
- // consuming the return value of the function that follows.
- _.compose = function() {
- var funcs = arguments;
- return function() {
- var args = arguments;
- for (var i = funcs.length - 1; i >= 0; i--) {
- args = [funcs[i].apply(this, args)];
- }
- return args[0];
- };
- };
-
- // Returns a function that will only be executed after being called N times.
- _.after = function(times, func) {
- if (times <= 0) return func();
- return function() {
- if (--times < 1) {
- return func.apply(this, arguments);
- }
- };
- };
-
- // Object Functions
- // ----------------
-
- // Retrieve the names of an object's properties.
- // Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = nativeKeys || function(obj) {
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
- var keys = [];
- for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
- return keys;
- };
-
- // Retrieve the values of an object's properties.
- _.values = function(obj) {
- var values = [];
- for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
- return values;
- };
-
- // Convert an object into a list of `[key, value]` pairs.
- _.pairs = function(obj) {
- var pairs = [];
- for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
- return pairs;
- };
-
- // Invert the keys and values of an object. The values must be serializable.
- _.invert = function(obj) {
- var result = {};
- for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
- return result;
- };
-
- // Return a sorted list of the function names available on the object.
- // Aliased as `methods`
- _.functions = _.methods = function(obj) {
- var names = [];
- for (var key in obj) {
- if (_.isFunction(obj[key])) names.push(key);
- }
- return names.sort();
- };
-
- // Extend a given object with all the properties in passed-in object(s).
- _.extend = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- if (source) {
- for (var prop in source) {
- obj[prop] = source[prop];
- }
- }
- });
- return obj;
- };
-
- // Return a copy of the object only containing the whitelisted properties.
- _.pick = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- each(keys, function(key) {
- if (key in obj) copy[key] = obj[key];
- });
- return copy;
- };
-
- // Return a copy of the object without the blacklisted properties.
- _.omit = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- for (var key in obj) {
- if (!_.contains(keys, key)) copy[key] = obj[key];
- }
- return copy;
- };
-
- // Fill in a given object with default properties.
- _.defaults = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- if (source) {
- for (var prop in source) {
- if (obj[prop] == null) obj[prop] = source[prop];
- }
- }
- });
- return obj;
- };
-
- // Create a (shallow-cloned) duplicate of an object.
- _.clone = function(obj) {
- if (!_.isObject(obj)) return obj;
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
- };
-
- // Invokes interceptor with the obj, and then returns obj.
- // The primary purpose of this method is to "tap into" a method chain, in
- // order to perform operations on intermediate results within the chain.
- _.tap = function(obj, interceptor) {
- interceptor(obj);
- return obj;
- };
-
- // Internal recursive comparison function for `isEqual`.
- var eq = function(a, b, aStack, bStack) {
- // Identical objects are equal. `0 === -0`, but they aren't identical.
- // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
- if (a === b) return a !== 0 || 1 / a == 1 / b;
- // A strict comparison is necessary because `null == undefined`.
- if (a == null || b == null) return a === b;
- // Unwrap any wrapped objects.
- if (a instanceof _) a = a._wrapped;
- if (b instanceof _) b = b._wrapped;
- // Compare `[[Class]]` names.
- var className = toString.call(a);
- if (className != toString.call(b)) return false;
- switch (className) {
- // Strings, numbers, dates, and booleans are compared by value.
- case '[object String]':
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
- // equivalent to `new String("5")`.
- return a == String(b);
- case '[object Number]':
- // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
- // other numeric values.
- return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
- case '[object Date]':
- case '[object Boolean]':
- // Coerce dates and booleans to numeric primitive values. Dates are compared by their
- // millisecond representations. Note that invalid dates with millisecond representations
- // of `NaN` are not equivalent.
- return +a == +b;
- // RegExps are compared by their source patterns and flags.
- case '[object RegExp]':
- return a.source == b.source &&
- a.global == b.global &&
- a.multiline == b.multiline &&
- a.ignoreCase == b.ignoreCase;
- }
- if (typeof a != 'object' || typeof b != 'object') return false;
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
- var length = aStack.length;
- while (length--) {
- // Linear search. Performance is inversely proportional to the number of
- // unique nested structures.
- if (aStack[length] == a) return bStack[length] == b;
- }
- // Add the first object to the stack of traversed objects.
- aStack.push(a);
- bStack.push(b);
- var size = 0, result = true;
- // Recursively compare objects and arrays.
- if (className == '[object Array]') {
- // Compare array lengths to determine if a deep comparison is necessary.
- size = a.length;
- result = size == b.length;
- if (result) {
- // Deep compare the contents, ignoring non-numeric properties.
- while (size--) {
- if (!(result = eq(a[size], b[size], aStack, bStack))) break;
- }
- }
- } else {
- // Objects with different constructors are not equivalent, but `Object`s
- // from different frames are.
- var aCtor = a.constructor, bCtor = b.constructor;
- if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
- _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
- return false;
- }
- // Deep compare objects.
- for (var key in a) {
- if (_.has(a, key)) {
- // Count the expected number of properties.
- size++;
- // Deep compare each member.
- if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
- }
- }
- // Ensure that both objects contain the same number of properties.
- if (result) {
- for (key in b) {
- if (_.has(b, key) && !(size--)) break;
- }
- result = !size;
- }
- }
- // Remove the first object from the stack of traversed objects.
- aStack.pop();
- bStack.pop();
- return result;
- };
-
- // Perform a deep comparison to check if two objects are equal.
- _.isEqual = function(a, b) {
- return eq(a, b, [], []);
- };
-
- // Is a given array, string, or object empty?
- // An "empty" object has no enumerable own-properties.
- _.isEmpty = function(obj) {
- if (obj == null) return true;
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
- for (var key in obj) if (_.has(obj, key)) return false;
- return true;
- };
-
- // Is a given value a DOM element?
- _.isElement = function(obj) {
- return !!(obj && obj.nodeType === 1);
- };
-
- // Is a given value an array?
- // Delegates to ECMA5's native Array.isArray
- _.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) == '[object Array]';
- };
-
- // Is a given variable an object?
- _.isObject = function(obj) {
- return obj === Object(obj);
- };
-
- // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
- each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
- _['is' + name] = function(obj) {
- return toString.call(obj) == '[object ' + name + ']';
- };
- });
-
- // Define a fallback version of the method in browsers (ahem, IE), where
- // there isn't any inspectable "Arguments" type.
- if (!_.isArguments(arguments)) {
- _.isArguments = function(obj) {
- return !!(obj && _.has(obj, 'callee'));
- };
- }
-
- // Optimize `isFunction` if appropriate.
- if (typeof (/./) !== 'function') {
- _.isFunction = function(obj) {
- return typeof obj === 'function';
- };
- }
-
- // Is a given object a finite number?
- _.isFinite = function(obj) {
- return isFinite(obj) && !isNaN(parseFloat(obj));
- };
-
- // Is the given value `NaN`? (NaN is the only number which does not equal itself).
- _.isNaN = function(obj) {
- return _.isNumber(obj) && obj != +obj;
- };
-
- // Is a given value a boolean?
- _.isBoolean = function(obj) {
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
- };
-
- // Is a given value equal to null?
- _.isNull = function(obj) {
- return obj === null;
- };
-
- // Is a given variable undefined?
- _.isUndefined = function(obj) {
- return obj === void 0;
- };
-
- // Shortcut function for checking if an object has a given property directly
- // on itself (in other words, not on a prototype).
- _.has = function(obj, key) {
- return hasOwnProperty.call(obj, key);
- };
-
- // Utility Functions
- // -----------------
-
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
- // previous owner. Returns a reference to the Underscore object.
- _.noConflict = function() {
- root._ = previousUnderscore;
- return this;
- };
-
- // Keep the identity function around for default iterators.
- _.identity = function(value) {
- return value;
- };
-
- // Run a function **n** times.
- _.times = function(n, iterator, context) {
- var accum = Array(n);
- for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
- return accum;
- };
-
- // Return a random integer between min and max (inclusive).
- _.random = function(min, max) {
- if (max == null) {
- max = min;
- min = 0;
- }
- return min + Math.floor(Math.random() * (max - min + 1));
- };
-
- // List of HTML entities for escaping.
- var entityMap = {
- escape: {
- '&': '&amp;',
- '<': '&lt;',
- '>': '&gt;',
- '"': '&quot;',
- "'": '&#x27;',
- '/': '&#x2F;'
- }
- };
- entityMap.unescape = _.invert(entityMap.escape);
-
- // Regexes containing the keys and values listed immediately above.
- var entityRegexes = {
- escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
- unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
- };
-
- // Functions for escaping and unescaping strings to/from HTML interpolation.
- _.each(['escape', 'unescape'], function(method) {
- _[method] = function(string) {
- if (string == null) return '';
- return ('' + string).replace(entityRegexes[method], function(match) {
- return entityMap[method][match];
- });
- };
- });
-
- // If the value of the named property is a function then invoke it;
- // otherwise, return it.
- _.result = function(object, property) {
- if (object == null) return null;
- var value = object[property];
- return _.isFunction(value) ? value.call(object) : value;
- };
-
- // Add your own custom functions to the Underscore object.
- _.mixin = function(obj) {
- each(_.functions(obj), function(name){
- var func = _[name] = obj[name];
- _.prototype[name] = function() {
- var args = [this._wrapped];
- push.apply(args, arguments);
- return result.call(this, func.apply(_, args));
- };
- });
- };
-
- // Generate a unique integer id (unique within the entire client session).
- // Useful for temporary DOM ids.
- var idCounter = 0;
- _.uniqueId = function(prefix) {
- var id = ++idCounter + '';
- return prefix ? prefix + id : id;
- };
-
- // By default, Underscore uses ERB-style template delimiters, change the
- // following template settings to use alternative delimiters.
- _.templateSettings = {
- evaluate : /<%([\s\S]+?)%>/g,
- interpolate : /<%=([\s\S]+?)%>/g,
- escape : /<%-([\s\S]+?)%>/g
- };
-
- // When customizing `templateSettings`, if you don't want to define an
- // interpolation, evaluation or escaping regex, we need one that is
- // guaranteed not to match.
- var noMatch = /(.)^/;
-
- // Certain characters need to be escaped so that they can be put into a
- // string literal.
- var escapes = {
- "'": "'",
- '\\': '\\',
- '\r': 'r',
- '\n': 'n',
- '\t': 't',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
-
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
-
- // JavaScript micro-templating, similar to John Resig's implementation.
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
- // and correctly escapes quotes within interpolated code.
- _.template = function(text, data, settings) {
- var render;
- settings = _.defaults({}, settings, _.templateSettings);
-
- // Combine delimiters into one regular expression via alternation.
- var matcher = new RegExp([
- (settings.escape || noMatch).source,
- (settings.interpolate || noMatch).source,
- (settings.evaluate || noMatch).source
- ].join('|') + '|$', 'g');
-
- // Compile the template source, escaping string literals appropriately.
- var index = 0;
- var source = "__p+='";
- text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
- source += text.slice(index, offset)
- .replace(escaper, function(match) { return '\\' + escapes[match]; });
-
- if (escape) {
- source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
- }
- if (interpolate) {
- source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
- }
- if (evaluate) {
- source += "';\n" + evaluate + "\n__p+='";
- }
- index = offset + match.length;
- return match;
- });
- source += "';\n";
-
- // If a variable is not specified, place data values in local scope.
- if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
-
- source = "var __t,__p='',__j=Array.prototype.join," +
- "print=function(){__p+=__j.call(arguments,'');};\n" +
- source + "return __p;\n";
-
- try {
- render = new Function(settings.variable || 'obj', '_', source);
- } catch (e) {
- e.source = source;
- throw e;
- }
-
- if (data) return render(data, _);
- var template = function(data) {
- return render.call(this, data, _);
- };
-
- // Provide the compiled function source as a convenience for precompilation.
- template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
-
- return template;
- };
-
- // Add a "chain" function, which will delegate to the wrapper.
- _.chain = function(obj) {
- return _(obj).chain();
- };
-
- // OOP
- // ---------------
- // If Underscore is called as a function, it returns a wrapped object that
- // can be used OO-style. This wrapper holds altered versions of all the
- // underscore functions. Wrapped objects may be chained.
-
- // Helper function to continue chaining intermediate results.
- var result = function(obj) {
- return this._chain ? _(obj).chain() : obj;
- };
-
- // Add all of the Underscore functions to the wrapper object.
- _.mixin(_);
-
- // Add all mutator Array functions to the wrapper.
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
- var method = ArrayProto[name];
- _.prototype[name] = function() {
- var obj = this._wrapped;
- method.apply(obj, arguments);
- if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
- return result.call(this, obj);
- };
- });
-
- // Add all accessor Array functions to the wrapper.
- each(['concat', 'join', 'slice'], function(name) {
- var method = ArrayProto[name];
- _.prototype[name] = function() {
- return result.call(this, method.apply(this._wrapped, arguments));
- };
- });
-
- _.extend(_.prototype, {
-
- // Start chaining a wrapped Underscore object.
- chain: function() {
- this._chain = true;
- return this;
- },
-
- // Extracts the result from a wrapped and chained object.
- value: function() {
- return this._wrapped;
- }
-
- });
-
-}).call(this);
-
-})()
-},{}],14:[function(require,module,exports){
-exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
- var e, m,
- eLen = nBytes * 8 - mLen - 1,
- eMax = (1 << eLen) - 1,
- eBias = eMax >> 1,
- nBits = -7,
- i = isBE ? 0 : (nBytes - 1),
- d = isBE ? 1 : -1,
- s = buffer[offset + i];
-
- i += d;
-
- e = s & ((1 << (-nBits)) - 1);
- s >>= (-nBits);
- nBits += eLen;
- for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
-
- m = e & ((1 << (-nBits)) - 1);
- e >>= (-nBits);
- nBits += mLen;
- for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
-
- if (e === 0) {
- e = 1 - eBias;
- } else if (e === eMax) {
- return m ? NaN : ((s ? -1 : 1) * Infinity);
- } else {
- m = m + Math.pow(2, mLen);
- e = e - eBias;
- }
- return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
-};
-
-exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
- var e, m, c,
- eLen = nBytes * 8 - mLen - 1,
- eMax = (1 << eLen) - 1,
- eBias = eMax >> 1,
- rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
- i = isBE ? (nBytes - 1) : 0,
- d = isBE ? -1 : 1,
- s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
-
- value = Math.abs(value);
-
- if (isNaN(value) || value === Infinity) {
- m = isNaN(value) ? 1 : 0;
- e = eMax;
- } else {
- e = Math.floor(Math.log(value) / Math.LN2);
- if (value * (c = Math.pow(2, -e)) < 1) {
- e--;
- c *= 2;
- }
- if (e + eBias >= 1) {
- value += rt / c;
- } else {
- value += rt * Math.pow(2, 1 - eBias);
- }
- if (value * c >= 2) {
- e++;
- c /= 2;
- }
-
- if (e + eBias >= eMax) {
- m = 0;
- e = eMax;
- } else if (e + eBias >= 1) {
- m = (value * c - 1) * Math.pow(2, mLen);
- e = e + eBias;
- } else {
- m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
- e = 0;
- }
- }
-
- for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
-
- e = (e << mLen) | m;
- eLen += mLen;
- for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
-
- buffer[offset + i - d] |= s * 128;
-};
-
-},{}],13:[function(require,module,exports){
-(function(){function SlowBuffer (size) {
- this.length = size;
-};
-
-var assert = require('assert');
-
-exports.INSPECT_MAX_BYTES = 50;
-
-
-function toHex(n) {
- if (n < 16) return '0' + n.toString(16);
- return n.toString(16);
-}
-
-function utf8ToBytes(str) {
- var byteArray = [];
- for (var i = 0; i < str.length; i++)
- if (str.charCodeAt(i) <= 0x7F)
- byteArray.push(str.charCodeAt(i));
- else {
- var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
- for (var j = 0; j < h.length; j++)
- byteArray.push(parseInt(h[j], 16));
- }
-
- return byteArray;
-}
-
-function asciiToBytes(str) {
- var byteArray = []
- for (var i = 0; i < str.length; i++ )
- // Node's code seems to be doing this and not & 0x7F..
- byteArray.push( str.charCodeAt(i) & 0xFF );
-
- return byteArray;
-}
-
-function base64ToBytes(str) {
- return require("base64-js").toByteArray(str);
-}
-
-SlowBuffer.byteLength = function (str, encoding) {
- switch (encoding || "utf8") {
- case 'hex':
- return str.length / 2;
-
- case 'utf8':
- case 'utf-8':
- return utf8ToBytes(str).length;
-
- case 'ascii':
- case 'binary':
- return str.length;
-
- case 'base64':
- return base64ToBytes(str).length;
-
- default:
- throw new Error('Unknown encoding');
- }
-};
-
-function blitBuffer(src, dst, offset, length) {
- var pos, i = 0;
- while (i < length) {
- if ((i+offset >= dst.length) || (i >= src.length))
- break;
-
- dst[i + offset] = src[i];
- i++;
- }
- return i;
-}
-
-SlowBuffer.prototype.utf8Write = function (string, offset, length) {
- var bytes, pos;
- return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
-};
-
-SlowBuffer.prototype.asciiWrite = function (string, offset, length) {
- var bytes, pos;
- return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
-};
-
-SlowBuffer.prototype.binaryWrite = SlowBuffer.prototype.asciiWrite;
-
-SlowBuffer.prototype.base64Write = function (string, offset, length) {
- var bytes, pos;
- return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
-};
-
-SlowBuffer.prototype.base64Slice = function (start, end) {
- var bytes = Array.prototype.slice.apply(this, arguments)
- return require("base64-js").fromByteArray(bytes);
-}
-
-function decodeUtf8Char(str) {
- try {
- return decodeURIComponent(str);
- } catch (err) {
- return String.fromCharCode(0xFFFD); // UTF 8 invalid char
- }
-}
-
-SlowBuffer.prototype.utf8Slice = function () {
- var bytes = Array.prototype.slice.apply(this, arguments);
- var res = "";
- var tmp = "";
- var i = 0;
- while (i < bytes.length) {
- if (bytes[i] <= 0x7F) {
- res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
- tmp = "";
- } else
- tmp += "%" + bytes[i].toString(16);
-
- i++;
- }
-
- return res + decodeUtf8Char(tmp);
-}
-
-SlowBuffer.prototype.asciiSlice = function () {
- var bytes = Array.prototype.slice.apply(this, arguments);
- var ret = "";
- for (var i = 0; i < bytes.length; i++)
- ret += String.fromCharCode(bytes[i]);
- return ret;
-}
-
-SlowBuffer.prototype.binarySlice = SlowBuffer.prototype.asciiSlice;
-
-SlowBuffer.prototype.inspect = function() {
- var out = [],
- len = this.length;
- for (var i = 0; i < len; i++) {
- out[i] = toHex(this[i]);
- if (i == exports.INSPECT_MAX_BYTES) {
- out[i + 1] = '...';
- break;
- }
- }
- return '<SlowBuffer ' + out.join(' ') + '>';
-};
-
-
-SlowBuffer.prototype.hexSlice = function(start, end) {
- var len = this.length;
-
- if (!start || start < 0) start = 0;
- if (!end || end < 0 || end > len) end = len;
-
- var out = '';
- for (var i = start; i < end; i++) {
- out += toHex(this[i]);
- }
- return out;
-};
-
-
-SlowBuffer.prototype.toString = function(encoding, start, end) {
- encoding = String(encoding || 'utf8').toLowerCase();
- start = +start || 0;
- if (typeof end == 'undefined') end = this.length;
-
- // Fastpath empty strings
- if (+end == start) {
- return '';
- }
-
- switch (encoding) {
- case 'hex':
- return this.hexSlice(start, end);
-
- case 'utf8':
- case 'utf-8':
- return this.utf8Slice(start, end);
-
- case 'ascii':
- return this.asciiSlice(start, end);
-
- case 'binary':
- return this.binarySlice(start, end);
-
- case 'base64':
- return this.base64Slice(start, end);
-
- case 'ucs2':
- case 'ucs-2':
- return this.ucs2Slice(start, end);
-
- default:
- throw new Error('Unknown encoding');
- }
-};
-
-
-SlowBuffer.prototype.hexWrite = function(string, offset, length) {
- offset = +offset || 0;
- var remaining = this.length - offset;
- if (!length) {
- length = remaining;
- } else {
- length = +length;
- if (length > remaining) {
- length = remaining;
- }
- }
-
- // must be an even number of digits
- var strLen = string.length;
- if (strLen % 2) {
- throw new Error('Invalid hex string');
- }
- if (length > strLen / 2) {
- length = strLen / 2;
- }
- for (var i = 0; i < length; i++) {
- var byte = parseInt(string.substr(i * 2, 2), 16);
- if (isNaN(byte)) throw new Error('Invalid hex string');
- this[offset + i] = byte;
- }
- SlowBuffer._charsWritten = i * 2;
- return i;
-};
-
-
-SlowBuffer.prototype.write = function(string, offset, length, encoding) {
- // Support both (string, offset, length, encoding)
- // and the legacy (string, encoding, offset, length)
- if (isFinite(offset)) {
- if (!isFinite(length)) {
- encoding = length;
- length = undefined;
- }
- } else { // legacy
- var swap = encoding;
- encoding = offset;
- offset = length;
- length = swap;
- }
-
- offset = +offset || 0;
- var remaining = this.length - offset;
- if (!length) {
- length = remaining;
- } else {
- length = +length;
- if (length > remaining) {
- length = remaining;
- }
- }
- encoding = String(encoding || 'utf8').toLowerCase();
-
- switch (encoding) {
- case 'hex':
- return this.hexWrite(string, offset, length);
-
- case 'utf8':
- case 'utf-8':
- return this.utf8Write(string, offset, length);
-
- case 'ascii':
- return this.asciiWrite(string, offset, length);
-
- case 'binary':
- return this.binaryWrite(string, offset, length);
-
- case 'base64':
- return this.base64Write(string, offset, length);
-
- case 'ucs2':
- case 'ucs-2':
- return this.ucs2Write(string, offset, length);
-
- default:
- throw new Error('Unknown encoding');
- }
-};
-
-
-// slice(start, end)
-SlowBuffer.prototype.slice = function(start, end) {
- if (end === undefined) end = this.length;
-
- if (end > this.length) {
- throw new Error('oob');
- }
- if (start > end) {
- throw new Error('oob');
- }
-
- return new Buffer(this, end - start, +start);
-};
-
-SlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) {
- var temp = [];
- for (var i=sourcestart; i<sourceend; i++) {
- assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
- temp.push(this[i]);
- }
-
- for (var i=targetstart; i<targetstart+temp.length; i++) {
- target[i] = temp[i-targetstart];
- }
-};
-
-SlowBuffer.prototype.fill = function(value, start, end) {
- if (end > this.length) {
- throw new Error('oob');
- }
- if (start > end) {
- throw new Error('oob');
- }
-
- for (var i = start; i < end; i++) {
- this[i] = value;
- }
-}
-
-function coerce(length) {
- // Coerce length to a number (possibly NaN), round up
- // in case it's fractional (e.g. 123.456) then do a
- // double negate to coerce a NaN to 0. Easy, right?
- length = ~~Math.ceil(+length);
- return length < 0 ? 0 : length;
-}
-
-
-// Buffer
-
-function Buffer(subject, encoding, offset) {
- if (!(this instanceof Buffer)) {
- return new Buffer(subject, encoding, offset);
- }
-
- var type;
-
- // Are we slicing?
- if (typeof offset === 'number') {
- this.length = coerce(encoding);
- this.parent = subject;
- this.offset = offset;
- } else {
- // Find the length
- switch (type = typeof subject) {
- case 'number':
- this.length = coerce(subject);
- break;
-
- case 'string':
- this.length = Buffer.byteLength(subject, encoding);
- break;
-
- case 'object': // Assume object is an array
- this.length = coerce(subject.length);
- break;
-
- default:
- throw new Error('First argument needs to be a number, ' +
- 'array or string.');
- }
-
- if (this.length > Buffer.poolSize) {
- // Big buffer, just alloc one.
- this.parent = new SlowBuffer(this.length);
- this.offset = 0;
-
- } else {
- // Small buffer.
- if (!pool || pool.length - pool.used < this.length) allocPool();
- this.parent = pool;
- this.offset = pool.used;
- pool.used += this.length;
- }
-
- // Treat array-ish objects as a byte array.
- if (isArrayIsh(subject)) {
- for (var i = 0; i < this.length; i++) {
- if (subject instanceof Buffer) {
- this.parent[i + this.offset] = subject.readUInt8(i);
- }
- else {
- this.parent[i + this.offset] = subject[i];
- }
- }
- } else if (type == 'string') {
- // We are a string
- this.length = this.write(subject, 0, encoding);
- }
- }
-
-}
-
-function isArrayIsh(subject) {
- return Array.isArray(subject) || Buffer.isBuffer(subject) ||
- subject && typeof subject === 'object' &&
- typeof subject.length === 'number';
-}
-
-exports.SlowBuffer = SlowBuffer;
-exports.Buffer = Buffer;
-
-Buffer.poolSize = 8 * 1024;
-var pool;
-
-function allocPool() {
- pool = new SlowBuffer(Buffer.poolSize);
- pool.used = 0;
-}
-
-
-// Static methods
-Buffer.isBuffer = function isBuffer(b) {
- return b instanceof Buffer || b instanceof SlowBuffer;
-};
-
-Buffer.concat = function (list, totalLength) {
- if (!Array.isArray(list)) {
- throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
- list should be an Array.");
- }
-
- if (list.length === 0) {
- return new Buffer(0);
- } else if (list.length === 1) {
- return list[0];
- }
-
- if (typeof totalLength !== 'number') {
- totalLength = 0;
- for (var i = 0; i < list.length; i++) {
- var buf = list[i];
- totalLength += buf.length;
- }
- }
-
- var buffer = new Buffer(totalLength);
- var pos = 0;
- for (var i = 0; i < list.length; i++) {
- var buf = list[i];
- buf.copy(buffer, pos);
- pos += buf.length;
- }
- return buffer;
-};
-
-// Inspect
-Buffer.prototype.inspect = function inspect() {
- var out = [],
- len = this.length;
-
- for (var i = 0; i < len; i++) {
- out[i] = toHex(this.parent[i + this.offset]);
- if (i == exports.INSPECT_MAX_BYTES) {
- out[i + 1] = '...';
- break;
- }
- }
-
- return '<Buffer ' + out.join(' ') + '>';
-};
-
-
-Buffer.prototype.get = function get(i) {
- if (i < 0 || i >= this.length) throw new Error('oob');
- return this.parent[this.offset + i];
-};
-
-
-Buffer.prototype.set = function set(i, v) {
- if (i < 0 || i >= this.length) throw new Error('oob');
- return this.parent[this.offset + i] = v;
-};
-
-
-// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
-Buffer.prototype.write = function(string, offset, length, encoding) {
- // Support both (string, offset, length, encoding)
- // and the legacy (string, encoding, offset, length)
- if (isFinite(offset)) {
- if (!isFinite(length)) {
- encoding = length;
- length = undefined;
- }
- } else { // legacy
- var swap = encoding;
- encoding = offset;
- offset = length;
- length = swap;
- }
-
- offset = +offset || 0;
- var remaining = this.length - offset;
- if (!length) {
- length = remaining;
- } else {
- length = +length;
- if (length > remaining) {
- length = remaining;
- }
- }
- encoding = String(encoding || 'utf8').toLowerCase();
-
- var ret;
- switch (encoding) {
- case 'hex':
- ret = this.parent.hexWrite(string, this.offset + offset, length);
- break;
-
- case 'utf8':
- case 'utf-8':
- ret = this.parent.utf8Write(string, this.offset + offset, length);
- break;
-
- case 'ascii':
- ret = this.parent.asciiWrite(string, this.offset + offset, length);
- break;
-
- case 'binary':
- ret = this.parent.binaryWrite(string, this.offset + offset, length);
- break;
-
- case 'base64':
- // Warning: maxLength not taken into account in base64Write
- ret = this.parent.base64Write(string, this.offset + offset, length);
- break;
-
- case 'ucs2':
- case 'ucs-2':
- ret = this.parent.ucs2Write(string, this.offset + offset, length);
- break;
-
- default:
- throw new Error('Unknown encoding');
- }
-
- Buffer._charsWritten = SlowBuffer._charsWritten;
-
- return ret;
-};
-
-
-// toString(encoding, start=0, end=buffer.length)
-Buffer.prototype.toString = function(encoding, start, end) {
- encoding = String(encoding || 'utf8').toLowerCase();
-
- if (typeof start == 'undefined' || start < 0) {
- start = 0;
- } else if (start > this.length) {
- start = this.length;
- }
-
- if (typeof end == 'undefined' || end > this.length) {
- end = this.length;
- } else if (end < 0) {
- end = 0;
- }
-
- start = start + this.offset;
- end = end + this.offset;
-
- switch (encoding) {
- case 'hex':
- return this.parent.hexSlice(start, end);
-
- case 'utf8':
- case 'utf-8':
- return this.parent.utf8Slice(start, end);
-
- case 'ascii':
- return this.parent.asciiSlice(start, end);
-
- case 'binary':
- return this.parent.binarySlice(start, end);
-
- case 'base64':
- return this.parent.base64Slice(start, end);
-
- case 'ucs2':
- case 'ucs-2':
- return this.parent.ucs2Slice(start, end);
-
- default:
- throw new Error('Unknown encoding');
- }
-};
-
-
-// byteLength
-Buffer.byteLength = SlowBuffer.byteLength;
-
-
-// fill(value, start=0, end=buffer.length)
-Buffer.prototype.fill = function fill(value, start, end) {
- value || (value = 0);
- start || (start = 0);
- end || (end = this.length);
-
- if (typeof value === 'string') {
- value = value.charCodeAt(0);
- }
- if (!(typeof value === 'number') || isNaN(value)) {
- throw new Error('value is not a number');
- }
-
- if (end < start) throw new Error('end < start');
-
- // Fill 0 bytes; we're done
- if (end === start) return 0;
- if (this.length == 0) return 0;
-
- if (start < 0 || start >= this.length) {
- throw new Error('start out of bounds');
- }
-
- if (end < 0 || end > this.length) {
- throw new Error('end out of bounds');
- }
-
- return this.parent.fill(value,
- start + this.offset,
- end + this.offset);
-};
-
-
-// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
-Buffer.prototype.copy = function(target, target_start, start, end) {
- var source = this;
- start || (start = 0);
- end || (end = this.length);
- target_start || (target_start = 0);
-
- if (end < start) throw new Error('sourceEnd < sourceStart');
-
- // Copy 0 bytes; we're done
- if (end === start) return 0;
- if (target.length == 0 || source.length == 0) return 0;
-
- if (target_start < 0 || target_start >= target.length) {
- throw new Error('targetStart out of bounds');
- }
-
- if (start < 0 || start >= source.length) {
- throw new Error('sourceStart out of bounds');
- }
-
- if (end < 0 || end > source.length) {
- throw new Error('sourceEnd out of bounds');
- }
-
- // Are we oob?
- if (end > this.length) {
- end = this.length;
- }
-
- if (target.length - target_start < end - start) {
- end = target.length - target_start + start;
- }
-
- return this.parent.copy(target.parent,
- target_start + target.offset,
- start + this.offset,
- end + this.offset);
-};
-
-
-// slice(start, end)
-Buffer.prototype.slice = function(start, end) {
- if (end === undefined) end = this.length;
- if (end > this.length) throw new Error('oob');
- if (start > end) throw new Error('oob');
-
- return new Buffer(this.parent, end - start, +start + this.offset);
-};
-
-
-// Legacy methods for backwards compatibility.
-
-Buffer.prototype.utf8Slice = function(start, end) {
- return this.toString('utf8', start, end);
-};
-
-Buffer.prototype.binarySlice = function(start, end) {
- return this.toString('binary', start, end);
-};
-
-Buffer.prototype.asciiSlice = function(start, end) {
- return this.toString('ascii', start, end);
-};
-
-Buffer.prototype.utf8Write = function(string, offset) {
- return this.write(string, offset, 'utf8');
-};
-
-Buffer.prototype.binaryWrite = function(string, offset) {
- return this.write(string, offset, 'binary');
-};
-
-Buffer.prototype.asciiWrite = function(string, offset) {
- return this.write(string, offset, 'ascii');
-};
-
-Buffer.prototype.readUInt8 = function(offset, noAssert) {
- var buffer = this;
-
- if (!noAssert) {
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- if (offset >= buffer.length) return;
-
- return buffer.parent[buffer.offset + offset];
-};
-
-function readUInt16(buffer, offset, isBigEndian, noAssert) {
- var val = 0;
-
-
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 1 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- if (offset >= buffer.length) return 0;
-
- if (isBigEndian) {
- val = buffer.parent[buffer.offset + offset] << 8;
- if (offset + 1 < buffer.length) {
- val |= buffer.parent[buffer.offset + offset + 1];
- }
- } else {
- val = buffer.parent[buffer.offset + offset];
- if (offset + 1 < buffer.length) {
- val |= buffer.parent[buffer.offset + offset + 1] << 8;
- }
- }
-
- return val;
-}
-
-Buffer.prototype.readUInt16LE = function(offset, noAssert) {
- return readUInt16(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readUInt16BE = function(offset, noAssert) {
- return readUInt16(this, offset, true, noAssert);
-};
-
-function readUInt32(buffer, offset, isBigEndian, noAssert) {
- var val = 0;
-
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- if (offset >= buffer.length) return 0;
-
- if (isBigEndian) {
- if (offset + 1 < buffer.length)
- val = buffer.parent[buffer.offset + offset + 1] << 16;
- if (offset + 2 < buffer.length)
- val |= buffer.parent[buffer.offset + offset + 2] << 8;
- if (offset + 3 < buffer.length)
- val |= buffer.parent[buffer.offset + offset + 3];
- val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);
- } else {
- if (offset + 2 < buffer.length)
- val = buffer.parent[buffer.offset + offset + 2] << 16;
- if (offset + 1 < buffer.length)
- val |= buffer.parent[buffer.offset + offset + 1] << 8;
- val |= buffer.parent[buffer.offset + offset];
- if (offset + 3 < buffer.length)
- val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
- }
-
- return val;
-}
-
-Buffer.prototype.readUInt32LE = function(offset, noAssert) {
- return readUInt32(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readUInt32BE = function(offset, noAssert) {
- return readUInt32(this, offset, true, noAssert);
-};
-
-
-/*
- * Signed integer types, yay team! A reminder on how two's complement actually
- * works. The first bit is the signed bit, i.e. tells us whether or not the
- * number should be positive or negative. If the two's complement value is
- * positive, then we're done, as it's equivalent to the unsigned representation.
- *
- * Now if the number is positive, you're pretty much done, you can just leverage
- * the unsigned translations and return those. Unfortunately, negative numbers
- * aren't quite that straightforward.
- *
- * At first glance, one might be inclined to use the traditional formula to
- * translate binary numbers between the positive and negative values in two's
- * complement. (Though it doesn't quite work for the most negative value)
- * Mainly:
- * - invert all the bits
- * - add one to the result
- *
- * Of course, this doesn't quite work in Javascript. Take for example the value
- * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
- * course, Javascript will do the following:
- *
- * > ~0xff80
- * -65409
- *
- * Whoh there, Javascript, that's not quite right. But wait, according to
- * Javascript that's perfectly correct. When Javascript ends up seeing the
- * constant 0xff80, it has no notion that it is actually a signed number. It
- * assumes that we've input the unsigned value 0xff80. Thus, when it does the
- * binary negation, it casts it into a signed value, (positive 0xff80). Then
- * when you perform binary negation on that, it turns it into a negative number.
- *
- * Instead, we're going to have to use the following general formula, that works
- * in a rather Javascript friendly way. I'm glad we don't support this kind of
- * weird numbering scheme in the kernel.
- *
- * (BIT-MAX - (unsigned)val + 1) * -1
- *
- * The astute observer, may think that this doesn't make sense for 8-bit numbers
- * (really it isn't necessary for them). However, when you get 16-bit numbers,
- * you do. Let's go back to our prior example and see how this will look:
- *
- * (0xffff - 0xff80 + 1) * -1
- * (0x007f + 1) * -1
- * (0x0080) * -1
- */
-Buffer.prototype.readInt8 = function(offset, noAssert) {
- var buffer = this;
- var neg;
-
- if (!noAssert) {
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- if (offset >= buffer.length) return;
-
- neg = buffer.parent[buffer.offset + offset] & 0x80;
- if (!neg) {
- return (buffer.parent[buffer.offset + offset]);
- }
-
- return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);
-};
-
-function readInt16(buffer, offset, isBigEndian, noAssert) {
- var neg, val;
-
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 1 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- val = readUInt16(buffer, offset, isBigEndian, noAssert);
- neg = val & 0x8000;
- if (!neg) {
- return val;
- }
-
- return (0xffff - val + 1) * -1;
-}
-
-Buffer.prototype.readInt16LE = function(offset, noAssert) {
- return readInt16(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readInt16BE = function(offset, noAssert) {
- return readInt16(this, offset, true, noAssert);
-};
-
-function readInt32(buffer, offset, isBigEndian, noAssert) {
- var neg, val;
-
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- val = readUInt32(buffer, offset, isBigEndian, noAssert);
- neg = val & 0x80000000;
- if (!neg) {
- return (val);
- }
-
- return (0xffffffff - val + 1) * -1;
-}
-
-Buffer.prototype.readInt32LE = function(offset, noAssert) {
- return readInt32(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readInt32BE = function(offset, noAssert) {
- return readInt32(this, offset, true, noAssert);
-};
-
-function readFloat(buffer, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
- 23, 4);
-}
-
-Buffer.prototype.readFloatLE = function(offset, noAssert) {
- return readFloat(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readFloatBE = function(offset, noAssert) {
- return readFloat(this, offset, true, noAssert);
-};
-
-function readDouble(buffer, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset + 7 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
- 52, 8);
-}
-
-Buffer.prototype.readDoubleLE = function(offset, noAssert) {
- return readDouble(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readDoubleBE = function(offset, noAssert) {
- return readDouble(this, offset, true, noAssert);
-};
-
-
-/*
- * We have to make sure that the value is a valid integer. This means that it is
- * non-negative. It has no fractional component and that it does not exceed the
- * maximum allowed value.
- *
- * value The number to check for validity
- *
- * max The maximum value
- */
-function verifuint(value, max) {
- assert.ok(typeof (value) == 'number',
- 'cannot write a non-number as a number');
-
- assert.ok(value >= 0,
- 'specified a negative value for writing an unsigned value');
-
- assert.ok(value <= max, 'value is larger than maximum value for type');
-
- assert.ok(Math.floor(value) === value, 'value has a fractional component');
-}
-
-Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
- var buffer = this;
-
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset < buffer.length,
- 'trying to write beyond buffer length');
-
- verifuint(value, 0xff);
- }
-
- if (offset < buffer.length) {
- buffer.parent[buffer.offset + offset] = value;
- }
-};
-
-function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 1 < buffer.length,
- 'trying to write beyond buffer length');
-
- verifuint(value, 0xffff);
- }
-
- for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
- buffer.parent[buffer.offset + offset + i] =
- (value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
- (isBigEndian ? 1 - i : i) * 8;
- }
-
-}
-
-Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
- writeUInt16(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
- writeUInt16(this, value, offset, true, noAssert);
-};
-
-function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'trying to write beyond buffer length');
-
- verifuint(value, 0xffffffff);
- }
-
- for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
- buffer.parent[buffer.offset + offset + i] =
- (value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
- }
-}
-
-Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
- writeUInt32(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
- writeUInt32(this, value, offset, true, noAssert);
-};
-
-
-/*
- * We now move onto our friends in the signed number category. Unlike unsigned
- * numbers, we're going to have to worry a bit more about how we put values into
- * arrays. Since we are only worrying about signed 32-bit values, we're in
- * slightly better shape. Unfortunately, we really can't do our favorite binary
- * & in this system. It really seems to do the wrong thing. For example:
- *
- * > -32 & 0xff
- * 224
- *
- * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
- * this aren't treated as a signed number. Ultimately a bad thing.
- *
- * What we're going to want to do is basically create the unsigned equivalent of
- * our representation and pass that off to the wuint* functions. To do that
- * we're going to do the following:
- *
- * - if the value is positive
- * we can pass it directly off to the equivalent wuint
- * - if the value is negative
- * we do the following computation:
- * mb + val + 1, where
- * mb is the maximum unsigned value in that byte size
- * val is the Javascript negative integer
- *
- *
- * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
- * you do out the computations:
- *
- * 0xffff - 128 + 1
- * 0xffff - 127
- * 0xff80
- *
- * You can then encode this value as the signed version. This is really rather
- * hacky, but it should work and get the job done which is our goal here.
- */
-
-/*
- * A series of checks to make sure we actually have a signed 32-bit number
- */
-function verifsint(value, max, min) {
- assert.ok(typeof (value) == 'number',
- 'cannot write a non-number as a number');
-
- assert.ok(value <= max, 'value larger than maximum allowed value');
-
- assert.ok(value >= min, 'value smaller than minimum allowed value');
-
- assert.ok(Math.floor(value) === value, 'value has a fractional component');
-}
-
-function verifIEEE754(value, max, min) {
- assert.ok(typeof (value) == 'number',
- 'cannot write a non-number as a number');
-
- assert.ok(value <= max, 'value larger than maximum allowed value');
-
- assert.ok(value >= min, 'value smaller than minimum allowed value');
-}
-
-Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
- var buffer = this;
-
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifsint(value, 0x7f, -0x80);
- }
-
- if (value >= 0) {
- buffer.writeUInt8(value, offset, noAssert);
- } else {
- buffer.writeUInt8(0xff + value + 1, offset, noAssert);
- }
-};
-
-function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 1 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifsint(value, 0x7fff, -0x8000);
- }
-
- if (value >= 0) {
- writeUInt16(buffer, value, offset, isBigEndian, noAssert);
- } else {
- writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
- }
-}
-
-Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
- writeInt16(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
- writeInt16(this, value, offset, true, noAssert);
-};
-
-function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifsint(value, 0x7fffffff, -0x80000000);
- }
-
- if (value >= 0) {
- writeUInt32(buffer, value, offset, isBigEndian, noAssert);
- } else {
- writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
- }
-}
-
-Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
- writeInt32(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
- writeInt32(this, value, offset, true, noAssert);
-};
-
-function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
- }
-
- require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
- 23, 4);
-}
-
-Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
- writeFloat(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
- writeFloat(this, value, offset, true, noAssert);
-};
-
-function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 7 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
- }
-
- require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
- 52, 8);
-}
-
-Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
- writeDouble(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
- writeDouble(this, value, offset, true, noAssert);
-};
-
-SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;
-SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;
-SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;
-SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;
-SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;
-SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;
-SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;
-SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;
-SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;
-SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;
-SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;
-SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;
-SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;
-SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;
-SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;
-SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;
-SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;
-SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;
-SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;
-SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;
-SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;
-SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;
-SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;
-SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;
-SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;
-SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;
-SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;
-SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;
-
-})()
-},{"assert":9,"./buffer_ieee754":14,"base64-js":15}],15:[function(require,module,exports){
-(function (exports) {
- 'use strict';
-
- var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-
- function b64ToByteArray(b64) {
- var i, j, l, tmp, placeHolders, arr;
-
- if (b64.length % 4 > 0) {
- throw 'Invalid string. Length must be a multiple of 4';
- }
-
- // the number of equal signs (place holders)
- // if there are two placeholders, than the two characters before it
- // represent one byte
- // if there is only one, then the three characters before it represent 2 bytes
- // this is just a cheap hack to not do indexOf twice
- placeHolders = b64.indexOf('=');
- placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
-
- // base64 is 4/3 + up to two characters of the original data
- arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
-
- // if there are placeholders, only get up to the last complete 4 chars
- l = placeHolders > 0 ? b64.length - 4 : b64.length;
-
- for (i = 0, j = 0; i < l; i += 4, j += 3) {
- tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
- arr.push((tmp & 0xFF0000) >> 16);
- arr.push((tmp & 0xFF00) >> 8);
- arr.push(tmp & 0xFF);
- }
-
- if (placeHolders === 2) {
- tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
- arr.push(tmp & 0xFF);
- } else if (placeHolders === 1) {
- tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
- arr.push((tmp >> 8) & 0xFF);
- arr.push(tmp & 0xFF);
- }
-
- return arr;
- }
-
- function uint8ToBase64(uint8) {
- var i,
- extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
- output = "",
- temp, length;
-
- function tripletToBase64 (num) {
- return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
- };
-
- // go through the array every three bytes, we'll deal with trailing stuff later
- for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
- temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
- output += tripletToBase64(temp);
- }
-
- // pad the end with zeros, but make sure to not forget the extra bytes
- switch (extraBytes) {
- case 1:
- temp = uint8[uint8.length - 1];
- output += lookup[temp >> 2];
- output += lookup[(temp << 4) & 0x3F];
- output += '==';
- break;
- case 2:
- temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
- output += lookup[temp >> 10];
- output += lookup[(temp >> 4) & 0x3F];
- output += lookup[(temp << 2) & 0x3F];
- output += '=';
- break;
- }
-
- return output;
- }
-
- module.exports.toByteArray = b64ToByteArray;
- module.exports.fromByteArray = uint8ToBase64;
-}());
-
-},{}]},{},["E/GbHF"])
-;
-JSHINT = require('jshint').JSHINT;
-}());
diff --git a/dom/system/gonk/tests/marionette/ril_jshint/jshintrc b/dom/system/gonk/tests/marionette/ril_jshint/jshintrc
deleted file mode 100644
index 437fe1a6f..000000000
--- a/dom/system/gonk/tests/marionette/ril_jshint/jshintrc
+++ /dev/null
@@ -1,118 +0,0 @@
-{
- // JSHint Default Configuration File (as on JSHint website)
- // See http://jshint.com/docs/ for more details
-
- // Modify for RIL usage.
-
- "maxerr" : 10000, // {int} Maximum error before stopping
-
- // Enforcing
- "bitwise" : false, // true: Prohibit bitwise operators (&, |, ^, etc.)
- "camelcase" : false, // true: Identifiers must be in camelCase
- "curly" : false, // true: Require {} for every new block or scope
- "eqeqeq" : false, // true: Require triple equals (===) for comparison
- "forin" : false, // true: Require filtering for..in loops with obj.hasOwnProperty()
- "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
- //"indent" : 2, // {int} Number of spaces to use for indentation
- "latedef" : false, // true: Require variables/functions to be defined before being used
- "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
- "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
- "noempty" : false, // true: Prohibit use of empty blocks
- "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
- "plusplus" : false, // true: Prohibit use of `++` & `--`
- "quotmark" : false, // Quotation mark consistency:
- // false : do nothing (default)
- // true : ensure whatever is used is consistent
- // "single" : require single quotes
- // "double" : require double quotes
- "undef" : false, // true: Require all non-global variables to be declared (prevents global leaks)
- "unused" : false, // true: Require all defined variables be used
- "strict" : false, // true: Requires all functions run in ES5 Strict Mode
- "trailing" : false, // true: Prohibit trailing whitespaces
- "maxparams" : false, // {int} Max number of formal params allowed per function
- "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
- "maxstatements" : false, // {int} Max number statements per function
- "maxcomplexity" : false, // {int} Max cyclomatic complexity per function
- "maxlen" : false, // {int} Max number of characters per line
-
- // Relaxing
- "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
- "boss" : false, // true: Tolerate assignments where comparisons would be expected
- "debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
- "eqnull" : true, // true: Tolerate use of `== null`
- "es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
- "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
- "moz" : true, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
- // (ex: `for each`, multiple try/catch, function expression…)
- "evil" : false, // true: Tolerate use of `eval` and `new Function()`
- "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
- "funcscope" : false, // true: Tolerate defining variables inside control statements"
- "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict')
- "iterator" : false, // true: Tolerate using the `__iterator__` property
- "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
- "laxbreak" : true, // true: Tolerate possibly unsafe line breakings
- "laxcomma" : false, // true: Tolerate comma-first style coding
- "loopfunc" : false, // true: Tolerate functions being defined in loops
- "multistr" : false, // true: Tolerate multi-line strings
- "proto" : true, // true: Tolerate using the `__proto__` property
- "scripturl" : false, // true: Tolerate script-targeted URLs
- "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
- "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
- "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
- "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
- "validthis" : true, // true: Tolerate using this in a non-constructor function
-
- // Environments
- "browser" : false, // Web Browser (window, document, etc)
- "couch" : false, // CouchDB
- "devel" : true, // Development/debugging (alert, confirm, etc)
- "dojo" : false, // Dojo Toolkit
- "jquery" : false, // jQuery
- "mootools" : false, // MooTools
- "node" : false, // Node.js
- "nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
- "prototypejs" : false, // Prototype and Scriptaculous
- "rhino" : false, // Rhino
- "worker" : true, // Web Workers
- "wsh" : false, // Windows Scripting Host
- "yui" : false, // Yahoo User Interface
-
- // Legacy
- "nomen" : false, // true: Prohibit dangling `_` in variables
- "onevar" : false, // true: Allow only one `var` statement per function
- "passfail" : false, // true: Stop on first error
- "white" : false, // true: Check against strict whitespace and indentation rules
-
- // Custom Globals
- "predef" : [ ], // additional predefined global variables
-
- "globals": {
- "ChromeWorker": false,
- "Components": false,
- "DOMRequestIpcHelper": false,
- "ObjectWrapper": false,
- "PhoneNumberUtils": false,
- "RILNetworkInterface": false,
- "Services": false,
- "Uint8Array": false,
- "WAP": false,
- "XPCOMUtils": false,
- "cpmm": false,
- "dump": false,
- "gAudioManager": false,
- "gMessageManager": false,
- "gMobileMessageDatabaseService": false,
- "gMobileMessageService": false,
- "gNetworkManager": false,
- "gPowerManagerService": false,
- "gSettingsService": false,
- "gSmsService": false,
- "gSystemMessenger": false,
- "gSystemWorkerManager": false,
- "gTimeService": false,
- "gUUIDGenerator": false,
- "ppmm": true,
-
- "__end_guardian_for_easy_sorting__": false
- }
-}
diff --git a/dom/system/gonk/tests/marionette/test_all_network_info.js b/dom/system/gonk/tests/marionette/test_all_network_info.js
deleted file mode 100644
index 5225ab6d6..000000000
--- a/dom/system/gonk/tests/marionette/test_all_network_info.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-var networkManager =
- Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
-ok(networkManager,
- "networkManager.constructor is " + networkManager.constructor);
-
-var wifiManager = window.navigator.mozWifiManager;
-ok(wifiManager, "wifiManager.constructor is " + wifiManager.constructor);
-
-function setEmulatorAPN() {
- let apn = [
- [{"carrier":"T-Mobile US",
- "apn":"epc.tmobile.com",
- "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types":["default","supl","mms","ims","dun", "fota"]}]
- ];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-function ensureWifiEnabled(aEnabled) {
- if (wifiManager.enabled === aEnabled) {
- log('Already ' + (aEnabled ? 'enabled' : 'disabled'));
- return Promise.resolve();
- }
- return requestWifiEnabled(aEnabled);
-}
-
-function requestWifiEnabled(aEnabled) {
- let promises = [];
-
- promises.push(waitForTargetEvent(wifiManager, aEnabled ? 'enabled' : 'disabled',
- function() {
- return wifiManager.enabled === aEnabled ? true : false;
- }));
- promises.push(setSettings(SETTINGS_KEY_WIFI_ENABLED, aEnabled));
-
- return Promise.all(promises);
-}
-
-// Test initial State
-function verifyInitialState() {
- log("= verifyInitialState =");
-
- // Data and wifi should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- })
- .then(() => ensureWifiEnabled(false));
-}
-
-function testAllNetworkInfo(aAnyConnected) {
- log("= testAllNetworkInfo = " + aAnyConnected);
-
- let allNetworkInfo = networkManager.allNetworkInfo;
- ok(allNetworkInfo, "NetworkManager.allNetworkInfo");
-
- let count = Object.keys(allNetworkInfo).length;
- ok(count > 0, "NetworkManager.allNetworkInfo count");
-
- let connected = false;
- for (let networkId in allNetworkInfo) {
- if (allNetworkInfo.hasOwnProperty(networkId)) {
- let networkInfo = allNetworkInfo[networkId];
- if (networkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- connected = true;
- break;
- }
- }
- }
-
- is(aAnyConnected, connected, "NetworkManager.allNetworkInfo any connected");
-}
-
-// Start test
-startTestBase(function() {
-
- let origApnSettings, origWifiEnabled;
- return Promise.resolve()
- .then(() => {
- origWifiEnabled = wifiManager.enabled;
- })
- .then(() => verifyInitialState())
- .then(() => getSettings(SETTINGS_KEY_DATA_APN_SETTINGS))
- .then(value => {
- origApnSettings = value;
- })
- .then(() => setEmulatorAPN())
- .then(() => setDataEnabledAndWait(true))
- .then(() => testAllNetworkInfo(true))
- .then(() => setDataEnabledAndWait(false))
- .then(() => testAllNetworkInfo(false))
- // Restore original apn settings and wifi state.
- .then(() => {
- if (origApnSettings) {
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, origApnSettings);
- }
- })
- .then(() => ensureWifiEnabled(origWifiEnabled));
-});
diff --git a/dom/system/gonk/tests/marionette/test_data_connection.js b/dom/system/gonk/tests/marionette/test_data_connection.js
deleted file mode 100644
index 5a53b1e5f..000000000
--- a/dom/system/gonk/tests/marionette/test_data_connection.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-function setEmulatorAPN() {
- let apn = [
- [{"carrier":"T-Mobile US",
- "apn":"epc.tmobile.com",
- "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types":["default","supl","mms","ims","dun", "fota"]}]
- ];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-// Test initial State
-function testInitialState() {
- log("= testInitialState =");
-
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- });
-}
-
-// Test default data Connection
-function testDefaultDataConnection() {
- log("= testDefaultDataConnection =");
-
- // Enable default data
- return setDataEnabledAndWait(true)
- // Disable default data
- .then(() => setDataEnabledAndWait(false));
-}
-
-// Test non default data connection
-function testNonDefaultDataConnection() {
- log("= testNonDefaultDataConnection =");
-
- function doTestNonDefaultDataConnection(type) {
- log("doTestNonDefaultDataConnection: " + type);
-
- return setupDataCallAndWait(type)
- .then(() => deactivateDataCallAndWait(type));
- }
-
- let currentApn;
- return getSettings(SETTINGS_KEY_DATA_APN_SETTINGS)
- .then(value => {
- currentApn = value;
- })
- .then(setEmulatorAPN)
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_MMS))
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_SUPL))
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_IMS))
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_DUN))
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_FOTA))
- // Restore APN settings
- .then(() => setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, currentApn));
-}
-
-// Start test
-startTestBase(function() {
- return testInitialState()
- .then(() => testDefaultDataConnection())
- .then(() => testNonDefaultDataConnection());
-});
diff --git a/dom/system/gonk/tests/marionette/test_data_connection_proxy.js b/dom/system/gonk/tests/marionette/test_data_connection_proxy.js
deleted file mode 100644
index a99187538..000000000
--- a/dom/system/gonk/tests/marionette/test_data_connection_proxy.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-const HTTP_PROXY = "10.0.2.200";
-const HTTP_PROXY_PORT = "8080";
-const MANUAL_PROXY_CONFIGURATION = 1;
-
-// Test initial State
-function verifyInitialState() {
- log("= verifyInitialState =");
-
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- });
-}
-
-function setTestApn() {
- let apn = [
- [ {"carrier": "T-Mobile US",
- "apn": "epc.tmobile.com",
- "proxy": HTTP_PROXY,
- "port": HTTP_PROXY_PORT,
- "mmsc": "http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types": ["default","supl","mms"]} ]
- ];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-function waitForHttpProxyVerified(aShouldBeSet) {
- let TIME_OUT_VALUE = 20000;
-
- return new Promise(function(aResolve, aReject) {
- try {
- waitFor(aResolve, () => {
- let proxyType = SpecialPowers.getIntPref("network.proxy.type");
- let httpProxy = SpecialPowers.getCharPref("network.proxy.http");
- let sslProxy = SpecialPowers.getCharPref("network.proxy.ssl");
- let httpProxyPort = SpecialPowers.getIntPref("network.proxy.http_port");
- let sslProxyPort = SpecialPowers.getIntPref("network.proxy.ssl_port");
-
- if ((aShouldBeSet &&
- proxyType == MANUAL_PROXY_CONFIGURATION &&
- httpProxy == HTTP_PROXY &&
- sslProxy == HTTP_PROXY &&
- httpProxyPort == HTTP_PROXY_PORT &&
- sslProxyPort == HTTP_PROXY_PORT) ||
- (!aShouldBeSet && proxyType != MANUAL_PROXY_CONFIGURATION &&
- !httpProxy && !sslProxy && !httpProxyPort && !sslProxyPort)) {
- return true;
- }
-
- return false;
- }, TIME_OUT_VALUE);
- } catch(aError) {
- // Timed out.
- aReject(aError);
- }
- });
-}
-
-function testDefaultDataHttpProxy() {
- log("= testDefaultDataHttpProxy =");
-
- return setDataEnabledAndWait(true)
- .then(() => waitForHttpProxyVerified(true))
- .then(() => setDataEnabledAndWait(false))
- .then(() => waitForHttpProxyVerified(false));
-}
-
-function testNonDefaultDataHttpProxy(aType) {
- log("= testNonDefaultDataHttpProxy - " + aType + " =");
-
- return setupDataCallAndWait(aType)
- // Http proxy should not be set for non-default data connections.
- .then(() => waitForHttpProxyVerified(false))
- .then(() => deactivateDataCallAndWait(aType));
-}
-
-// Start test
-startTestBase(function() {
- let origApnSettings;
- return verifyInitialState()
- .then(() => getSettings(SETTINGS_KEY_DATA_APN_SETTINGS))
- .then(value => {
- origApnSettings = value;
- })
- .then(() => setTestApn())
- .then(() => testDefaultDataHttpProxy())
- .then(() => testNonDefaultDataHttpProxy(NETWORK_TYPE_MOBILE_MMS))
- .then(() => testNonDefaultDataHttpProxy(NETWORK_TYPE_MOBILE_SUPL))
- // Restore APN settings
- .then(() => setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, origApnSettings));
-});
diff --git a/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js b/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js
deleted file mode 100644
index e178b8b65..000000000
--- a/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_CONTEXT = "chrome";
-
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-const NS_RIL_CONTRACTID = "@mozilla.org/ril;1";
-
-const PROP_RO_MOZ_RIL_NUMCLIENTS = "ro.moz.ril.numclients";
-
-const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces";
-
-ok(libcutils, "libcutils is available");
-
-var propNum = (function() {
- try {
- let numString = libcutils.property_get(PROP_RO_MOZ_RIL_NUMCLIENTS, "1");
- let num = parseInt(numString, 10);
- if (num >= 0) {
- return num;
- }
- } catch (e) {}
-})();
-
-log("Retrieved '" + PROP_RO_MOZ_RIL_NUMCLIENTS + "' = " + propNum);
-ok(propNum, PROP_RO_MOZ_RIL_NUMCLIENTS);
-
-var prefNum = Services.prefs.getIntPref(PREF_RIL_NUM_RADIO_INTERFACES);
-log("Retrieved '" + PREF_RIL_NUM_RADIO_INTERFACES + "' = " + prefNum);
-
-var ril = Cc[NS_RIL_CONTRACTID].getService(Ci.nsIRadioInterfaceLayer);
-ok(ril, "ril.constructor is " + ril.constructor);
-
-var ifaceNum = ril.numRadioInterfaces;
-log("Retrieved 'nsIRadioInterfaceLayer.numRadioInterfaces' = " + ifaceNum);
-
-is(propNum, prefNum);
-is(propNum, ifaceNum);
-
-finish();
diff --git a/dom/system/gonk/tests/marionette/test_fakevolume.js b/dom/system/gonk/tests/marionette/test_fakevolume.js
deleted file mode 100644
index 173f9ac11..000000000
--- a/dom/system/gonk/tests/marionette/test_fakevolume.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 10000;
-
-var Cc = SpecialPowers.Cc;
-var Ci = SpecialPowers.Ci;
-
-var volumeService = Cc["@mozilla.org/telephony/volume-service;1"].getService(Ci.nsIVolumeService);
-ok(volumeService, "Should have volume service");
-
-var volName = "fake";
-var mountPoint = "/data/fake/storage";
-volumeService.createFakeVolume(volName, mountPoint);
-
-var vol = volumeService.getVolumeByName(volName);
-ok(vol, "volume shouldn't be null");
-
-is(volName, vol.name, "name");
-is(mountPoint, vol.mountPoint, "moutnPoint");
-is(Ci.nsIVolume.STATE_MOUNTED, vol.state, "state");
-
-ok(vol.mountGeneration > 0, "mount generation should not be zero");
-
-finish();
diff --git a/dom/system/gonk/tests/marionette/test_geolocation.js b/dom/system/gonk/tests/marionette/test_geolocation.js
deleted file mode 100644
index 201c8b3e3..000000000
--- a/dom/system/gonk/tests/marionette/test_geolocation.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 10000;
-
-var geolocation = window.navigator.geolocation;
-ok(geolocation);
-
-var sample = [];
-var result = [];
-var wpid;
-
-/**
- * Grant special power to get the geolocation
- */
-SpecialPowers.addPermission("geolocation", true, document);
-
-/**
- * Disable wifi geolocation provider
- */
-wifiUri = SpecialPowers.getCharPref("geo.wifi.uri");
-SpecialPowers.setCharPref("geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?action=stop-responding");
-
-/**
- * Helper that compares the geolocation against the web API.
- */
-function verifyLocation() {
-
- log("Sample:" + sample.join(','));
- log("Result:" + result.join(','));
-
- for (i in sample) {
- is(sample.pop(), result.pop());
- }
-
- window.setTimeout(cleanup, 0);
-}
-
-/**
- * Test story begins here.
- */
-function setup() {
- log("Providing initial setup: set geographic position watcher.");
-
-
- wpid = geolocation.watchPosition(function(position) {
- log("Position changes: (" + position.coords.latitude + "/" + position.coords.longitude + ")");
- result.push(""+position.coords.latitude + "/" + position.coords.longitude);
- });
-
- lat = 0;
- lon = 0;
-
- cmd = "geo fix " + lon + " " + lat;
- sample.push(lat+"/"+lon);
-
- runEmulatorCmd(cmd, function(result) {
- window.setTimeout(movePosition_1, 0);
- });
-}
-
-function movePosition_1() {
- log("Geolocation changes. Move to Position 1.");
-
- lat = 25;
- lon = 121.56499833333334;
-
- cmd = "geo fix " + lon + " " + lat;
- sample.push(lat+"/"+lon);
-
- runEmulatorCmd(cmd, function(result) {
- window.setTimeout(movePosition_2, 0);
- });
-}
-
-function movePosition_2() {
- log("Geolocation changes to a negative longitude. Move to Position 2.");
-
- lat = 37.393;
- lon = -122.08199833333335;
-
- cmd = "geo fix " + lon + " " + lat;
- sample.push(lat+"/"+lon);
-
- runEmulatorCmd(cmd, function(result) {
- window.setTimeout(movePosition_3, 0);
- });
-}
-
-function movePosition_3() {
- log("Geolocation changes with WatchPosition. Move to Position 3.");
-
- lat = -22;
- lon = -43;
-
- cmd = "geo fix " + lon + " " + lat;
- sample.push(lat+"/"+lon);
-
- geolocation.getCurrentPosition(function(position) {
- log("getCurrentPosition: Expected location: ("+lat+"/"+lon+"); Current location: (" + position.coords.latitude + "/" + position.coords.longitude + ")");
- is(lat, position.coords.latitude);
- is(lon, position.coords.longitude);
- });
-
- runEmulatorCmd(cmd, function(result) {
- window.setTimeout(verifyLocation, 0);
- });
-}
-
-function cleanup() {
- geolocation.clearWatch(wpid);
- SpecialPowers.removePermission("geolocation", document);
- SpecialPowers.setCharPref("geo.wifi.uri", wifiUri);
- finish();
-}
-
-setup();
diff --git a/dom/system/gonk/tests/marionette/test_multiple_data_connection.js b/dom/system/gonk/tests/marionette/test_multiple_data_connection.js
deleted file mode 100644
index 24abd4451..000000000
--- a/dom/system/gonk/tests/marionette/test_multiple_data_connection.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-// Must sync with hardware/ril/reference-ril/reference-ril.c
-const MAX_DATA_CONTEXTS = 4;
-
-function setEmulatorAPN() {
- // Use different apn for each network type.
- let apn = [[ { "carrier":"T-Mobile US",
- "apn":"epc1.tmobile.com",
- "types":["default"] },
- { "carrier":"T-Mobile US",
- "apn":"epc2.tmobile.com",
- "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types":["mms"] },
- { "carrier":"T-Mobile US",
- "apn":"epc3.tmobile.com",
- "types":["supl"] },
- { "carrier":"T-Mobile US",
- "apn":"epc4.tmobile.com",
- "types":["ims"] },
- { "carrier":"T-Mobile US",
- "apn":"epc5.tmobile.com",
- "types":["dun"] },
- { "carrier":"T-Mobile US",
- "apn":"epc6.tmobile.com",
- "types":["fota"] }]];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-// Test initial State
-function testInitialState() {
- log("= testInitialState =");
-
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- });
-}
-
-function testSetupConcurrentDataCalls() {
- log("= testSetupConcurrentDataCalls =");
-
- let promise = Promise.resolve();
- // Skip default mobile type.
- for (let i = 1; i < MAX_DATA_CONTEXTS; i++) {
- let type = networkTypes[i];
- promise = promise.then(() => setupDataCallAndWait(type));
- }
- return promise;
-}
-
-function testDeactivateConcurrentDataCalls() {
- log("= testDeactivateConcurrentDataCalls =");
-
- let promise = Promise.resolve();
- // Skip default mobile type.
- for (let i = 1; i < MAX_DATA_CONTEXTS; i++) {
- let type = networkTypes[i];
- promise = promise.then(() => deactivateDataCallAndWait(type));
- }
- return promise;
-}
-
-// Start test
-startTestBase(function() {
-
- let origApnSettings;
- return testInitialState()
- .then(() => getSettings(SETTINGS_KEY_DATA_APN_SETTINGS))
- .then(value => {
- origApnSettings = value;
- })
- .then(() => setEmulatorAPN())
- .then(() => setDataEnabledAndWait(true))
- .then(() => testSetupConcurrentDataCalls())
- .then(() => testDeactivateConcurrentDataCalls())
- .then(() => setDataEnabledAndWait(false))
- .then(() => {
- if (origApnSettings) {
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, origApnSettings);
- }
- });
-});
diff --git a/dom/system/gonk/tests/marionette/test_network_active_changed.js b/dom/system/gonk/tests/marionette/test_network_active_changed.js
deleted file mode 100644
index 5886f37ed..000000000
--- a/dom/system/gonk/tests/marionette/test_network_active_changed.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-var networkManager =
- Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
-ok(networkManager,
- "networkManager.constructor is " + networkManager.constructor);
-
-function testInitialState() {
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then((enabled) => {
- is(enabled, false, "data should be off by default");
- is(networkManager.activeNetworkInfo, null,
- "networkManager.activeNetworkInfo should be null by default");
- });
-}
-
-function testActiveNetworkChangedBySwitchingDataCall(aDataCallEnabled) {
- log("Test active network by switching dataCallEnabled to " + aDataCallEnabled);
-
- let promises = [];
- promises.push(waitForObserverEvent(TOPIC_NETWORK_ACTIVE_CHANGED));
- promises.push(setSettings(SETTINGS_KEY_DATA_ENABLED, aDataCallEnabled));
-
- return Promise.all(promises).then(function(results) {
- let subject = results[0];
-
- if (aDataCallEnabled) {
- ok(subject instanceof Ci.nsINetworkInfo,
- "subject should be an instance of nsINetworkInfo");
- ok(subject instanceof Ci.nsIRilNetworkInfo,
- "subject should be an instance of nsIRilNetworkInfo");
- is(subject.type, NETWORK_TYPE_MOBILE,
- "subject.type should be NETWORK_TYPE_MOBILE");
- }
-
- is(subject, networkManager.activeNetworkInfo,
- "subject should be equal with networkManager.activeNetworkInfo");
- });
-}
-
-// Start test
-startTestBase(function() {
- return testInitialState()
- // Test active network changed by enabling data call.
- .then(() => testActiveNetworkChangedBySwitchingDataCall(true))
- // Test active network changed by disabling data call.
- .then(() => testActiveNetworkChangedBySwitchingDataCall(false));
-});
diff --git a/dom/system/gonk/tests/marionette/test_network_interface_list_service.js b/dom/system/gonk/tests/marionette/test_network_interface_list_service.js
deleted file mode 100644
index 549940fa5..000000000
--- a/dom/system/gonk/tests/marionette/test_network_interface_list_service.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-function getNetworkInfo(aType) {
- let networkListService =
- Cc["@mozilla.org/network/interface-list-service;1"].
- getService(Ci.nsINetworkInterfaceListService);
- // Get all available interfaces
- let networkList = networkListService.getDataInterfaceList(0);
-
- // Try to get nsINetworkInterface for aType.
- let numberOfInterface = networkList.getNumberOfInterface();
- for (let i = 0; i < numberOfInterface; i++) {
- let info = networkList.getInterfaceInfo(i);
- if (info.type === aType) {
- return info;
- }
- }
-
- return null;
-}
-
-// Test getDataInterfaceList by enabling/disabling mobile data.
-function testGetDataInterfaceList(aMobileDataEnabled) {
- log("Test getDataInterfaceList with mobile data " +
- aMobileDataEnabled ? "enabled" : "disabled");
-
- return setDataEnabledAndWait(aMobileDataEnabled)
- .then(() => getNetworkInfo(NETWORK_TYPE_MOBILE))
- .then((networkInfo) => {
- if (!networkInfo) {
- ok(false, "Should get an valid nsINetworkInfo for mobile");
- return;
- }
-
- ok(networkInfo instanceof Ci.nsINetworkInfo,
- "networkInfo should be an instance of nsINetworkInfo");
-
- let ipAddresses = {};
- let prefixs = {};
- let numOfGateways = {};
- let numOfDnses = {};
- let numOfIpAddresses = networkInfo.getAddresses(ipAddresses, prefixs);
- let gateways = networkInfo.getGateways(numOfGateways);
- let dnses = networkInfo.getDnses(numOfDnses);
-
- if (aMobileDataEnabled) {
- // Mobile data is enabled.
- is(networkInfo.state, NETWORK_STATE_CONNECTED, "check state");
- ok(numOfIpAddresses > 0, "check number of ipAddresses");
- ok(ipAddresses.value.length > 0, "check ipAddresses.length");
- ok(prefixs.value.length > 0, "check prefixs.length");
- ok(numOfGateways.value > 0, "check number of gateways");
- ok(prefixs.value.length > 0, "check prefixs.length");
- ok(gateways.length > 0, "check gateways.length");
- ok(numOfDnses.value > 0, "check number of dnses");
- ok(dnses.length > 0, "check dnses.length");
- } else {
- // Mobile data is disabled.
- is(networkInfo.state, NETWORK_STATE_DISCONNECTED, "check state");
- is(numOfIpAddresses, 0, "check number of ipAddresses");
- is(ipAddresses.value.length, 0, "check ipAddresses.length");
- is(prefixs.value.length, 0, "check prefixs.length");
- is(numOfGateways.value, 0, "check number of gateways");
- is(prefixs.value.length, 0, "check prefixs.length");
- is(gateways.length, 0, "check gateways.length");
- is(numOfDnses.value, 0, "check number of dnses");
- is(dnses.length, 0, "check dnses.length");
- }
- });
-}
-
-// Start test
-startTestBase(function() {
- return Promise.resolve()
- // Test initial State
- .then(() => {
- log("Test initial state");
-
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Mobile data must be off");
- });
- })
-
- // Test getDataInterfaceList with mobile data enabled.
- .then(() => testGetDataInterfaceList(true))
-
- // Test getDataInterfaceList with mobile data disabled.
- .then(() => testGetDataInterfaceList(false));
-});
diff --git a/dom/system/gonk/tests/marionette/test_network_interface_mtu.js b/dom/system/gonk/tests/marionette/test_network_interface_mtu.js
deleted file mode 100644
index 679efe2ed..000000000
--- a/dom/system/gonk/tests/marionette/test_network_interface_mtu.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-const TEST_MTU1 = "1410";
-const TEST_MTU2 = "1440";
-
-function setEmulatorAPN() {
- let apn = [
- [ { "carrier":"T-Mobile US",
- "apn":"epc1.tmobile.com",
- "types":["default"],
- "mtu": TEST_MTU1 },
- { "carrier":"T-Mobile US",
- "apn":"epc2.tmobile.com",
- "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types":["supl","mms","ims","dun", "fota"],
- "mtu": TEST_MTU2 } ]
- ];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-function verifyInitialState() {
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- });
-}
-
-function verifyMtu(aInterfaceName, aMtu) {
- return runEmulatorShellCmdSafe(['ip', 'link', 'show', 'dev', aInterfaceName])
- .then(aLines => {
- // Sample output:
- //
- // 4: rmnet0: <BROADCAST,MULTICAST> mtu 1410 qdisc pfifo_fast state DOWN mode DEFAULT qlen 1000
- // link/ether 52:54:00:12:34:58 brd ff:ff:ff:ff:ff:ff
- //
- let mtu;
- aLines.some(function (aLine) {
- let tokens = aLine.trim().split(/\s+/);
- let mtuIndex = tokens.indexOf('mtu');
- if (mtuIndex < 0 || mtuIndex + 1 >= tokens.length) {
- return false;
- }
-
- mtu = tokens[mtuIndex + 1];
- return true;
- });
-
- is(mtu, aMtu, aInterfaceName + "'s mtu.");
- });
-}
-
-function testDefaultDataCallMtu() {
- log("= testDefaultDataCallMtu =");
-
- return setDataEnabledAndWait(true)
- .then(aNetworkInfo => verifyMtu(aNetworkInfo.name, TEST_MTU1))
- .then(() => setDataEnabledAndWait(false));
-}
-
-function testNonDefaultDataCallMtu() {
- log("= testNonDefaultDataCallMtu =");
-
- function doTestNonDefaultDataCallMtu(aType) {
- log("doTestNonDefaultDataCallMtu: " + aType);
-
- return setupDataCallAndWait(aType)
- .then(aNetworkInfo => verifyMtu(aNetworkInfo.name, TEST_MTU2))
- .then(() => deactivateDataCallAndWait(aType));
- }
-
- return doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_MMS)
- .then(() => doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_SUPL))
- .then(() => doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_IMS))
- .then(() => doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_DUN))
- .then(() => doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_FOTA));
-}
-
-// Start test
-startTestBase(function() {
- let origApnSettings;
- return verifyInitialState()
- .then(() => getSettings(SETTINGS_KEY_DATA_APN_SETTINGS))
- .then(value => {
- origApnSettings = value;
- })
- .then(() => setEmulatorAPN())
- .then(() => testDefaultDataCallMtu())
- .then(() => testNonDefaultDataCallMtu())
- .then(() => {
- if (origApnSettings) {
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, origApnSettings);
- }
- });
-});
diff --git a/dom/system/gonk/tests/marionette/test_ril_code_quality.py b/dom/system/gonk/tests/marionette/test_ril_code_quality.py
deleted file mode 100644
index d741d8a2e..000000000
--- a/dom/system/gonk/tests/marionette/test_ril_code_quality.py
+++ /dev/null
@@ -1,371 +0,0 @@
-"""
-The test performs the static code analysis check by JSHint.
-
-Target js files:
-- RadioInterfaceLayer.js
-- ril_worker.js
-- ril_consts.js
-
-If the js file contains the line of 'importScript()' (Ex: ril_worker.js), the
-test will perform a special merge step before excuting JSHint.
-
-Ex: Script A
---------------------------------
-importScripts('Script B')
-...
---------------------------------
-
-We merge these two scripts into one by the following way.
-
---------------------------------
-[Script B (ex: ril_consts.js)]
-(function(){ [Script A (ex: ril_worker.js)]
-})();
---------------------------------
-
-Script A (ril_worker.js) runs global strict mode.
-Script B (ril_consts.js) not.
-
-The above merge way ensures the correct scope of 'strict mode.'
-"""
-
-import bisect
-import inspect
-import os
-import os.path
-import re
-import unicodedata
-
-from marionette_harness import MarionetteTestCase
-
-
-class StringUtility:
-
- """A collection of some string utilities."""
-
- @staticmethod
- def find_match_lines(lines, pattern):
- """Return a list of lines that contains given pattern."""
- return [line for line in lines if pattern in line]
-
- @staticmethod
- def remove_non_ascii(data):
- """Remove non ascii characters in data and return it as new string."""
- if type(data).__name__ == 'unicode':
- data = unicodedata.normalize(
- 'NFKD', data).encode('ascii', 'ignore')
- return data
-
- @staticmethod
- def auto_close(lines):
- """Ensure every line ends with '\n'."""
- if lines and not lines[-1].endswith('\n'):
- lines[-1] += '\n'
- return lines
-
- @staticmethod
- def auto_wrap_strict_mode(lines):
- """Wrap by function scope if lines contain 'use strict'."""
- if StringUtility.find_match_lines(lines, 'use strict'):
- lines[0] = '(function(){' + lines[0]
- lines.append('})();\n')
- return lines
-
- @staticmethod
- def get_imported_list(lines):
- """Get a list of imported items."""
- return [item
- for line in StringUtility.find_match_lines(lines, 'importScripts')
- for item in StringUtility._get_imported_list_from_line(line)]
-
- @staticmethod
- def _get_imported_list_from_line(line):
- """Extract all items from 'importScripts(...)'.
-
- importScripts("ril_consts.js", "systemlibs.js")
- => ['ril_consts', 'systemlibs.js']
-
- """
- pattern = re.compile(r'\s*importScripts\((.*)\)')
- m = pattern.match(line)
- if not m:
- raise Exception('Parse importScripts error.')
- return [name.translate(None, '\' "') for name in m.group(1).split(',')]
-
-
-class ResourceUriFileReader:
-
- """Handle the process of reading the source code from system."""
-
- URI_PREFIX = 'resource://gre/'
- URI_PATH = {
- 'RadioInterfaceLayer.js': 'components/RadioInterfaceLayer.js',
- 'ril_worker.js': 'modules/ril_worker.js',
- 'ril_consts.js': 'modules/ril_consts.js',
- 'systemlibs.js': 'modules/systemlibs.js',
- 'worker_buf.js': 'modules/workers/worker_buf.js',
- }
-
- CODE_OPEN_CHANNEL_BY_URI = '''
- var Cc = Components.classes;
- var Ci = Components.interfaces;
- var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
- var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
- global.uri = '%(uri)s';
- global.channel = ios.newChannel2(global.uri,
- null,
- null,
- null, // aLoadingNode
- secMan.getSystemPrincipal(),
- null, // aTriggeringPrincipal
- Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
- Ci.nsIContentPolicy.TYPE_OTHER);
- '''
-
- CODE_GET_SPEC = '''
- return global.channel.URI.spec;
- '''
-
- CODE_READ_CONTENT = '''
- var Cc = Components.classes;
- var Ci = Components.interfaces;
-
- var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
- var inputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
-
- var jaruri = global.channel.URI.QueryInterface(Ci.nsIJARURI);
- var file = jaruri.JARFile.QueryInterface(Ci.nsIFileURL).file;
- var entry = jaruri.JAREntry;
- zipReader.open(file);
- inputStream.init(zipReader.getInputStream(entry));
- var content = inputStream.read(inputStream.available());
- inputStream.close();
- zipReader.close();
- return content;
- '''
-
- @classmethod
- def get_uri(cls, filename):
- """Convert filename to URI in system."""
- if filename.startswith(cls.URI_PREFIX):
- return filename
- else:
- return cls.URI_PREFIX + cls.URI_PATH[filename]
-
- def __init__(self, marionette):
- self.runjs = lambda x: marionette.execute_script(x,
- new_sandbox=False,
- sandbox='system')
-
- def read_file(self, filename):
- """Read file and return the contents as string."""
- content = self._read_uri(self.get_uri(filename))
- content = content.replace('"use strict";', '')
- return StringUtility.remove_non_ascii(content)
-
- def _read_uri(self, uri):
- """Read URI in system and return the contents as string."""
- # Open the uri as a channel.
- self.runjs(self.CODE_OPEN_CHANNEL_BY_URI % {'uri': uri})
-
- # Make sure spec is a jar uri, and not recursive.
- # Ex: 'jar:file:///system/b2g/omni.ja!/modules/ril_worker.js'
- #
- # For simplicity, we don't handle other special cases in this test.
- # If B2G build system changes in the future, such as put the jar in
- # another jar, the test case will fail.
- spec = self.runjs(self.CODE_GET_SPEC)
- if (not spec.startswith('jar:file://')) or (spec.count('jar:') != 1):
- raise Exception('URI resolve error')
-
- # Read the content from channel.
- content = self.runjs(self.CODE_READ_CONTENT)
- return content
-
-
-class JSHintEngine:
-
- """Invoke jshint script on system."""
-
- CODE_INIT_JSHINT = '''
- %(script)s;
- global.JSHINT = JSHINT;
- global.options = JSON.parse(%(config_string)s);
- global.globals = global.options.globals;
- delete global.options.globals;
- '''
-
- CODE_RUN_JSHINT = '''
- global.script = %(code)s;
- return global.JSHINT(global.script, global.options, global.globals);
- '''
-
- CODE_GET_JSHINT_ERROR = '''
- return global.JSHINT.errors;
- '''
-
- def __init__(self, marionette, script, config):
- # Remove single line comment in config.
- config = '\n'.join([line.partition('//')[0]
- for line in config.splitlines()])
-
- # Set global (JSHINT, options, global) in js environment.
- self.runjs = lambda x: marionette.execute_script(x,
- new_sandbox=False,
- sandbox='system')
- self.runjs(self.CODE_INIT_JSHINT %
- {'script': script, 'config_string': repr(config)})
-
- def run(self, code, filename=''):
- """Excute JShint check for the given code."""
- check_pass = self.runjs(self.CODE_RUN_JSHINT % {'code': repr(code)})
- errors = self.runjs(self.CODE_GET_JSHINT_ERROR)
- return check_pass, self._get_error_messages(errors, filename)
-
- def _get_error_messages(self, errors, filename=''):
- """
- Convert an error object to a list of readable string.
-
- [{"a": null, "c": null, "code": "W033", "d": null, "character": 6,
- "evidence": "var a", "raw": "Missing semicolon.",
- "reason": "Missing semicolon.", "b": null, "scope": "(main)", "line": 1,
- "id": "(error)"}]
- => line 1, col 6, Missing semicolon.
-
- """
- LINE, COL, REASON = u'line', u'character', u'reason'
- return ["%s: line %s, col %s, %s" %
- (filename, error[LINE], error[COL], error[REASON])
- for error in errors if error]
-
-
-class Linter:
-
- """Handle the linting related process."""
-
- def __init__(self, code_reader, jshint, reporter=None):
- """Set the linter with code_reader, jshint engine, and reporter.
-
- Should have following functionality.
- - code_reader.read_file(filename)
- - jshint.run(code, filename)
- - reporter([...])
-
- """
- self.code_reader = code_reader
- self.jshint = jshint
- if reporter is None:
- self.reporter = lambda x: '\n'.join(x)
- else:
- self.reporter = reporter
-
- def lint_file(self, filename):
- """Lint the file and return (pass, error_message)."""
- # Get code contents.
- code = self.code_reader.read_file(filename)
- lines = code.splitlines()
- import_list = StringUtility.get_imported_list(lines)
- if not import_list:
- check_pass, error_message = self.jshint.run(code, filename)
- else:
- newlines, info = self._merge_multiple_codes(filename, import_list)
- # Each line of |newlines| contains '\n'.
- check_pass, error_message = self.jshint.run(''.join(newlines))
- error_message = self._convert_merged_result(error_message, info)
- # Only keep errors for this file.
- error_message = [line for line in error_message
- if line.startswith(filename)]
- check_pass = (len(error_message) == 0)
- return check_pass, self.reporter(error_message)
-
- def _merge_multiple_codes(self, filename, import_list):
- """Merge multiple codes from filename and import_list."""
- dirname, filename = os.path.split(filename)
- dst_line = 1
- dst_results = []
- info = []
-
- # Put the imported script first, and then the original script.
- for f in import_list + [filename]:
- filepath = os.path.join(dirname, f)
-
- # Maintain a mapping table.
- # New line number after merge => original file and line number.
- info.append((dst_line, filepath, 1))
- try:
- code = self.code_reader.read_file(filepath)
- lines = code.splitlines(True) # Keep '\n'.
- src_results = StringUtility.auto_wrap_strict_mode(
- StringUtility.auto_close(lines))
- dst_results.extend(src_results)
- dst_line += len(src_results)
- except:
- info.pop()
- return dst_results, info
-
- def _convert_merged_result(self, error_lines, line_info):
- pattern = re.compile(r'(.*): line (\d+),(.*)')
- start_line = [info[0] for info in line_info]
- new_result_lines = []
- for line in error_lines:
- m = pattern.match(line)
- if not m:
- continue
-
- line_number, remain = int(m.group(2)), m.group(3)
-
- # [1, 2, 7, 8]
- # ^ for 7, pos = 3
- # ^ for 6, pos = 2
- pos = bisect.bisect_right(start_line, line_number)
- dst_line, name, src_line = line_info[pos - 1]
- real_line_number = line_number - dst_line + src_line
- new_result_lines.append(
- "%s: line %s,%s" % (name, real_line_number, remain))
- return new_result_lines
-
-
-class TestRILCodeQuality(MarionetteTestCase):
-
- JSHINT_PATH = 'ril_jshint/jshint.js'
- JSHINTRC_PATH = 'ril_jshint/jshintrc'
-
- def _read_local_file(self, filepath):
- """Read file content from local (folder of this test case)."""
- test_dir = os.path.dirname(inspect.getfile(TestRILCodeQuality))
- return open(os.path.join(test_dir, filepath)).read()
-
- def _get_extended_error_message(self, error_message):
- return '\n'.join(['See errors below and more information in Bug 880643',
- '\n'.join(error_message),
- 'See errors above and more information in Bug 880643'])
-
- def _check(self, filename):
- check_pass, error_message = self.linter.lint_file(filename)
- self.assertTrue(check_pass, error_message)
-
- def setUp(self):
- MarionetteTestCase.setUp(self)
- self.linter = Linter(
- ResourceUriFileReader(self.marionette),
- JSHintEngine(self.marionette,
- self._read_local_file(self.JSHINT_PATH),
- self._read_local_file(self.JSHINTRC_PATH)),
- self._get_extended_error_message)
-
- def tearDown(self):
- MarionetteTestCase.tearDown(self)
-
- def test_RadioInterfaceLayer(self):
- self._check('RadioInterfaceLayer.js')
-
- # Bug 936504. Disable the test for 'ril_worker.js'. It sometimes runs very
- # slow and causes the timeout fail on try server.
- #def test_ril_worker(self):
- # self._check('ril_worker.js')
-
- def test_ril_consts(self):
- self._check('ril_consts.js')
-
- def test_worker_buf(self):
- self._check('worker_buf.js')
diff --git a/dom/system/gonk/tests/marionette/test_screen_state.js b/dom/system/gonk/tests/marionette/test_screen_state.js
deleted file mode 100644
index 2281412d5..000000000
--- a/dom/system/gonk/tests/marionette/test_screen_state.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 10000;
-
-var Services = SpecialPowers.Services;
-
-function testScreenState(on, expected, msg) {
- // send event to RadioInterface
- Services.obs.notifyObservers(null, 'screen-state-changed', on);
- // maybe rild/qemu needs some time to process the event
- window.setTimeout(function() {
- runEmulatorCmd('gsm report creg', function(result) {
- is(result.pop(), 'OK', '\'gsm report creg\' successful');
- ok(result.indexOf(expected) !== -1, msg);
- runNextTest();
- })}, 1000);
-}
-
-function testScreenStateDisabled() {
- testScreenState('off', '+CREG: 1', 'screen is disabled');
-}
-
-function testScreenStateEnabled() {
- testScreenState('on', '+CREG: 2', 'screen is enabled');
-}
-
-var tests = [
- testScreenStateDisabled,
- testScreenStateEnabled
-];
-
-function runNextTest() {
- let test = tests.shift();
- if (!test) {
- cleanUp();
- return;
- }
-
- test();
-}
-
-function cleanUp() {
- finish();
-}
-
-runNextTest();
diff --git a/dom/system/gonk/tests/marionette/test_timezone_changes.js b/dom/system/gonk/tests/marionette/test_timezone_changes.js
deleted file mode 100644
index 11dbaec5a..000000000
--- a/dom/system/gonk/tests/marionette/test_timezone_changes.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-function init() {
- let promises = [];
-
- /*
- * The initial timezone of the emulator could be anywhere, depends the host
- * machine. Ensure resetting it to UTC before testing.
- */
- promises.push(runEmulatorCmdSafe('gsm timezone 0'));
- promises.push(new Promise((aResolve, aReject) => {
- waitFor(aResolve, () => {
- return new Date().getTimezoneOffset() === 0;
- });
- }));
-
- return Promise.all(promises);
-}
-
-function paddingZeros(aNumber, aLength) {
- let str = '' + aNumber;
- while (str.length < aLength) {
- str = '0' + str;
- }
-
- return str;
-}
-
-function verifyDate(aTestDate, aUTCOffsetDate) {
- // Verify basic properties.
- is(aUTCOffsetDate.getUTCFullYear(), aTestDate.getFullYear(), 'year');
- is(aUTCOffsetDate.getUTCMonth(), aTestDate.getMonth(), 'month');
- is(aUTCOffsetDate.getUTCDate(), aTestDate.getDate(), 'date');
- is(aUTCOffsetDate.getUTCHours(), aTestDate.getHours(), 'hours');
- is(aUTCOffsetDate.getUTCMinutes(), aTestDate.getMinutes(), 'minutes');
- is(aUTCOffsetDate.getUTCMilliseconds(), aTestDate.getMilliseconds(), 'milliseconds');
-
- // Ensure toLocaleString also uses correct timezone.
- // It uses ICU's timezone instead of the offset calculated from gecko prtime.
- let expectedDateString =
- paddingZeros(aUTCOffsetDate.getUTCMonth() + 1, 2) + '/' +
- paddingZeros(aUTCOffsetDate.getUTCDate(), 2);
- let dateString = aTestDate.toLocaleString('en-US', {
- month: '2-digit',
- day: '2-digit',
- });
- let expectedTimeString =
- paddingZeros(aUTCOffsetDate.getUTCHours(), 2) + ':' +
- paddingZeros(aUTCOffsetDate.getUTCMinutes(), 2);
- let timeString = aTestDate.toLocaleString('en-US', {
- hour12: false,
- hour: '2-digit',
- minute: '2-digit'
- });
-
- is(expectedDateString, dateString, 'dateString');
- is(expectedTimeString, timeString, 'timeString');
-}
-
-function waitForTimezoneUpdate(aTzOffset,
- aTestDateInMillis = 86400000, // Use 'UTC 00:00:00, 2nd of Jan, 1970' by default.
- aTransTzOffset, aTransTestDateInMillis) {
- return new Promise(function(aResolve, aReject) {
- window.addEventListener('moztimechange', function onevent(aEvent) {
- // Since there could be multiple duplicate moztimechange event, wait until
- // timezone is actually changed to expected value before removing the
- // listener.
- let testDate = new Date(aTestDateInMillis);
- if (testDate.getTimezoneOffset() === aTzOffset) {
- window.removeEventListener('moztimechange', onevent);
-
- // The UTC time of offsetDate is the same as the expected local time of
- // testDate. We'll use it to verify the values.
- let offsetDate = new Date(aTestDateInMillis - aTzOffset * 60 * 1000);
- verifyDate(testDate, offsetDate);
-
- // Verify transition time if given.
- if (aTransTzOffset !== undefined) {
- testDate = new Date(aTransTestDateInMillis);
- is(testDate.getTimezoneOffset(), aTransTzOffset);
-
- // Verify transition date.
- offsetDate = new Date(aTransTestDateInMillis - aTransTzOffset * 60 * 1000);
- verifyDate(testDate, offsetDate);
- }
-
- aResolve(aEvent);
- }
- });
- });
-}
-
-function testChangeNitzTimezone(aTzDiff) {
- let promises = [];
-
- // aTzOffset should be the expected value for getTimezoneOffset().
- // Note that getTimezoneOffset() is not so straightforward,
- // it values (UTC - localtime), so UTC+08:00 returns -480.
- promises.push(waitForTimezoneUpdate(-aTzDiff * 15));
- promises.push(runEmulatorCmdSafe('gsm timezone ' + aTzDiff));
-
- return Promise.all(promises);
-}
-
-function testChangeOlsonTimezone(aOlsonTz, aTzOffset, aTestDateInMillis,
- aTransTzOffset, aTransTestDateInMillis) {
- let promises = [];
-
- promises.push(waitForTimezoneUpdate(aTzOffset, aTestDateInMillis,
- aTransTzOffset, aTransTestDateInMillis));
- promises.push(setSettings('time.timezone', aOlsonTz));
-
- return Promise.all(promises);
-}
-
-// Start test
-startTestBase(function() {
- return init()
- .then(() => testChangeNitzTimezone(36)) // UTC+09:00
- .then(() => testChangeOlsonTimezone('America/New_York',
- 300, 1446357600000, // 2015/11/01 02:00 UTC-04:00 => 01:00 UTC-05:00 (EST)
- 240, 1425798000000)) // 2015/03/08 02:00 UTC-05:00 => 03:00 UTC-04:00 (EDT)
- .then(() => testChangeNitzTimezone(-22)) // UTC-05:30
- .then(() => testChangeNitzTimezone(51)) // UTC+12:45
- .then(() => testChangeOlsonTimezone('Australia/Adelaide',
- -570, 1428165000000, // 2015/04/05 03:00 UTC+10:30 => 02:00 UTC+09:30 (ACST)
- -630, 1443889800000)) // 2015/10/04 02:00 UTC+09:30 => 03:00 UTC+10:30 (ACDT)
- .then(() => testChangeNitzTimezone(-38)) // UTC-09:30
- .then(() => testChangeNitzTimezone(0)) // UTC
- .then(() => runEmulatorCmdSafe('gsm timezone auto'));
-});
diff --git a/dom/system/gonk/tests/test_ril_system_messenger.js b/dom/system/gonk/tests/test_ril_system_messenger.js
deleted file mode 100644
index a588d0ddb..000000000
--- a/dom/system/gonk/tests/test_ril_system_messenger.js
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-var RIL = {};
-Cu.import("resource://gre/modules/ril_consts.js", RIL);
-
-XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory",
- "@mozilla.org/icc/stkcmdfactory;1",
- "nsIStkCmdFactory");
-
-/**
- * Name space for RILSystemMessenger.jsm. Only initialized after first call to
- * newRILSystemMessenger.
- */
-var RSM;
-
-var gReceivedMsgType = null;
-var gReceivedMessage = null;
-
-/**
- * Create a new RILSystemMessenger instance.
- *
- * @return a RILSystemMessenger instance.
- */
-function newRILSystemMessenger() {
- if (!RSM) {
- RSM = Cu.import("resource://gre/modules/RILSystemMessenger.jsm", {});
- equal(typeof RSM.RILSystemMessenger, "function", "RSM.RILSystemMessenger");
- }
-
- let rsm = new RSM.RILSystemMessenger();
- rsm.broadcastMessage = (aType, aMessage) => {
- gReceivedMsgType = aType;
- gReceivedMessage = aMessage;
- };
-
- rsm.createCommandMessage = (aStkProactiveCmd) => {
- return gStkCmdFactory.createCommandMessage(aStkProactiveCmd);
- };
-
- return rsm;
-}
-
-function equal_received_system_message(aType, aMessage) {
- equal(aType, gReceivedMsgType);
- deepEqual(aMessage, gReceivedMessage);
- gReceivedMsgType = null;
- gReceivedMessage = null;
-}
-
-/**
- * Verify that each nsIXxxMessenger could be retrieved.
- */
-function run_test() {
- let telephonyMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsITelephonyMessenger);
-
- let smsMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsISmsMessenger);
-
- let cellbroadcastMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsICellbroadcastMessenger);
-
- let mobileConnectionMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsIMobileConnectionMessenger);
-
- let iccMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsIIccMessenger);
-
- ok(telephonyMessenger !== null, "Get TelephonyMessenger.");
- ok(smsMessenger != null, "Get SmsMessenger.");
- ok(cellbroadcastMessenger != null, "Get CellbroadcastMessenger.");
- ok(mobileConnectionMessenger != null, "Get MobileConnectionMessenger.");
- ok(iccMessenger != null, "Get IccMessenger.");
-
- run_next_test();
-}
-
-/**
- * Verify RILSystemMessenger.notifyNewCall()
- */
-add_test(function test_telephony_messenger_notify_new_call() {
- let messenger = newRILSystemMessenger();
-
- messenger.notifyNewCall();
- equal_received_system_message("telephony-new-call", {});
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyCallEnded()
- */
-add_test(function test_telephony_messenger_notify_call_ended() {
- let messenger = newRILSystemMessenger();
-
- messenger.notifyCallEnded(1,
- "+0987654321",
- null,
- true,
- 500,
- false,
- true);
-
- equal_received_system_message("telephony-call-ended", {
- serviceId: 1,
- number: "+0987654321",
- emergency: true,
- duration: 500,
- direction: "incoming",
- hangUpLocal: true
- });
-
- // Verify 'optional' parameter of secondNumber.
- messenger.notifyCallEnded(1,
- "+0987654321",
- "+1234567890",
- true,
- 500,
- true,
- false);
-
- equal_received_system_message("telephony-call-ended", {
- serviceId: 1,
- number: "+0987654321",
- emergency: true,
- duration: 500,
- direction: "outgoing",
- hangUpLocal: false,
- secondNumber: "+1234567890"
- });
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifySms()
- */
-add_test(function test_sms_messenger_notify_sms() {
- let messenger = newRILSystemMessenger();
- let timestamp = Date.now();
- let sentTimestamp = timestamp + 100;
- let deliveryTimestamp = sentTimestamp + 100;
-
- // Verify 'sms-received' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_RECEIVED,
- 1,
- 2,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_RECEIVED,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
- "+0987654321",
- null,
- "Incoming message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_CLASS_2,
- timestamp,
- sentTimestamp,
- 0,
- false);
-
- equal_received_system_message("sms-received", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 1,
- threadId: 2,
- delivery: "received",
- deliveryStatus: "success",
- sender: "+0987654321",
- receiver: null,
- body: "Incoming message",
- messageClass: "class-2",
- timestamp: timestamp,
- sentTimestamp: sentTimestamp,
- deliveryTimestamp: 0,
- read: false
- });
-
- // Verify 'sms-sent' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_SENT,
- 3,
- 4,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_SENT,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_PENDING,
- null,
- "+0987654321",
- "Outgoing message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- 0,
- 0,
- true);
-
- equal_received_system_message("sms-sent", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 3,
- threadId: 4,
- delivery: "sent",
- deliveryStatus: "pending",
- sender: null,
- receiver: "+0987654321",
- body: "Outgoing message",
- messageClass: "normal",
- timestamp: timestamp,
- sentTimestamp: 0,
- deliveryTimestamp: 0,
- read: true
- });
-
- // Verify 'sms-delivery-success' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_DELIVERY_SUCCESS,
- 5,
- 6,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_SENT,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
- null,
- "+0987654321",
- "Outgoing message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- 0,
- deliveryTimestamp,
- true);
-
- equal_received_system_message("sms-delivery-success", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 5,
- threadId: 6,
- delivery: "sent",
- deliveryStatus: "success",
- sender: null,
- receiver: "+0987654321",
- body: "Outgoing message",
- messageClass: "normal",
- timestamp: timestamp,
- sentTimestamp: 0,
- deliveryTimestamp: deliveryTimestamp,
- read: true
- });
-
- // Verify 'sms-failed' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_SENT_FAILED,
- 7,
- 8,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_ERROR,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_ERROR,
- null,
- "+0987654321",
- "Outgoing message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- 0,
- 0,
- true);
-
- equal_received_system_message("sms-failed", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 7,
- threadId: 8,
- delivery: "error",
- deliveryStatus: "error",
- sender: null,
- receiver: "+0987654321",
- body: "Outgoing message",
- messageClass: "normal",
- timestamp: timestamp,
- sentTimestamp: 0,
- deliveryTimestamp: 0,
- read: true
- });
-
- // Verify 'sms-delivery-error' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_DELIVERY_ERROR,
- 9,
- 10,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_SENT,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_ERROR,
- null,
- "+0987654321",
- "Outgoing message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- 0,
- 0,
- true);
-
- equal_received_system_message("sms-delivery-error", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 9,
- threadId: 10,
- delivery: "sent",
- deliveryStatus: "error",
- sender: null,
- receiver: "+0987654321",
- body: "Outgoing message",
- messageClass: "normal",
- timestamp: timestamp,
- sentTimestamp: 0,
- deliveryTimestamp: 0,
- read: true
- });
-
- // Verify the protection of invalid nsISmsMessenger.NOTIFICATION_TYPEs.
- try {
- messenger.notifySms(5,
- 1,
- 2,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_RECEIVED,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
- "+0987654321",
- null,
- "Incoming message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- sentTimestamp,
- 0,
- false);
- ok(false, "Failed to verify the protection of invalid nsISmsMessenger.NOTIFICATION_TYPE!");
- } catch (e) {}
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyCbMessageReceived()
- */
-add_test(function test_cellbroadcast_messenger_notify_cb_message_received() {
- let messenger = newRILSystemMessenger();
- let timestamp = Date.now();
-
- // Verify ETWS
- messenger.notifyCbMessageReceived(0,
- Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_CELL_IMMEDIATE,
- 256,
- 4352,
- null,
- null,
- Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_NORMAL,
- timestamp,
- Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID,
- true,
- Ci.nsICellBroadcastService.GSM_ETWS_WARNING_EARTHQUAKE,
- false,
- true);
- equal_received_system_message("cellbroadcast-received", {
- serviceId: 0,
- gsmGeographicalScope: "cell-immediate",
- messageCode: 256,
- messageId: 4352,
- language: null,
- body: null,
- messageClass: "normal",
- timestamp: timestamp,
- cdmaServiceCategory: null,
- etws: {
- warningType: "earthquake",
- emergencyUserAlert: false,
- popup: true
- }
- });
-
- // Verify Normal CB Message
- messenger.notifyCbMessageReceived(1,
- Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_PLMN,
- 0,
- 50,
- "en",
- "The quick brown fox jumps over the lazy dog",
- Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_NORMAL,
- timestamp,
- Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID,
- false,
- Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID,
- false,
- false);
- equal_received_system_message("cellbroadcast-received", {
- serviceId: 1,
- gsmGeographicalScope: "plmn",
- messageCode: 0,
- messageId: 50,
- language: "en",
- body: "The quick brown fox jumps over the lazy dog",
- messageClass: "normal",
- timestamp: timestamp,
- cdmaServiceCategory: null,
- etws: null
- });
-
- // Verify CB Message with ETWS Info
- messenger.notifyCbMessageReceived(0,
- Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_LOCATION_AREA,
- 0,
- 4354,
- "en",
- "Earthquake & Tsunami Warning!",
- Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_0,
- timestamp,
- Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID,
- true,
- Ci.nsICellBroadcastService.GSM_ETWS_WARNING_EARTHQUAKE_TSUNAMI,
- true,
- false);
- equal_received_system_message("cellbroadcast-received", {
- serviceId: 0,
- gsmGeographicalScope: "location-area",
- messageCode: 0,
- messageId: 4354,
- language: "en",
- body: "Earthquake & Tsunami Warning!",
- messageClass: "class-0",
- timestamp: timestamp,
- cdmaServiceCategory: null,
- etws: {
- warningType: "earthquake-tsunami",
- emergencyUserAlert: true,
- popup: false
- }
- });
-
- // Verify CDMA CB Message
- messenger.notifyCbMessageReceived(0,
- Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_INVALID,
- 0,
- 0,
- null,
- "CDMA CB Message",
- Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_NORMAL,
- timestamp,
- 512,
- false,
- Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID,
- false,
- false);
- equal_received_system_message("cellbroadcast-received", {
- serviceId: 0,
- gsmGeographicalScope: null,
- messageCode: 0,
- messageId: 0,
- language: null,
- body: "CDMA CB Message",
- messageClass: "normal",
- timestamp: timestamp,
- cdmaServiceCategory: 512,
- etws: null
- });
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyUssdReceived()
- */
-add_test(function test_mobileconnection_notify_ussd_received() {
- let messenger = newRILSystemMessenger();
-
- messenger.notifyUssdReceived(0, "USSD Message", false);
-
- equal_received_system_message("ussd-received", {
- serviceId: 0,
- message: "USSD Message",
- sessionEnded: false
- });
-
- messenger.notifyUssdReceived(1, "USSD Message", true);
-
- equal_received_system_message("ussd-received", {
- serviceId: 1,
- message: "USSD Message",
- sessionEnded: true
- });
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyCdmaInfoRecXXX()
- */
-add_test(function test_mobileconnection_notify_cdma_info() {
- let messenger = newRILSystemMessenger();
-
- messenger.notifyCdmaInfoRecDisplay(0, "CDMA Display Info");
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- display: "CDMA Display Info"
- });
-
- messenger.notifyCdmaInfoRecCalledPartyNumber(1, 1, 2, "+0987654321", 3, 4);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 1,
- calledNumber: {
- type: 1,
- plan: 2,
- number: "+0987654321",
- pi: 3,
- si: 4
- }
- });
-
- messenger.notifyCdmaInfoRecCallingPartyNumber(0, 5, 6, "+1234567890", 7, 8);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- callingNumber: {
- type: 5,
- plan: 6,
- number: "+1234567890",
- pi: 7,
- si: 8
- }
- });
-
- messenger.notifyCdmaInfoRecConnectedPartyNumber(1, 4, 3, "+56473839201", 2, 1);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 1,
- connectedNumber: {
- type: 4,
- plan: 3,
- number: "+56473839201",
- pi: 2,
- si: 1
- }
- });
-
- messenger.notifyCdmaInfoRecSignal(0, 1, 2, 3);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- signal: {
- type: 1,
- alertPitch: 2,
- signal: 3
- }
- });
-
- messenger.notifyCdmaInfoRecRedirectingNumber(1, 8, 7, "+1029384756", 6, 5, 4);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 1,
- redirect: {
- type: 8,
- plan: 7,
- number: "+1029384756",
- pi: 6,
- si: 5,
- reason: 4
- }
- });
-
- messenger.notifyCdmaInfoRecLineControl(0, 1, 0, 1, 255);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- lineControl: {
- polarityIncluded: 1,
- toggle: 0,
- reverse: 1,
- powerDenial: 255
- }
- });
-
- messenger.notifyCdmaInfoRecClir(1, 256);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 1,
- clirCause: 256
- });
-
- messenger.notifyCdmaInfoRecAudioControl(0, 255, -1);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- audioControl: {
- upLink: 255,
- downLink: -1
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Error Handling of StkProactiveCmdFactory.createCommand()
- */
-add_test(function test_icc_stk_cmd_factory_create_command_error() {
- let messenger = newRILSystemMessenger();
-
- // Verify the protection of invalid typeOfCommand.
- try {
- gStkCmdFactory.createCommand({
- commandNumber: 0,
- typeOfCommand: RIL.STK_CMD_MORE_TIME, // Invalid TypeOfCommand
- commandQualifier: 0x00
- });
-
- ok(false, "Failed to verify the protection of createCommand()!");
- } catch (e) {
- ok(e.message.indexOf("Unknown Command Type") !== -1,
- "Invalid typeOfCommand!");
- }
-
- run_next_test();
-});
-
-/**
- * Verify Error Handling of StkProactiveCmdFactory.createCommandMessage()
- */
-add_test(function test_icc_stk_cmd_factory_create_system_msg_invalid_cmd_type() {
- let messenger = newRILSystemMessenger();
- let iccId = "99887766554433221100";
-
- // Verify the protection of invalid typeOfCommand.
- try {
- gStkCmdFactory.createCommandMessage({
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd]),
-
- // nsIStkProactiveCmd
- commandNumber: 0,
- typeOfCommand: RIL.STK_CMD_MORE_TIME, // Invalid TypeOfCommand
- commandQualifier: 0
- });
-
- ok(false, "Failed to identify invalid typeOfCommand!");
- } catch (e) {
- ok(e.message.indexOf("Unknown Command Type") !== -1,
- "Invalid typeOfCommand!");
- }
-
- run_next_test();
-});
-
-/**
- * Verify Error Handling of StkProactiveCmdFactory.createCommandMessage()
- */
-add_test(function test_icc_stk_cmd_factory_create_system_msg_incorrect_cmd_type() {
- let messenger = newRILSystemMessenger();
- let iccId = "99887766554433221100";
-
- // Verify the protection of invalid typeOfCommand.
- try {
- gStkCmdFactory.createCommandMessage({
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
- Ci.nsIStkProvideLocalInfoCmd]),
-
- // nsIStkProactiveCmd
- commandNumber: 0,
- typeOfCommand: RIL.STK_CMD_POLL_INTERVAL, // Incorrect typeOfCommand
- commandQualifier: 0,
- // nsIStkProvideLocalInfoCmd
- localInfoType: 0x00,
- });
-
- ok(false, "Failed to identify incorrect typeOfCommand!");
- } catch (e) {
- ok(e.message.indexOf("Failed to convert command into concrete class: ") !== -1);
- }
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyStkProactiveCommand()
- */
-add_test(function test_icc_notify_stk_proactive_command() {
- let messenger = newRILSystemMessenger();
- let iccId = "99887766554433221100";
- let WHT = 0xFFFFFFFF;
- let BLK = 0x000000FF;
- let RED = 0xFF0000FF;
- let GRN = 0x00FF00FF;
- let BLU = 0x0000FFFF;
- let TSP = 0;
- // Basic Image, see Anex B.1 in TS 31.102.
- let basicIcon = {
- width: 8,
- height: 8,
- codingScheme: "basic",
- pixels: [WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT,
- BLK, BLK, BLK, BLK, BLK, BLK, WHT, WHT,
- WHT, BLK, WHT, BLK, BLK, WHT, BLK, WHT,
- WHT, BLK, BLK, WHT, WHT, BLK, BLK, WHT,
- WHT, BLK, BLK, WHT, WHT, BLK, BLK, WHT,
- WHT, BLK, WHT, BLK, BLK, WHT, BLK, WHT,
- WHT, WHT, BLK, BLK, BLK, BLK, WHT, WHT,
- WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT]
- };
- // Color Image, see Anex B.2 in TS 31.102.
- let colorIcon = {
- width: 8,
- height: 8,
- codingScheme: "color",
- pixels: [BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU,
- BLU, RED, RED, RED, RED, RED, RED, BLU,
- BLU, RED, GRN, GRN, GRN, RED, RED, BLU,
- BLU, RED, RED, GRN, GRN, RED, RED, BLU,
- BLU, RED, RED, GRN, GRN, RED, RED, BLU,
- BLU, RED, RED, GRN, GRN, GRN, RED, BLU,
- BLU, RED, RED, RED, RED, RED, RED, BLU,
- BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU]
- };
- // Color Image with Transparency, see Anex B.2 in TS 31.102.
- let colorTransparencyIcon = {
- width: 8,
- height: 8,
- codingScheme: "color-transparency",
- pixels: [TSP, TSP, TSP, TSP, TSP, TSP, TSP, TSP,
- TSP, RED, RED, RED, RED, RED, RED, TSP,
- TSP, RED, GRN, GRN, GRN, RED, RED, TSP,
- TSP, RED, RED, GRN, GRN, RED, RED, TSP,
- TSP, RED, RED, GRN, GRN, RED, RED, TSP,
- TSP, RED, RED, GRN, GRN, GRN, RED, TSP,
- TSP, RED, RED, RED, RED, RED, RED, TSP,
- TSP, TSP, TSP, TSP, TSP, TSP, TSP, TSP]
- };
-
- let cmdCount = 0;
-
- // Test Messages:
- let messages = [
- // STK_CMD_REFRESH
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_REFRESH,
- commandQualifier: 0x04 // UICC Reset
- },
- // STK_CMD_POLL_INTERVAL
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_POLL_INTERVAL,
- commandQualifier: 0x00, // RFU
- options: {
- timeUnit: RIL.STK_TIME_UNIT_TENTH_SECOND,
- timeInterval: 0x05
- }
- },
- // STK_CMD_POLL_OFF
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_POLL_OFF,
- commandQualifier: 0x00, // RFU
- },
- // STK_CMD_PROVIDE_LOCAL_INFO
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_PROVIDE_LOCAL_INFO,
- commandQualifier: 0x01, // IMEI of the terminal
- options: {
- localInfoType: 0x01 // IMEI of the terminal
- }
- },
- // STK_CMD_SET_UP_EVENT_LIST with eventList
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_EVENT_LIST,
- commandQualifier: 0x00, // RFU
- options: {
- eventList: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C ]
- }
- },
- // STK_CMD_SET_UP_EVENT_LIST without eventList
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_EVENT_LIST,
- commandQualifier: 0x00, // RFU
- options: {
- eventList: null
- }
- },
- // STK_CMD_SET_UP_MENU with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_MENU,
- commandQualifier: 0x80, // bit 8: 1 = help information available
- options: {
- title: "Toolkit Menu 1",
- items: [
- { identifier: 0x01, text: "Menu Item 1" },
- { identifier: 0x02, text: "Menu Item 2" },
- { identifier: 0x03, text: "Menu Item 3" }
- ],
- isHelpAvailable: true
- }
- },
- // STK_CMD_SET_UP_MENU with optional properties including:
- // iconInfo for this menu, iconInfo for each item and nextActionList.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_MENU,
- commandQualifier: 0x00, // bit 8: 0 = help information is not available
- options: {
- title: "Toolkit Menu 2",
- items: [
- { identifier: 0x01,
- text: "Menu Item 1",
- iconSelfExplanatory: true,
- icons: [basicIcon]
- },
- { identifier: 0x02,
- text: "Menu Item 2",
- iconSelfExplanatory: false,
- icons: [basicIcon, colorIcon]
- },
- { identifier: 0x03,
- text: "Menu Item 3",
- iconSelfExplanatory: true,
- icons: [basicIcon, colorIcon, colorTransparencyIcon]
- },
- ],
- nextActionList: [
- RIL.STK_NEXT_ACTION_END_PROACTIVE_SESSION,
- RIL.STK_NEXT_ACTION_NULL,
- RIL.STK_NEXT_ACTION_NULL,
- RIL.STK_NEXT_ACTION_NULL
- ],
- iconSelfExplanatory: false,
- icons: [basicIcon, colorIcon, colorTransparencyIcon],
- isHelpAvailable: false
- }
- },
- // STK_CMD_SELECT_ITEM with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SELECT_ITEM,
- commandQualifier: RIL.STK_PRESENTATION_TYPE_NOT_SPECIFIED,
- options: {
- title: null,
- items: [
- { identifier: 0x01, text: "Menu Item 1" },
- { identifier: 0x02, text: "Menu Item 2" },
- { identifier: 0x03, text: "Menu Item 3" }
- ],
- presentationType: RIL.STK_PRESENTATION_TYPE_NOT_SPECIFIED,
- isHelpAvailable: false
- }
- },
- // STK_CMD_SELECT_ITEM with optional properties including:
- // title, iconInfo for this menu, iconInfo for each item and nextActionList.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SELECT_ITEM,
- commandQualifier: RIL.STK_PRESENTATION_TYPE_NAVIGATION_OPTIONS,
- options: {
- title: "Selected Toolkit Menu",
- items: [
- { identifier: 0x01,
- text: "Menu Item 1",
- iconSelfExplanatory: true,
- icons: [basicIcon]
- },
- { identifier: 0x02,
- text: "Menu Item 2",
- iconSelfExplanatory: false,
- icons: [basicIcon, colorIcon]
- },
- { identifier: 0x03,
- text: "Menu Item 3",
- iconSelfExplanatory: true,
- icons: [basicIcon, colorIcon, colorTransparencyIcon]
- },
- ],
- nextActionList: [
- RIL.STK_NEXT_ACTION_END_PROACTIVE_SESSION,
- RIL.STK_NEXT_ACTION_NULL,
- RIL.STK_NEXT_ACTION_NULL,
- RIL.STK_NEXT_ACTION_NULL
- ],
- defaultItem: 0x02,
- iconSelfExplanatory: false,
- icons: [basicIcon, colorIcon, colorTransparencyIcon],
- presentationType: RIL.STK_PRESENTATION_TYPE_NAVIGATION_OPTIONS,
- isHelpAvailable: false
- }
- },
- // STK_CMD_DISPLAY_TEXT with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_DISPLAY_TEXT,
- commandQualifier: 0x01, // bit 1: High Priority
- options: {
- text: "Display Text 1",
- isHighPriority: true,
- userClear: false,
- responseNeeded: false
- }
- },
- // STK_CMD_DISPLAY_TEXT with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_DISPLAY_TEXT,
- commandQualifier: 0x80, // bit 8: User Clear
- options: {
- text: "Display Text 2",
- isHighPriority: false,
- userClear: true,
- responseNeeded: true,
- duration: {
- timeUnit: RIL.STK_TIME_UNIT_TENTH_SECOND,
- timeInterval: 0x05
- },
- iconSelfExplanatory: true,
- icons: [basicIcon]
- }
- },
- // STK_CMD_SET_UP_IDLE_MODE_TEXT
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_IDLE_MODE_TEXT,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Setup Idle Mode Text"
- }
- },
- // STK_CMD_SEND_SS
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_SS,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Send SS",
- iconSelfExplanatory: true,
- icons: [colorIcon]
- }
- },
- // STK_CMD_SEND_USSD
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_USSD,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Send USSD"
- }
- },
- // STK_CMD_SEND_SMS
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_SMS,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Send SMS",
- iconSelfExplanatory: false,
- icons: [colorTransparencyIcon]
- }
- },
- // STK_CMD_SEND_DTMF
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_DTMF,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Send DTMF",
- iconSelfExplanatory: true,
- icons: [basicIcon]
- }
- },
- // STK_CMD_GET_INKEY
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_GET_INKEY,
- commandQualifier: 0x84, // bit 3: isYesNoRequested, bit 8: isHelpAvailable
- options: {
- text: "Get Input Key",
- minLength: 1,
- maxLength: 1,
- duration: {
- timeUnit: RIL.STK_TIME_UNIT_SECOND,
- timeInterval: 0x0A
- },
- isAlphabet: false,
- isUCS2: false,
- isYesNoRequested: true,
- isHelpAvailable: true,
- defaultText: null,
- iconSelfExplanatory: false,
- icons: [colorIcon]
- }
- },
- // STK_CMD_GET_INPUT
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_GET_INPUT,
- commandQualifier: 0x0F, // bit 1-4: isAlphabet, isUCS2, hideInput, isPacked
- options: {
- text: "Get Input Text",
- minLength: 1,
- maxLength: 255,
- defaultText: "Default Input Text",
- isAlphabet: true,
- isUCS2: true,
- hideInput: true,
- isPacked: true,
- isHelpAvailable: false,
- defaultText: null,
- iconSelfExplanatory: true,
- icons: [basicIcon]
- }
- },
- // STK_CMD_SET_UP_CALL with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_CALL,
- commandQualifier: 0x00, // RFU
- options: {
- address: "+0987654321"
- }
- },
- // STK_CMD_SET_UP_CALL with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_CALL,
- commandQualifier: 0x00, // RFU
- options: {
- address: "+0987654321",
- confirmMessage: {
- text: "Confirm Message",
- iconSelfExplanatory: false,
- icons: [colorIcon]
- },
- callMessage: {
- text: "Call Message",
- iconSelfExplanatory: true,
- icons: [basicIcon]
- },
- duration: {
- timeUnit: RIL.STK_TIME_UNIT_SECOND,
- timeInterval: 0x0A
- }
- }
- },
- // STK_CMD_LAUNCH_BROWSER with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_LAUNCH_BROWSER,
- commandQualifier: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
- options: {
- url: "http://www.mozilla.org",
- mode: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER
- }
- },
- // STK_CMD_LAUNCH_BROWSER with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_LAUNCH_BROWSER,
- commandQualifier: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
- options: {
- url: "http://www.mozilla.org",
- mode: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
- confirmMessage: {
- text: "Confirm Message for Launch Browser",
- iconSelfExplanatory: false,
- icons: [colorTransparencyIcon]
- }
- }
- },
- // STK_CMD_PLAY_TONE with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_PLAY_TONE,
- commandQualifier: 0x01, // isVibrate
- options: {
- text: null,
- isVibrate: true
- }
- },
- // STK_CMD_PLAY_TONE with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_PLAY_TONE,
- commandQualifier: 0x00, // isVibrate = false
- options: {
- text: "Play Tone",
- tone: RIL.STK_TONE_TYPE_CONGESTION,
- isVibrate: false,
- duration: {
- timeUnit: RIL.STK_TIME_UNIT_SECOND,
- timeInterval: 0x0A
- },
- iconSelfExplanatory: true,
- icons: [basicIcon]
- }
- },
- // STK_CMD_TIMER_MANAGEMENT with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_TIMER_MANAGEMENT,
- commandQualifier: RIL.STK_TIMER_DEACTIVATE,
- options: {
- timerId: 0x08,
- timerAction: RIL.STK_TIMER_DEACTIVATE
- }
- },
- // STK_CMD_TIMER_MANAGEMENT with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_TIMER_MANAGEMENT,
- commandQualifier: RIL.STK_TIMER_START,
- options: {
- timerId: 0x01,
- timerValue: (12 * 60 * 60) + (30 * 60) + (30), // 12:30:30
- timerAction: RIL.STK_TIMER_START
- }
- },
- // STK_CMD_OPEN_CHANNEL with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_OPEN_CHANNEL,
- commandQualifier: 0x00, //RFU
- options: {
- text: null,
- }
- },
- // STK_CMD_OPEN_CHANNEL with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_OPEN_CHANNEL,
- commandQualifier: 0x00, //RFU
- options: {
- text: "Open Channel",
- iconSelfExplanatory: false,
- icons: [colorIcon]
- }
- },
- // STK_CMD_CLOSE_CHANNEL with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_CLOSE_CHANNEL,
- commandQualifier: 0x00, //RFU
- options: {
- text: "Close Channel",
- iconSelfExplanatory: true,
- icons: [colorTransparencyIcon]
- }
- },
- // STK_CMD_SEND_DATA with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_DATA,
- commandQualifier: 0x00, //RFU
- options: {
- text: null,
- iconSelfExplanatory: false,
- icons: [basicIcon]
- }
- },
- // STK_CMD_RECEIVE_DATA with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_RECEIVE_DATA,
- commandQualifier: 0x00, //RFU
- options: {
- text: "Receive Data"
- }
- },
- null // Termination condition to run_next_test()
- ];
-
- messages.forEach(function(aMessage) {
- if (!aMessage) {
- run_next_test();
- return;
- }
-
- messenger.notifyStkProactiveCommand(iccId,
- gStkCmdFactory.createCommand(aMessage));
-
- equal_received_system_message("icc-stkcommand", {
- iccId: iccId,
- command: aMessage
- });
- });
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_barring_password.js b/dom/system/gonk/tests/test_ril_worker_barring_password.js
deleted file mode 100644
index fcd3e4405..000000000
--- a/dom/system/gonk/tests/test_ril_worker_barring_password.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-const PIN = "0000";
-const NEW_PIN = "1234";
-
-add_test(function test_change_call_barring_password() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
-
- function do_test(facility, pin, newPin) {
- buf.sendParcel = function fakeSendParcel () {
- // Request Type.
- equal(this.readInt32(), REQUEST_CHANGE_BARRING_PASSWORD);
-
- // Token : we don't care.
- this.readInt32();
-
- let parcel = this.readStringList();
- equal(parcel.length, 3);
- equal(parcel[0], facility);
- equal(parcel[1], pin);
- equal(parcel[2], newPin);
- };
-
- let options = {facility: facility, pin: pin, newPin: newPin};
- context.RIL.changeCallBarringPassword(options);
- }
-
- do_test(ICC_CB_FACILITY_BA_ALL, PIN, NEW_PIN);
-
- run_next_test();
-});
-
-add_test(function test_check_change_call_barring_password_result() {
- let barringPasswordOptions;
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
-
- let context = worker.ContextPool._contexts[0];
- context.RIL.changeCallBarringPassword =
- function fakeChangeCallBarringPassword(options) {
- barringPasswordOptions = options;
- context.RIL[REQUEST_CHANGE_BARRING_PASSWORD](0, {});
- };
-
- context.RIL.changeCallBarringPassword({pin: PIN, newPin: NEW_PIN});
-
- let postedMessage = workerHelper.postedMessage;
- equal(barringPasswordOptions.pin, PIN);
- equal(barringPasswordOptions.newPin, NEW_PIN);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_buf.js b/dom/system/gonk/tests/test_ril_worker_buf.js
deleted file mode 100644
index 30054a881..000000000
--- a/dom/system/gonk/tests/test_ril_worker_buf.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Add test function with specified parcel and request handler.
- *
- * @param parcel
- * Incoming parcel to be tested.
- * @param handler
- * Handler to be invoked as RIL request handler.
- */
-function add_test_incoming_parcel(parcel, handler) {
- add_test(function test_incoming_parcel() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // do nothing
- },
- postMessage: function(message) {
- // do nothing
- }
- });
-
- if (!parcel) {
- parcel = newIncomingParcel(-1,
- worker.RESPONSE_TYPE_UNSOLICITED,
- worker.REQUEST_VOICE_REGISTRATION_STATE,
- [0, 0, 0, 0]);
- }
-
- let context = worker.ContextPool._contexts[0];
- // supports only requests less or equal than UINT8_MAX(255).
- let buf = context.Buf;
- let request = parcel[buf.PARCEL_SIZE_SIZE + buf.UINT32_SIZE];
- context.RIL[request] = function ril_request_handler() {
- handler.apply(this, arguments);
- };
-
- worker.onRILMessage(0, parcel);
-
- // end of incoming parcel's trip, let's do next test.
- run_next_test();
- });
-}
-
-// Test normal parcel handling.
-add_test_incoming_parcel(null,
- function test_normal_parcel_handling() {
- let self = this;
- try {
- // reads exactly the same size, should not throw anything.
- self.context.Buf.readInt32();
- } catch (e) {
- ok(false, "Got exception: " + e);
- }
- }
-);
-
-// Test parcel under read.
-add_test_incoming_parcel(null,
- function test_parcel_under_read() {
- let self = this;
- try {
- // reads less than parcel size, should not throw.
- self.context.Buf.readUint16();
- } catch (e) {
- ok(false, "Got exception: " + e);
- }
- }
-);
-
-// Test parcel over read.
-add_test_incoming_parcel(null,
- function test_parcel_over_read() {
- let buf = this.context.Buf;
-
- // read all data available
- while (buf.readAvailable > 0) {
- buf.readUint8();
- }
-
- throws(function over_read_handler() {
- // reads more than parcel size, should throw an error.
- buf.readUint8();
- },"Trying to read data beyond the parcel end!");
- }
-);
-
-// Test Bug 814761: buffer overwritten
-add_test(function test_incoming_parcel_buffer_overwritten() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // do nothing
- },
- postMessage: function(message) {
- // do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- // A convenient alias.
- let buf = context.Buf;
-
- // Allocate an array of specified size and set each of its elements to value.
- function calloc(length, value) {
- let array = new Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = value;
- }
- return array;
- }
-
- // Do nothing in handleParcel().
- let request = worker.REQUEST_VOICE_REGISTRATION_STATE;
- context.RIL[request] = null;
-
- // Prepare two parcels, whose sizes are both smaller than the incoming buffer
- // size but larger when combined, to trigger the bug.
- let pA_dataLength = buf.incomingBufferLength / 2;
- let pA = newIncomingParcel(-1,
- worker.RESPONSE_TYPE_UNSOLICITED,
- request,
- calloc(pA_dataLength, 1));
- let pA_parcelSize = pA.length - buf.PARCEL_SIZE_SIZE;
-
- let pB_dataLength = buf.incomingBufferLength * 3 / 4;
- let pB = newIncomingParcel(-1,
- worker.RESPONSE_TYPE_UNSOLICITED,
- request,
- calloc(pB_dataLength, 1));
- let pB_parcelSize = pB.length - buf.PARCEL_SIZE_SIZE;
-
- // First, send an incomplete pA and verifies related data pointer:
- let p1 = pA.subarray(0, pA.length - 1);
- worker.onRILMessage(0, p1);
- // The parcel should not have been processed.
- equal(buf.readAvailable, 0);
- // buf.currentParcelSize should have been set because incoming data has more
- // than 4 octets.
- equal(buf.currentParcelSize, pA_parcelSize);
- // buf.readIncoming should contains remaining unconsumed octets count.
- equal(buf.readIncoming, p1.length - buf.PARCEL_SIZE_SIZE);
- // buf.incomingWriteIndex should be ready to accept the last octet.
- equal(buf.incomingWriteIndex, p1.length);
-
- // Second, send the last octet of pA and whole pB. The Buf should now expand
- // to cover both pA & pB.
- let p2 = new Uint8Array(1 + pB.length);
- p2.set(pA.subarray(pA.length - 1), 0);
- p2.set(pB, 1);
- worker.onRILMessage(0, p2);
- // The parcels should have been both consumed.
- equal(buf.readAvailable, 0);
- // No parcel data remains.
- equal(buf.currentParcelSize, 0);
- // No parcel data remains.
- equal(buf.readIncoming, 0);
- // The Buf should now expand to cover both pA & pB.
- equal(buf.incomingWriteIndex, pA.length + pB.length);
-
- // end of incoming parcel's trip, let's do next test.
- run_next_test();
-});
-
-// Test Buf.readUint8Array.
-add_test_incoming_parcel(null,
- function test_buf_readUint8Array() {
- let buf = this.context.Buf;
-
- let u8array = buf.readUint8Array(1);
- equal(u8array instanceof Uint8Array, true);
- equal(u8array.length, 1);
- equal(buf.readAvailable, 3);
-
- u8array = buf.readUint8Array(2);
- equal(u8array.length, 2);
- equal(buf.readAvailable, 1);
-
- throws(function over_read_handler() {
- // reads more than parcel size, should throw an error.
- u8array = buf.readUint8Array(2);
- }, "Trying to read data beyond the parcel end!");
- }
-);
diff --git a/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js b/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js
deleted file mode 100644
index 335c0c403..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js
+++ /dev/null
@@ -1,234 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Helper function.
- */
-function newWorkerWithParcel(parcelBuf) {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let index = 0; // index for read
- let buf = parcelBuf;
-
- let context = worker.ContextPool._contexts[0];
- context.Buf.readUint8 = function() {
- return buf[index++];
- };
-
- context.Buf.readUint16 = function() {
- return buf[index++];
- };
-
- context.Buf.readInt32 = function() {
- return buf[index++];
- };
-
- context.Buf.seekIncoming = function(offset) {
- index += offset / context.Buf.UINT32_SIZE;
- };
-
- return worker;
-}
-
-// Test CDMA information record decoder.
-
-/**
- * Verify decoder for type DISPLAY
- */
-add_test(function test_display() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x00, // type: display
- 0x09, // length: 9
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x00]);
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].display, "Test Info");
-
- run_next_test();
-});
-
-/**
- * Verify decoder for type EXTENDED DISPLAY
- */
-add_test(function test_extended_display() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x07, // type: extended display
- 0x12, // length: 18
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x78, 0x74,
- 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x49, 0x6E,
- 0x66, 0x6F, 0x00, 0x00]);
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].display, "Test Extended Info");
-
- run_next_test();
-});
-
-/**
- * Verify decoder for mixed type
- */
-add_test(function test_mixed() {
- let worker = newWorkerWithParcel([
- 0x02, // two inforemation record
- 0x00, // type: display
- 0x0B, // length: 11
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x20, 0x31, 0x00,
- 0x07, // type: extended display
- 0x0B, // length: 11
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x20, 0x32, 0x00]);
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].display, "Test Info 1");
- equal(records[1].display, "Test Info 2");
-
- run_next_test();
-});
-
-/**
- * Verify decoder for multiple types
- */
-add_test(function test_multiple() {
- let worker = newWorkerWithParcel([
- 0x02, // two inforemation record
- 0x00, // type: display
- 0x0B, // length: 11
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x20, 0x31, 0x00,
- 0x00, // type: display
- 0x0B, // length: 11
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x20, 0x32, 0x00]);
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].display, "Test Info 1");
- equal(records[1].display, "Test Info 2");
-
- run_next_test();
-});
-
-/**
- * Verify decoder for Signal Type
- */
-add_test(function test_signal() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x04, // type: signal
- 0x01, // isPresent: non-zero
- 0x00, // signalType: Tone signal (00)
- 0x01, // alertPitch: High pitch
- 0x03]); // signal: Abbreviated intercept (000011)
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].signal.type, 0x00);
- equal(records[0].signal.alertPitch, 0x01);
- equal(records[0].signal.signal, 0x03);
-
- run_next_test();
-});
-
-/**
- * Verify decoder for Signal Type for Not Presented
- */
-add_test(function test_signal_not_present() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x04, // type: signal
- 0x00, // isPresent: zero
- 0x00, // signalType: Tone signal (00)
- 0x01, // alertPitch: High pitch
- 0x03]); // signal: Abbreviated intercept (000011)
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records.length, 0);
-
- run_next_test();
-});
-
-/**
- * Verify decoder for Line Control
- */
-add_test(function test_line_control() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x06, // type: line control
- 0x01, // polarity included
- 0x00, // not toggled
- 0x01, // reversed
- 0xFF]); // Power denial timeout: 255 * 5 ms
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].lineControl.polarityIncluded, 1);
- equal(records[0].lineControl.toggle, 0);
- equal(records[0].lineControl.reverse, 1);
- equal(records[0].lineControl.powerDenial, 255);
-
- run_next_test();
-});
-
-/**
- * Verify decoder for CLIR Cause
- */
-add_test(function test_clir() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x08, // type: clir
- 0x01]); // cause: Rejected by user
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].clirCause, 1);
-
- run_next_test();
-});
-
-/**
- * Verify decoder for Audio Control
- */
-add_test(function test_clir() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x0A, // type: audio control
- 0x01, // uplink
- 0xFF]); // downlink
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].audioControl.upLink, 1);
- equal(records[0].audioControl.downLink, 255);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js b/dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js
deleted file mode 100644
index d5645a3cf..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js
+++ /dev/null
@@ -1,470 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_ril_worker_cellbroadcast_activate() {
- let worker = newWorker({
- postRILMessage: function(id, parcel) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- let parcelTypes = [];
- let org_newParcel = context.Buf.newParcel;
- context.Buf.newParcel = function(type, options) {
- parcelTypes.push(type);
- org_newParcel.apply(this, arguments);
- };
-
- function setup(isCdma) {
- context.RIL._isCdma = isCdma;
- context.RIL.cellBroadcastDisabled = false;
- context.RIL.mergedCellBroadcastConfig = [1, 2, 4, 7]; // 1, 4-6
- parcelTypes = [];
- }
-
- function test(isCdma, expectedRequest) {
- setup(isCdma);
- context.RIL.setCellBroadcastDisabled({disabled: true});
- // Makesure that request parcel is sent out.
- notEqual(parcelTypes.indexOf(expectedRequest), -1);
- equal(context.RIL.cellBroadcastDisabled, true);
- }
-
- test(false, REQUEST_GSM_SMS_BROADCAST_ACTIVATION);
- test(true, REQUEST_CDMA_SMS_BROADCAST_ACTIVATION);
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_cellbroadcast_config() {
- let currentParcel;
- let worker = newWorker({
- postRILMessage: function(id, parcel) {
- currentParcel = parcel;
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- function U32ArrayFromParcelArray(pa) {
- do_print(pa);
- let out = [];
- for (let i = 0; i < pa.length; i += 4) {
- let data = pa[i] + (pa[i+1] << 8) + (pa[i+2] << 16) + (pa[i+3] << 24);
- out.push(data);
- }
- return out;
- }
-
- function test(isCdma, configs, expected) {
- let parcelType = isCdma ? REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG
- : REQUEST_GSM_SET_BROADCAST_SMS_CONFIG;
-
- let found = false;
- worker.postRILMessage = function(id, parcel) {
- let u32Parcel = U32ArrayFromParcelArray(Array.slice(parcel));
- if (u32Parcel[1] != parcelType) {
- return;
- }
-
- found = true;
- // Check parcel. Data start from 4th word (32bit)
- equal(u32Parcel.slice(3).toString(), expected);
- };
-
- context.RIL._isCdma = isCdma;
- context.RIL.setSmsBroadcastConfig(configs);
-
- // Makesure that request parcel is sent out.
- ok(found);
- }
-
- // (GSM) RIL writes the following data to outgoing parcel:
- // nums [(from, to, 0, 0xFF, 1), ... ]
- test(false,
- [1, 2, 4, 7] /* 1, 4-6 */,
- ["2", "1,1,0,255,1", "4,6,0,255,1"].join());
-
- // (CDMA) RIL writes the following data to outgoing parcel:
- // nums [(id, 0, 1), ... ]
- test(true,
- [1, 2, 4, 7] /* 1, 4-6 */,
- ["4", "1,0,1", "4,0,1", "5,0,1", "6,0,1"].join());
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_cellbroadcast_merge_config() {
- let worker = newWorker({
- postRILMessage: function(id, parcel) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- function test(isCdma, configs, expected) {
- context.RIL._isCdma = isCdma;
- context.RIL.cellBroadcastConfigs = configs;
- context.RIL._mergeAllCellBroadcastConfigs();
- equal(context.RIL.mergedCellBroadcastConfig.toString(), expected);
- }
-
- let configs = {
- MMI: [1, 2, 4, 7], // 1, 4-6
- CBMI: [6, 9], // 6-8
- CBMID: [8, 11], // 8-10
- CBMIR: [10, 13] // 10-12
- };
-
- test(false, configs, "1,2,4,13");
- test(true, configs, "1,2,4,7");
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_cellbroadcast_set_search_list() {
- let worker = newWorker({
- postRILMessage: function(id, parcel) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
-
- function test(aIsCdma, aSearchList, aExpected) {
- context.RIL._isCdma = aIsCdma;
-
- let options = { searchList: aSearchList };
- context.RIL.setCellBroadcastSearchList(options);
- // Enforce the MMI result to string for comparison.
- equal("" + context.RIL.cellBroadcastConfigs.MMI, aExpected);
- do_check_eq(options.errorMsg, undefined);
- }
-
- let searchListStr = "1,2,3,4";
- let searchList = { gsm: "1,2,3,4", cdma: "5,6,7,8" };
-
- test(false, searchListStr, "1,2,2,3,3,4,4,5");
- test(true, searchListStr, "1,2,2,3,3,4,4,5");
- test(false, searchList, "1,2,2,3,3,4,4,5");
- test(true, searchList, "5,6,6,7,7,8,8,9");
- test(false, null, "null");
- test(true, null, "null");
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_mergeCellBroadcastConfigs() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- function test(olist, from, to, expected) {
- let result = ril._mergeCellBroadcastConfigs(olist, from, to);
- equal(JSON.stringify(expected), JSON.stringify(result));
- }
-
- test(null, 0, 1, [0, 1]);
-
- test([10, 13], 7, 8, [ 7, 8, 10, 13]);
- test([10, 13], 7, 9, [ 7, 9, 10, 13]);
- test([10, 13], 7, 10, [ 7, 13]);
- test([10, 13], 7, 11, [ 7, 13]);
- test([10, 13], 7, 12, [ 7, 13]);
- test([10, 13], 7, 13, [ 7, 13]);
- test([10, 13], 7, 14, [ 7, 14]);
- test([10, 13], 7, 15, [ 7, 15]);
- test([10, 13], 7, 16, [ 7, 16]);
- test([10, 13], 8, 9, [ 8, 9, 10, 13]);
- test([10, 13], 8, 10, [ 8, 13]);
- test([10, 13], 8, 11, [ 8, 13]);
- test([10, 13], 8, 12, [ 8, 13]);
- test([10, 13], 8, 13, [ 8, 13]);
- test([10, 13], 8, 14, [ 8, 14]);
- test([10, 13], 8, 15, [ 8, 15]);
- test([10, 13], 8, 16, [ 8, 16]);
- test([10, 13], 9, 10, [ 9, 13]);
- test([10, 13], 9, 11, [ 9, 13]);
- test([10, 13], 9, 12, [ 9, 13]);
- test([10, 13], 9, 13, [ 9, 13]);
- test([10, 13], 9, 14, [ 9, 14]);
- test([10, 13], 9, 15, [ 9, 15]);
- test([10, 13], 9, 16, [ 9, 16]);
- test([10, 13], 10, 11, [10, 13]);
- test([10, 13], 10, 12, [10, 13]);
- test([10, 13], 10, 13, [10, 13]);
- test([10, 13], 10, 14, [10, 14]);
- test([10, 13], 10, 15, [10, 15]);
- test([10, 13], 10, 16, [10, 16]);
- test([10, 13], 11, 12, [10, 13]);
- test([10, 13], 11, 13, [10, 13]);
- test([10, 13], 11, 14, [10, 14]);
- test([10, 13], 11, 15, [10, 15]);
- test([10, 13], 11, 16, [10, 16]);
- test([10, 13], 12, 13, [10, 13]);
- test([10, 13], 12, 14, [10, 14]);
- test([10, 13], 12, 15, [10, 15]);
- test([10, 13], 12, 16, [10, 16]);
- test([10, 13], 13, 14, [10, 14]);
- test([10, 13], 13, 15, [10, 15]);
- test([10, 13], 13, 16, [10, 16]);
- test([10, 13], 14, 15, [10, 13, 14, 15]);
- test([10, 13], 14, 16, [10, 13, 14, 16]);
- test([10, 13], 15, 16, [10, 13, 15, 16]);
-
- test([10, 13, 14, 17], 7, 8, [ 7, 8, 10, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 9, [ 7, 9, 10, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 10, [ 7, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 11, [ 7, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 12, [ 7, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 13, [ 7, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 14, [ 7, 17]);
- test([10, 13, 14, 17], 7, 15, [ 7, 17]);
- test([10, 13, 14, 17], 7, 16, [ 7, 17]);
- test([10, 13, 14, 17], 7, 17, [ 7, 17]);
- test([10, 13, 14, 17], 7, 18, [ 7, 18]);
- test([10, 13, 14, 17], 7, 19, [ 7, 19]);
- test([10, 13, 14, 17], 8, 9, [ 8, 9, 10, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 10, [ 8, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 11, [ 8, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 12, [ 8, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 13, [ 8, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 14, [ 8, 17]);
- test([10, 13, 14, 17], 8, 15, [ 8, 17]);
- test([10, 13, 14, 17], 8, 16, [ 8, 17]);
- test([10, 13, 14, 17], 8, 17, [ 8, 17]);
- test([10, 13, 14, 17], 8, 18, [ 8, 18]);
- test([10, 13, 14, 17], 8, 19, [ 8, 19]);
- test([10, 13, 14, 17], 9, 10, [ 9, 13, 14, 17]);
- test([10, 13, 14, 17], 9, 11, [ 9, 13, 14, 17]);
- test([10, 13, 14, 17], 9, 12, [ 9, 13, 14, 17]);
- test([10, 13, 14, 17], 9, 13, [ 9, 13, 14, 17]);
- test([10, 13, 14, 17], 9, 14, [ 9, 17]);
- test([10, 13, 14, 17], 9, 15, [ 9, 17]);
- test([10, 13, 14, 17], 9, 16, [ 9, 17]);
- test([10, 13, 14, 17], 9, 17, [ 9, 17]);
- test([10, 13, 14, 17], 9, 18, [ 9, 18]);
- test([10, 13, 14, 17], 9, 19, [ 9, 19]);
- test([10, 13, 14, 17], 10, 11, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 10, 12, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 10, 13, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 10, 14, [10, 17]);
- test([10, 13, 14, 17], 10, 15, [10, 17]);
- test([10, 13, 14, 17], 10, 16, [10, 17]);
- test([10, 13, 14, 17], 10, 17, [10, 17]);
- test([10, 13, 14, 17], 10, 18, [10, 18]);
- test([10, 13, 14, 17], 10, 19, [10, 19]);
- test([10, 13, 14, 17], 11, 12, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 11, 13, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 11, 14, [10, 17]);
- test([10, 13, 14, 17], 11, 15, [10, 17]);
- test([10, 13, 14, 17], 11, 16, [10, 17]);
- test([10, 13, 14, 17], 11, 17, [10, 17]);
- test([10, 13, 14, 17], 11, 18, [10, 18]);
- test([10, 13, 14, 17], 11, 19, [10, 19]);
- test([10, 13, 14, 17], 12, 13, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 12, 14, [10, 17]);
- test([10, 13, 14, 17], 12, 15, [10, 17]);
- test([10, 13, 14, 17], 12, 16, [10, 17]);
- test([10, 13, 14, 17], 12, 17, [10, 17]);
- test([10, 13, 14, 17], 12, 18, [10, 18]);
- test([10, 13, 14, 17], 12, 19, [10, 19]);
- test([10, 13, 14, 17], 13, 14, [10, 17]);
- test([10, 13, 14, 17], 13, 15, [10, 17]);
- test([10, 13, 14, 17], 13, 16, [10, 17]);
- test([10, 13, 14, 17], 13, 17, [10, 17]);
- test([10, 13, 14, 17], 13, 18, [10, 18]);
- test([10, 13, 14, 17], 13, 19, [10, 19]);
- test([10, 13, 14, 17], 14, 15, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 14, 16, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 14, 17, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 14, 18, [10, 13, 14, 18]);
- test([10, 13, 14, 17], 14, 19, [10, 13, 14, 19]);
- test([10, 13, 14, 17], 15, 16, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 15, 17, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 15, 18, [10, 13, 14, 18]);
- test([10, 13, 14, 17], 15, 19, [10, 13, 14, 19]);
- test([10, 13, 14, 17], 16, 17, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 16, 18, [10, 13, 14, 18]);
- test([10, 13, 14, 17], 16, 19, [10, 13, 14, 19]);
- test([10, 13, 14, 17], 17, 18, [10, 13, 14, 18]);
- test([10, 13, 14, 17], 17, 19, [10, 13, 14, 19]);
- test([10, 13, 14, 17], 18, 19, [10, 13, 14, 17, 18, 19]);
-
- test([10, 13, 16, 19], 7, 14, [ 7, 14, 16, 19]);
- test([10, 13, 16, 19], 7, 15, [ 7, 15, 16, 19]);
- test([10, 13, 16, 19], 7, 16, [ 7, 19]);
- test([10, 13, 16, 19], 8, 14, [ 8, 14, 16, 19]);
- test([10, 13, 16, 19], 8, 15, [ 8, 15, 16, 19]);
- test([10, 13, 16, 19], 8, 16, [ 8, 19]);
- test([10, 13, 16, 19], 9, 14, [ 9, 14, 16, 19]);
- test([10, 13, 16, 19], 9, 15, [ 9, 15, 16, 19]);
- test([10, 13, 16, 19], 9, 16, [ 9, 19]);
- test([10, 13, 16, 19], 10, 14, [10, 14, 16, 19]);
- test([10, 13, 16, 19], 10, 15, [10, 15, 16, 19]);
- test([10, 13, 16, 19], 10, 16, [10, 19]);
- test([10, 13, 16, 19], 11, 14, [10, 14, 16, 19]);
- test([10, 13, 16, 19], 11, 15, [10, 15, 16, 19]);
- test([10, 13, 16, 19], 11, 16, [10, 19]);
- test([10, 13, 16, 19], 12, 14, [10, 14, 16, 19]);
- test([10, 13, 16, 19], 12, 15, [10, 15, 16, 19]);
- test([10, 13, 16, 19], 12, 16, [10, 19]);
- test([10, 13, 16, 19], 13, 14, [10, 14, 16, 19]);
- test([10, 13, 16, 19], 13, 15, [10, 15, 16, 19]);
- test([10, 13, 16, 19], 13, 16, [10, 19]);
- test([10, 13, 16, 19], 14, 15, [10, 13, 14, 15, 16, 19]);
- test([10, 13, 16, 19], 14, 16, [10, 13, 14, 19]);
- test([10, 13, 16, 19], 15, 16, [10, 13, 15, 19]);
-
- run_next_test();
-});
-
-add_test(function test_ril_consts_cellbroadcast_misc() {
- // Must be 16 for indexing.
- equal(CB_DCS_LANG_GROUP_1.length, 16);
- equal(CB_DCS_LANG_GROUP_2.length, 16);
-
- // Array length must be even.
- equal(CB_NON_MMI_SETTABLE_RANGES.length & 0x01, 0);
- for (let i = 0; i < CB_NON_MMI_SETTABLE_RANGES.length;) {
- let from = CB_NON_MMI_SETTABLE_RANGES[i++];
- let to = CB_NON_MMI_SETTABLE_RANGES[i++];
- equal(from < to, true);
- }
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_checkCellBroadcastMMISettable() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- function test(from, to, expected) {
- equal(expected, ril._checkCellBroadcastMMISettable(from, to));
- }
-
- test(-2, -1, false);
- test(-1, 0, false);
- test(0, 1, true);
- test(1, 1, false);
- test(2, 1, false);
- test(65536, 65537, false);
-
- // We have both [4096, 4224), [4224, 4352), so it's actually [4096, 4352),
- // and [61440, 65536), [65535, 65536), so it's actually [61440, 65536).
- for (let i = 0; i < CB_NON_MMI_SETTABLE_RANGES.length;) {
- let from = CB_NON_MMI_SETTABLE_RANGES[i++];
- let to = CB_NON_MMI_SETTABLE_RANGES[i++];
- if ((from != 4224) && (from != 65535)) {
- test(from - 1, from, true);
- }
- test(from - 1, from + 1, false);
- test(from - 1, to, false);
- test(from - 1, to + 1, false);
- test(from, from + 1, false);
- test(from, to, false);
- test(from, to + 1, false);
- if ((from + 1) < to) {
- test(from + 1, to, false);
- test(from + 1, to + 1, false);
- }
- if ((to != 4224) && (to < 65535)) {
- test(to, to + 1, true);
- test(to + 1, to + 2, true);
- }
- }
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_CellBroadcastDisabled() {
- let count = 0;
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- if (message.rilMessageType == "cellbroadcast-received") {
- ok(true, "cellbroadcast-received: " + JSON.stringify(message));
- count++;
- }
- }
- });
-
- function buildPdu(aMessageId) {
- return "C002" + aMessageId + "011154741914AFA7C76B9058" +
- "FEBEBB41E6371EA4AEB7E173D0DB5E96" +
- "83E8E832881DD6E741E4F7B9D168341A" +
- "8D46A3D168341A8D46A3D168341A8D46" +
- "A3D168341A8D46A3D168341A8D46A3D1" +
- "68341A8D46A3D100";
- }
-
- worker.ContextPool._contexts[0].RIL.cellBroadcastDisabled = true;
-
- let networkAlertIds = [
- "1100", "1107", // ETWS
- "1112", "112F", // CMAS
- "1130", "18FF", // PWS
- ];
- networkAlertIds.forEach(aMessageId => {
- worker.onRILMessage(
- 0,
- newIncomingParcel(
- -1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(buildPdu(aMessageId))));
- });
- equal(count, networkAlertIds.length, "Alerts shall not be ignored.");
-
- count = 0;
- let normalMsgIds = [ "0000", "03E7", "1108", "1901" ];
- normalMsgIds.forEach(aMessageId => {
- worker.onRILMessage(
- 0,
- newIncomingParcel(
- -1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(buildPdu(aMessageId))));
- });
- equal(count, 0, "Normal messages shall be ignored.");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_gsm.js b/dom/system/gonk/tests/test_ril_worker_cellbroadcast_gsm.js
deleted file mode 100644
index b08b64135..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_gsm.js
+++ /dev/null
@@ -1,230 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_ril_worker_GsmPDUHelper_readCbDataCodingScheme() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- function test_dcs(dcs, encoding, language, hasLanguageIndicator, messageClass) {
- context.Buf.readUint8 = function() {
- return dcs;
- };
-
- let msg = {};
- context.GsmPDUHelper.readCbDataCodingScheme(msg);
-
- equal(msg.dcs, dcs);
- equal(msg.encoding, encoding);
- equal(msg.language, language);
- equal(msg.hasLanguageIndicator, hasLanguageIndicator);
- equal(msg.messageClass, messageClass);
- }
-
- function test_dcs_throws(dcs) {
- context.Buf.readUint8 = function() {
- return dcs;
- };
-
- throws(function() {
- context.GsmPDUHelper.readCbDataCodingScheme({});
- }, "Unsupported CBS data coding scheme: " + dcs);
- }
-
- // Group 0000
- for (let i = 0; i < 16; i++) {
- test_dcs(i, PDU_DCS_MSG_CODING_7BITS_ALPHABET, CB_DCS_LANG_GROUP_1[i],
- false, GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- }
-
- // Group 0001
- // 0000 GSM 7 bit default alphabet; message preceded by language indication.
- test_dcs(0x10, PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, true,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- // 0001 UCS2; message preceded by language indication.
- test_dcs(0x11, PDU_DCS_MSG_CODING_16BITS_ALPHABET, null, true,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
-
- // Group 0010
- // 0000..0100
- for (let i = 0; i < 5; i++) {
- test_dcs(0x20 + i, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- CB_DCS_LANG_GROUP_2[i], false,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- }
- // 0101..1111 Reserved
- for (let i = 5; i < 16; i++) {
- test_dcs(0x20 + i, PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, false,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- }
-
- // Group 0100, 0101, 1001
- for (let group of [0x40, 0x50, 0x90]) {
- for (let i = 0; i < 16; i++) {
- let encoding = i & 0x0C;
- if (encoding == 0x0C) {
- encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- }
- let messageClass = GECKO_SMS_MESSAGE_CLASSES[i & PDU_DCS_MSG_CLASS_BITS];
- test_dcs(group + i, encoding, null, false, messageClass);
- }
- }
-
- // Group 1111
- for (let i = 0; i < 16; i ++) {
- let encoding = i & 0x04 ? PDU_DCS_MSG_CODING_8BITS_ALPHABET
- : PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- let messageClass;
- switch(i & PDU_DCS_MSG_CLASS_BITS) {
- case 0x01: messageClass = PDU_DCS_MSG_CLASS_USER_1; break;
- case 0x02: messageClass = PDU_DCS_MSG_CLASS_USER_2; break;
- case 0x03: messageClass = PDU_DCS_MSG_CLASS_3; break;
- default: messageClass = PDU_DCS_MSG_CLASS_NORMAL; break;
- }
- test_dcs(0xF0 + i, encoding, null, false,
- GECKO_SMS_MESSAGE_CLASSES[messageClass]);
- }
-
- // Group 0011, 1000, 1010, 1011, 1100
- // 0000..1111 Reserved
- for (let group of [0x30, 0x80, 0xA0, 0xB0, 0xC0]) {
- for (let i = 0; i < 16; i++) {
- test_dcs(group + i, PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, false,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- }
- }
-
- // Group 0110, 0111, 1101, 1110
- // TODO: unsupported
- for (let group of [0x60, 0x70, 0xD0, 0xE0]) {
- for (let i = 0; i < 16; i++) {
- test_dcs_throws(group + i);
- }
- }
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_GsmPDUHelper_readGsmCbData() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- function test_data(options, expected) {
- let readIndex = 0;
- context.Buf.readUint8 = function() {
- return options[3][readIndex++];
- };
- context.Buf.readUint8Array = function(length) {
- let array = new Uint8Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = this.readUint8();
- }
- return array;
- };
-
- let msg = {
- encoding: options[0],
- language: options[1],
- hasLanguageIndicator: options[2]
- };
- context.GsmPDUHelper.readGsmCbData(msg, options[3].length);
-
- equal(msg.body, expected[0]);
- equal(msg.data == null, expected[1] == null);
- if (expected[1] != null) {
- equal(msg.data.length, expected[1].length);
- for (let i = 0; i < expected[1].length; i++) {
- equal(msg.data[i], expected[1][i]);
- }
- }
- equal(msg.language, expected[2]);
- }
-
- // We're testing Cell Broadcast message body with all zeros octet stream. As
- // shown in 3GPP TS 23.038, septet 0x00 will be decoded as '@' when both
- // langTableIndex and langShiftTableIndex equal to
- // PDU_DCS_MSG_CODING_7BITS_ALPHABET.
-
- // PDU_DCS_MSG_CODING_7BITS_ALPHABET
- test_data([PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, false,
- [0]],
- ["@", null, null]);
- test_data([PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, true,
- [0, 0, 0, 0]],
- ["@", null, "@@"]);
- test_data([PDU_DCS_MSG_CODING_7BITS_ALPHABET, "@@", false,
- [0]],
- ["@", null, "@@"]);
-
- // PDU_DCS_MSG_CODING_8BITS_ALPHABET
- test_data([PDU_DCS_MSG_CODING_8BITS_ALPHABET, null, false,
- [0]],
- [null, [0], null]);
-
- // PDU_DCS_MSG_CODING_16BITS_ALPHABET
- test_data([PDU_DCS_MSG_CODING_16BITS_ALPHABET, null, false,
- [0x00, 0x40]],
- ["@", null, null]);
- test_data([PDU_DCS_MSG_CODING_16BITS_ALPHABET, null, true,
- [0x00, 0x00, 0x00, 0x40]],
- ["@", null, "@@"]);
- test_data([PDU_DCS_MSG_CODING_16BITS_ALPHABET, "@@", false,
- [0x00, 0x40]],
- ["@", null, "@@"]);
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_Sim_Download_Message() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- ok(message.rilMessageType !== "cellbroadcast-received",
- "Data-Download message shall be ignored.");
- }
- });
-
- function buildPdu(aMessageId) {
- return "C002" + aMessageId + "011154741914AFA7C76B9058" +
- "FEBEBB41E6371EA4AEB7E173D0DB5E96" +
- "83E8E832881DD6E741E4F7B9D168341A" +
- "8D46A3D168341A8D46A3D168341A8D46" +
- "A3D168341A8D46A3D168341A8D46A3D1" +
- "68341A8D46A3D100";
- }
-
- ["1000", "107F", "1080", "10FF"].forEach(aMessageId => {
- worker.onRILMessage(
- 0,
- newIncomingParcel(
- -1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(buildPdu(aMessageId))));
- });
-
- ok(true, "All Data-Download Messages are ingored.");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_umts.js b/dom/system/gonk/tests/test_ril_worker_cellbroadcast_umts.js
deleted file mode 100644
index 0380c4122..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_umts.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-function buildHexStr(aNum, aNumSemiOctets) {
- let str = aNum.toString(16);
- while (str.length < aNumSemiOctets) {
- str = "0" + str;
- }
- return str;
-}
-
-/**
- * Verify GsmPDUHelper#readUmtsCbMessage with numOfPages from 1 to 15.
- */
-add_test(function test_GsmPDUHelper_readUmtsCbMessage_MultiParts() {
- let CB_UMTS_MESSAGE_PAGE_SIZE = 82;
- let CB_MAX_CONTENT_PER_PAGE_7BIT = 93;
- let workerHelper = newInterceptWorker(),
- worker = workerHelper.worker,
- context = worker.ContextPool._contexts[0],
- GsmPDUHelper = context.GsmPDUHelper;
-
- function test_MultiParts(aNumOfPages) {
- let pdu = buildHexStr(CB_UMTS_MESSAGE_TYPE_CBS, 2) // msg_type
- + buildHexStr(0, 4) // skip msg_id
- + buildHexStr(0, 4) // skip SN
- + buildHexStr(0, 2) // skip dcs
- + buildHexStr(aNumOfPages, 2); // set num_of_pages
- for (let i = 1; i <= aNumOfPages; i++) {
- pdu = pdu + buildHexStr(0, CB_UMTS_MESSAGE_PAGE_SIZE * 2)
- + buildHexStr(CB_UMTS_MESSAGE_PAGE_SIZE, 2); // msg_info_length
- }
-
- worker.onRILMessage(0, newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(pdu)));
-
- let postedMessage = workerHelper.postedMessage;
- equal("cellbroadcast-received", postedMessage.rilMessageType);
- equal(postedMessage.fullBody.length,
- aNumOfPages * CB_MAX_CONTENT_PER_PAGE_7BIT);
- }
-
- [1, 5, 15].forEach(function(i) {
- test_MultiParts(i);
- });
-
- run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper#readUmtsCbMessage with 8bit encoded.
- */
-add_test(function test_GsmPDUHelper_readUmtsCbMessage_Binary() {
- let CB_UMTS_MESSAGE_PAGE_SIZE = 82;
- let CB_MAX_CONTENT_PER_PAGE_7BIT = 93;
- let TEXT_BINARY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFF";
- let workerHelper = newInterceptWorker(),
- worker = workerHelper.worker,
- context = worker.ContextPool._contexts[0],
- GsmPDUHelper = context.GsmPDUHelper;
-
- function test_MultiPartsBinary(aNumOfPages) {
- let pdu = buildHexStr(CB_UMTS_MESSAGE_TYPE_CBS, 2) // msg_type
- + buildHexStr(0, 4) // skip msg_id
- + buildHexStr(0, 4) // skip SN
- + buildHexStr(68, 2) // set DCS to 8bit data
- + buildHexStr(aNumOfPages, 2); // set num_of_pages
- for (let i = 1; i <= aNumOfPages; i++) {
- pdu = pdu + TEXT_BINARY
- + buildHexStr(CB_UMTS_MESSAGE_PAGE_SIZE, 2); // msg_info_length
- }
-
- worker.onRILMessage(0, newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(pdu)));
-
- let postedMessage = workerHelper.postedMessage;
- equal("cellbroadcast-received", postedMessage.rilMessageType);
- equal(postedMessage.fullData.length,
- aNumOfPages * CB_UMTS_MESSAGE_PAGE_SIZE);
- for (let i = 0; i < postedMessage.fullData.length; i++) {
- equal(postedMessage.fullData[i], 255);
- }
- }
-
- [1, 5, 15].forEach(function(i) {
- test_MultiPartsBinary(i);
- });
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cf.js b/dom/system/gonk/tests/test_ril_worker_cf.js
deleted file mode 100644
index b8db716b7..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cf.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-function toaFromString(number) {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
- return context.RIL._toaFromString(number);
-}
-
-add_test(function test_toaFromString_empty() {
- let retval = toaFromString("");
-
- equal(retval, TOA_UNKNOWN);
-
- run_next_test();
-});
-
-add_test(function test_toaFromString_undefined() {
- let retval = toaFromString();
-
- equal(retval, TOA_UNKNOWN);
-
- run_next_test();
-});
-
-add_test(function test_toaFromString_unknown() {
- let retval = toaFromString("666222333");
-
- equal(retval, TOA_UNKNOWN);
-
- run_next_test();
-});
-
-add_test(function test_toaFromString_international() {
- let retval = toaFromString("+34666222333");
-
- equal(retval, TOA_INTERNATIONAL);
-
- run_next_test();
-});
-
-add_test(function test_setCallForward_unconditional() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCallForward = function fakeSetCallForward(options) {
- context.RIL[REQUEST_SET_CALL_FORWARD](0, {});
- };
-
- context.RIL.setCallForward({
- action: CALL_FORWARD_ACTION_REGISTRATION,
- reason: CALL_FORWARD_REASON_UNCONDITIONAL,
- serviceClass: ICC_SERVICE_CLASS_VOICE,
- number: "666222333",
- timeSeconds: 10
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
-
- run_next_test();
-});
-
-add_test(function test_queryCallForwardStatus_unconditional() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCallForward = function fakeSetCallForward(options) {
- context.RIL[REQUEST_SET_CALL_FORWARD](0, {});
- };
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.Buf.readString = function fakeReadString() {
- return "+34666222333";
- };
-
- context.RIL.queryCallForwardStatus = function fakeQueryCallForward(options) {
- context.Buf.int32Array = [
- 0, // rules.timeSeconds
- 145, // rules.toa
- 49, // rules.serviceClass
- CALL_FORWARD_REASON_UNCONDITIONAL, // rules.reason
- 1, // rules.active
- 1 // rulesLength
- ];
- context.RIL[REQUEST_QUERY_CALL_FORWARD_STATUS](1, {});
- };
-
- context.RIL.queryCallForwardStatus({
- action: CALL_FORWARD_ACTION_QUERY_STATUS,
- reason: CALL_FORWARD_REASON_UNCONDITIONAL,
- serviceClass: ICC_SERVICE_CLASS_VOICE,
- number: "666222333",
- timeSeconds: 10
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- ok(Array.isArray(postedMessage.rules));
- do_print(postedMessage.rules.length);
- equal(postedMessage.rules.length, 1);
- ok(postedMessage.rules[0].active);
- equal(postedMessage.rules[0].reason, CALL_FORWARD_REASON_UNCONDITIONAL);
- equal(postedMessage.rules[0].number, "+34666222333");
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_clip.js b/dom/system/gonk/tests/test_ril_worker_clip.js
deleted file mode 100644
index d1ce5f617..000000000
--- a/dom/system/gonk/tests/test_ril_worker_clip.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_queryCLIP_provisioned() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.queryCLIP = function fakeQueryCLIP(options) {
- context.Buf.int32Array = [
- 1, // CLIP provisioned.
- 1 // Length.
- ];
- context.RIL[REQUEST_QUERY_CLIP](1, {});
- };
-
- context.RIL.queryCLIP({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- equal(postedMessage.provisioned, 1);
- run_next_test();
-});
-
-add_test(function test_getCLIP_error_generic_failure_invalid_length() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.queryCLIP = function fakeQueryCLIP(options) {
- context.Buf.int32Array = [
- 1, // CLIP provisioned.
- 0 // Length.
- ];
- context.RIL[REQUEST_QUERY_CLIP](1, {});
- };
-
- context.RIL.queryCLIP({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_clir.js b/dom/system/gonk/tests/test_ril_worker_clir.js
deleted file mode 100644
index 5882a3c4c..000000000
--- a/dom/system/gonk/tests/test_ril_worker_clir.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-// Calling line identification restriction constants.
-
-// Uses subscription default value.
-const CLIR_DEFAULT = 0;
-// Restricts CLI presentation.
-const CLIR_INVOCATION = 1;
-// Allows CLI presentation.
-const CLIR_SUPPRESSION = 2;
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_setCLIR_success() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCLIR = function fakeSetCLIR(options) {
- context.RIL[REQUEST_SET_CLIR](0, {
- rilMessageType: "setCLIR"
- });
- };
-
- context.RIL.setCLIR({
- clirMode: CLIR_DEFAULT
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
-
- run_next_test();
-});
-
-add_test(function test_setCLIR_generic_failure() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCLIR = function fakeSetCLIR(options) {
- context.RIL[REQUEST_SET_CLIR](0, {
- rilMessageType: "setCLIR",
- errorMsg: GECKO_ERROR_GENERIC_FAILURE
- });
- };
-
- context.RIL.setCLIR({
- clirMode: CLIR_DEFAULT
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
-
- run_next_test();
-});
-
-add_test(function test_getCLIR_n0_m1() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.getCLIR = function fakeGetCLIR(options) {
- context.Buf.int32Array = [
- 1, // Presentation indicator is used according to the subscription
- // of the CLIR service.
- 0, // CLIR provisioned in permanent mode.
- 2 // Length.
- ];
- context.RIL[REQUEST_GET_CLIR](1, {
- rilMessageType: "setCLIR"
- });
- };
-
- context.RIL.getCLIR({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- equal(postedMessage.n, 0);
- equal(postedMessage.m, 1);
- run_next_test();
-});
-
-add_test(function test_getCLIR_error_generic_failure_invalid_length() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.getCLIR = function fakeGetCLIR(options) {
- context.Buf.int32Array = [
- 1, // Presentation indicator is used according to the subscription
- // of the CLIR service.
- 0, // CLIR provisioned in permanent mode.
- 0 // Length (invalid one).
- ];
- context.RIL[REQUEST_GET_CLIR](1, {
- rilMessageType: "setCLIR"
- });
- };
-
- context.RIL.getCLIR({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cw.js b/dom/system/gonk/tests/test_ril_worker_cw.js
deleted file mode 100644
index efa8b5c21..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cw.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_setCallWaiting_success() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
- context.RIL[REQUEST_SET_CALL_WAITING](0, {});
- };
-
- context.RIL.setCallWaiting({
- enabled: true
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
-
- run_next_test();
-});
-
-add_test(function test_setCallWaiting_generic_failure() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
- context.RIL[REQUEST_SET_CALL_WAITING](0, {
- errorMsg: GECKO_ERROR_GENERIC_FAILURE
- });
- };
-
- context.RIL.setCallWaiting({
- enabled: true
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
-
- run_next_test();
-});
-
-add_test(function test_queryCallWaiting_success_enabled_true() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
- context.Buf.int32Array = [
- 1, // serviceClass
- 1, // enabled
- 2 // length
- ];
- context.RIL[REQUEST_QUERY_CALL_WAITING](1, {});
- };
-
- context.RIL.queryCallWaiting({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- equal(postedMessage.serviceClass, 1);
- run_next_test();
-});
-
-add_test(function test_queryCallWaiting_success_enabled_false() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
- context.Buf.int32Array = [
- 1, // serviceClass
- 0, // enabled
- 2 // length
- ];
- context.RIL[REQUEST_QUERY_CALL_WAITING](1, {});
- };
-
- context.RIL.queryCallWaiting({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- equal(postedMessage.serviceClass, ICC_SERVICE_CLASS_NONE);
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_ecm.js b/dom/system/gonk/tests/test_ril_worker_ecm.js
deleted file mode 100644
index d10cba9ec..000000000
--- a/dom/system/gonk/tests/test_ril_worker_ecm.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-var timeoutCallback = null;
-var timeoutDelayMs = 0;
-const TIMER_ID = 1234;
-const TIMEOUT_VALUE = 300000; // 5 mins.
-
-// No window in xpcshell-test. Create our own timer mechanism.
-
-function setTimeout(callback, timeoutMs) {
- timeoutCallback = callback;
- timeoutDelayMs = timeoutMs;
- equal(timeoutMs, TIMEOUT_VALUE);
- return TIMER_ID;
-}
-
-function clearTimeout(timeoutId) {
- equal(timeoutId, TIMER_ID);
- timeoutCallback = null;
-}
-
-function fireTimeout() {
- notEqual(timeoutCallback, null);
- if (timeoutCallback) {
- timeoutCallback();
- timeoutCallback = null;
- }
-}
-
-add_test(function test_enter_emergencyCbMode() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- // Do it twice. Should always send the event.
- for (let i = 0; i < 2; ++i) {
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- let postedMessage = workerHelper.postedMessage;
-
- // Should store the mode.
- equal(context.RIL._isInEmergencyCbMode, true);
-
- // Should notify change.
- equal(postedMessage.rilMessageType, "emergencyCbModeChange");
- equal(postedMessage.active, true);
- equal(postedMessage.timeoutMs, TIMEOUT_VALUE);
-
- // Should start timer.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
- }
-
- run_next_test();
-});
-
-add_test(function test_exit_emergencyCbMode() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- context.RIL[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE]();
- let postedMessage = workerHelper.postedMessage;
-
- // Should store the mode.
- equal(context.RIL._isInEmergencyCbMode, false);
-
- // Should notify change.
- equal(postedMessage.rilMessageType, "emergencyCbModeChange");
- equal(postedMessage.active, false);
-
- // Should clear timer.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, null);
-
- run_next_test();
-});
-
-add_test(function test_request_exit_emergencyCbMode_when_timeout() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- equal(context.RIL._isInEmergencyCbMode, true);
- equal(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
-
- let parcelTypes = [];
- context.Buf.newParcel = function(type, options) {
- parcelTypes.push(type);
- };
-
- // Timeout.
- fireTimeout();
-
- // Should clear timeout event.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, null);
-
- // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
- notEqual(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
-
- run_next_test();
-});
-
-add_test(function test_request_exit_emergencyCbMode_when_dial() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- equal(context.RIL._isInEmergencyCbMode, true);
- equal(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
-
- let parcelTypes = [];
- context.Buf.newParcel = function(type, options) {
- parcelTypes.push(type);
- };
-
- // Dial non-emergency call.
- context.RIL.dial({number: "0912345678",
- isEmergency: false,
- isDialEmergency: false});
-
- // Should clear timeout event.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, null);
-
- // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
- notEqual(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
-
- run_next_test();
-});
-
-add_test(function test_request_exit_emergencyCbMode_explicitly() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- equal(context.RIL._isInEmergencyCbMode, true);
- equal(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
-
- let parcelTypes = [];
- context.Buf.newParcel = function(type, options) {
- parcelTypes.push(type);
- };
-
- context.RIL.handleChromeMessage({rilMessageType: "exitEmergencyCbMode"});
- context.RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE](1, {
- rilMessageType: "exitEmergencyCbMode"
- });
- let postedMessage = workerHelper.postedMessage;
-
- // Should clear timeout event.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, null);
-
- // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
- notEqual(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
-
- // Send back the response.
- equal(postedMessage.rilMessageType, "exitEmergencyCbMode");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js
deleted file mode 100644
index 89fcd874d..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-// Test ICC_COMMAND_GET_RESPONSE with FCP template format.
-/**
- * Verify transparent structure with FCP template format.
- */
-add_test(function test_fcp_template_for_transparent_structure() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
-
- let tag_test = [
- 0x62,
- 0x22,
- 0x82, 0x02, 0x41, 0x21,
- 0x83, 0x02, 0x2F, 0xE2,
- 0xA5, 0x09, 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00,
- 0x8A, 0x01, 0x05,
- 0x8B, 0x03, 0x2F, 0x06, 0x0B,
- 0x80, 0x02, 0x00, 0x0A,
- 0x88, 0x01, 0x10];
-
- for (let i = 0; i < tag_test.length; i++) {
- pduHelper.writeHexOctet(tag_test[i]);
- }
-
- let berTlv = berHelper.decode(tag_test.length);
- let iter = berTlv.value.values();
- let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
- equal(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_STRUCTURE_TRANSPARENT]);
-
- tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
- equal(tlv.value.fileId, 0x2FE2);
-
- tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
- equal(tlv.value.fileSizeData, 0x0A);
-
- run_next_test();
-});
-
-/**
- * Verify linear fixed structure with FCP template format.
- */
-add_test(function test_fcp_template_for_linear_fixed_structure() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
-
- let tag_test = [
- 0x62,
- 0x1E,
- 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01,
- 0x83, 0x02, 0x6F, 0x40,
- 0xA5, 0x03, 0x92, 0x01, 0x00,
- 0x8A, 0x01, 0x07,
- 0x8B, 0x03, 0x6F, 0x06, 0x02,
- 0x80, 0x02, 0x00, 0x1A,
- 0x88, 0x00];
-
- for (let i = 0; i < tag_test.length; i++) {
- pduHelper.writeHexOctet(tag_test[i]);
- }
-
- let berTlv = berHelper.decode(tag_test.length);
- let iter = berTlv.value.values();
- let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
- equal(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_STRUCTURE_LINEAR_FIXED]);
- equal(tlv.value.recordLength, 0x1A);
- equal(tlv.value.numOfRecords, 0x01);
-
- tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
- equal(tlv.value.fileId, 0x6F40);
-
- tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
- equal(tlv.value.fileSizeData, 0x1A);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js b/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js
deleted file mode 100644
index dc7eb93b9..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js
+++ /dev/null
@@ -1,282 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify RIL.iccGetCardLockEnabled
- */
-add_test(function test_icc_get_card_lock_enabled() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let ril = context.RIL;
- ril.aid = "123456789";
-
- function do_test(aLock) {
- const serviceClass = ICC_SERVICE_CLASS_VOICE |
- ICC_SERVICE_CLASS_DATA |
- ICC_SERVICE_CLASS_FAX;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), REQUEST_QUERY_FACILITY_LOCK)
-
- // Token : we don't care.
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 4);
- equal(parcel[0], GECKO_CARDLOCK_TO_FACILITY[aLock]);
- equal(parcel[1], "");
- equal(parcel[2], serviceClass.toString());
- equal(parcel[3], ril.aid);
- };
-
- ril.iccGetCardLockEnabled({lockType: aLock});
- }
-
- do_test(GECKO_CARDLOCK_PIN)
- do_test(GECKO_CARDLOCK_FDN)
-
- run_next_test();
-});
-
-add_test(function test_path_id_for_spid_and_spn() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }});
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ICCFileHelper = context.ICCFileHelper;
-
- // Test SIM
- RIL.appType = CARD_APPTYPE_SIM;
- equal(ICCFileHelper.getEFPath(ICC_EF_SPDI),
- EF_PATH_MF_SIM + EF_PATH_DF_GSM);
- equal(ICCFileHelper.getEFPath(ICC_EF_SPN),
- EF_PATH_MF_SIM + EF_PATH_DF_GSM);
-
- // Test USIM
- RIL.appType = CARD_APPTYPE_USIM;
- equal(ICCFileHelper.getEFPath(ICC_EF_SPDI),
- EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
- equal(ICCFileHelper.getEFPath(ICC_EF_SPDI),
- EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
- run_next_test();
-});
-
-/**
- * Verify RIL.iccSetCardLockEnabled
- */
-add_test(function test_icc_set_card_lock_enabled() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let ril = context.RIL;
- ril.aid = "123456789";
-
- function do_test(aLock, aPassword, aEnabled) {
- const serviceClass = ICC_SERVICE_CLASS_VOICE |
- ICC_SERVICE_CLASS_DATA |
- ICC_SERVICE_CLASS_FAX;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SET_FACILITY_LOCK);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 5);
- equal(parcel[0], GECKO_CARDLOCK_TO_FACILITY[aLock]);
- equal(parcel[1], aEnabled ? "1" : "0");
- equal(parcel[2], aPassword);
- equal(parcel[3], serviceClass.toString());
- equal(parcel[4], ril.aid);
- };
-
- ril.iccSetCardLockEnabled({
- lockType: aLock,
- enabled: aEnabled,
- password: aPassword});
- }
-
- do_test(GECKO_CARDLOCK_PIN, "1234", true);
- do_test(GECKO_CARDLOCK_PIN, "1234", false);
- do_test(GECKO_CARDLOCK_FDN, "4321", true);
- do_test(GECKO_CARDLOCK_FDN, "4321", false);
-
- run_next_test();
-});
-
-/**
- * Verify RIL.iccChangeCardLockPassword
- */
-add_test(function test_icc_change_card_lock_password() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let ril = context.RIL;
-
-
- function do_test(aLock, aPassword, aNewPassword) {
- let GECKO_CARDLOCK_TO_REQUEST = {};
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PIN] = REQUEST_CHANGE_SIM_PIN;
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PIN2] = REQUEST_CHANGE_SIM_PIN2;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), GECKO_CARDLOCK_TO_REQUEST[aLock]);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 3);
- equal(parcel[0], aPassword);
- equal(parcel[1], aNewPassword);
- equal(parcel[2], ril.aid);
- };
-
- ril.iccChangeCardLockPassword({
- lockType: aLock,
- password: aPassword,
- newPassword: aNewPassword});
- }
-
- do_test(GECKO_CARDLOCK_PIN, "1234", "4321");
- do_test(GECKO_CARDLOCK_PIN2, "1234", "4321");
-
- run_next_test();
-});
-
-/**
- * Verify RIL.iccUnlockCardLock - PIN
- */
-add_test(function test_icc_unlock_card_lock_pin() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let buf = context.Buf;
- ril.aid = "123456789";
-
- function do_test(aLock, aPassword) {
- let GECKO_CARDLOCK_TO_REQUEST = {};
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PIN] = REQUEST_ENTER_SIM_PIN;
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PIN2] = REQUEST_ENTER_SIM_PIN2;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), GECKO_CARDLOCK_TO_REQUEST[aLock]);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 2);
- equal(parcel[0], aPassword);
- equal(parcel[1], ril.aid);
- };
-
- ril.iccUnlockCardLock({
- lockType: aLock,
- password: aPassword
- });
- }
-
- do_test(GECKO_CARDLOCK_PIN, "1234");
- do_test(GECKO_CARDLOCK_PIN2, "1234");
-
- run_next_test();
-});
-
-/**
- * Verify RIL.iccUnlockCardLock - PUK
- */
-add_test(function test_icc_unlock_card_lock_puk() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let buf = context.Buf;
- ril.aid = "123456789";
-
- function do_test(aLock, aPassword, aNewPin) {
- let GECKO_CARDLOCK_TO_REQUEST = {};
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PUK] = REQUEST_ENTER_SIM_PUK;
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PUK2] = REQUEST_ENTER_SIM_PUK2;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), GECKO_CARDLOCK_TO_REQUEST[aLock]);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 3);
- equal(parcel[0], aPassword);
- equal(parcel[1], aNewPin);
- equal(parcel[2], ril.aid);
- };
-
- ril.iccUnlockCardLock({
- lockType: aLock,
- password: aPassword,
- newPin: aNewPin
- });
- }
-
- do_test(GECKO_CARDLOCK_PUK, "12345678", "1234");
- do_test(GECKO_CARDLOCK_PUK2, "12345678", "1234");
-
- run_next_test();
-});
-
-/**
- * Verify RIL.iccUnlockCardLock - Depersonalization
- */
-add_test(function test_icc_unlock_card_lock_depersonalization() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let buf = context.Buf;
-
- function do_test(aPassword) {
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 1);
- equal(parcel[0], aPassword);
- };
-
- ril.iccUnlockCardLock({
- lockType: GECKO_CARDLOCK_NCK,
- password: aPassword
- });
- }
-
- do_test("12345678");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_CardState.js b/dom/system/gonk/tests/test_ril_worker_icc_CardState.js
deleted file mode 100644
index 788df5073..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_CardState.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_personalization_state() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
- function testPersonalization(isCdma, cardPersoState, geckoCardState) {
- let iccStatus = {
- cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: (!isCdma) ? 0 : -1,
- cdmaSubscriptionAppIndex: (isCdma) ? 0 : -1,
- apps: [
- {
- app_state: CARD_APPSTATE_SUBSCRIPTION_PERSO,
- perso_substate: cardPersoState
- }],
- };
-
- ril._isCdma = isCdma;
- ril._processICCStatus(iccStatus);
- equal(ril.cardState, geckoCardState);
- }
-
- // Test GSM personalization state.
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK,
- Ci.nsIIcc.CARD_STATE_NETWORK_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
- Ci.nsIIcc.CARD_STATE_NETWORK_SUBSET_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
- Ci.nsIIcc.CARD_STATE_CORPORATE_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
- Ci.nsIIcc.CARD_STATE_SERVICE_PROVIDER_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SIM,
- Ci.nsIIcc.CARD_STATE_SIM_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
- Ci.nsIIcc.CARD_STATE_NETWORK_PUK_REQUIRED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
- Ci.nsIIcc.CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
- Ci.nsIIcc.CARD_STATE_CORPORATE_PUK_REQUIRED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
- Ci.nsIIcc.CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SIM_PUK,
- Ci.nsIIcc.CARD_STATE_SIM_PUK_REQUIRED);
-
- testPersonalization(false, CARD_PERSOSUBSTATE_UNKNOWN,
- Ci.nsIIcc.CARD_STATE_UNKNOWN);
- testPersonalization(false, CARD_PERSOSUBSTATE_IN_PROGRESS,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
- testPersonalization(false, CARD_PERSOSUBSTATE_READY,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_READY);
-
- // Test CDMA personalization state.
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
- Ci.nsIIcc.CARD_STATE_NETWORK1_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
- Ci.nsIIcc.CARD_STATE_NETWORK2_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
- Ci.nsIIcc.CARD_STATE_HRPD_NETWORK_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
- Ci.nsIIcc.CARD_STATE_RUIM_CORPORATE_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
- Ci.nsIIcc.CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
- Ci.nsIIcc.CARD_STATE_RUIM_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
- Ci.nsIIcc.CARD_STATE_NETWORK1_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
- Ci.nsIIcc.CARD_STATE_NETWORK2_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
- Ci.nsIIcc.CARD_STATE_HRPD_NETWORK_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
- Ci.nsIIcc.CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
- Ci.nsIIcc.CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
- Ci.nsIIcc.CARD_STATE_RUIM_PUK_REQUIRED);
-
- testPersonalization(true, CARD_PERSOSUBSTATE_UNKNOWN,
- Ci.nsIIcc.CARD_STATE_UNKNOWN);
- testPersonalization(true, CARD_PERSOSUBSTATE_IN_PROGRESS,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
- testPersonalization(true, CARD_PERSOSUBSTATE_READY,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_READY);
-
- run_next_test();
-});
-
-/**
- * Verify SIM app_state in _processICCStatus
- */
-add_test(function test_card_app_state() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
- function testCardAppState(cardAppState, geckoCardState) {
- let iccStatus = {
- cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: 0,
- apps: [
- {
- app_state: cardAppState
- }],
- };
-
- ril._processICCStatus(iccStatus);
- equal(ril.cardState, geckoCardState);
- }
-
- testCardAppState(CARD_APPSTATE_ILLEGAL,
- Ci.nsIIcc.CARD_STATE_ILLEGAL);
- testCardAppState(CARD_APPSTATE_PIN,
- Ci.nsIIcc.CARD_STATE_PIN_REQUIRED);
- testCardAppState(CARD_APPSTATE_PUK,
- Ci.nsIIcc.CARD_STATE_PUK_REQUIRED);
- testCardAppState(CARD_APPSTATE_READY,
- Ci.nsIIcc.CARD_STATE_READY);
- testCardAppState(CARD_APPSTATE_UNKNOWN,
- Ci.nsIIcc.CARD_STATE_UNKNOWN);
- testCardAppState(CARD_APPSTATE_DETECTED,
- Ci.nsIIcc.CARD_STATE_UNKNOWN);
-
- run_next_test();
-});
-
-/**
- * Verify permanent blocked for ICC.
- */
-add_test(function test_icc_permanent_blocked() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
- function testPermanentBlocked(pin1_replaced, universalPINState, pin1) {
- let iccStatus = {
- cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: 0,
- universalPINState: universalPINState,
- apps: [
- {
- pin1_replaced: pin1_replaced,
- pin1: pin1
- }]
- };
-
- ril._processICCStatus(iccStatus);
- equal(ril.cardState, Ci.nsIIcc.CARD_STATE_PERMANENT_BLOCKED);
- }
-
- testPermanentBlocked(1,
- CARD_PINSTATE_ENABLED_PERM_BLOCKED,
- CARD_PINSTATE_UNKNOWN);
- testPermanentBlocked(1,
- CARD_PINSTATE_ENABLED_PERM_BLOCKED,
- CARD_PINSTATE_ENABLED_PERM_BLOCKED);
- testPermanentBlocked(0,
- CARD_PINSTATE_UNKNOWN,
- CARD_PINSTATE_ENABLED_PERM_BLOCKED);
-
- run_next_test();
-});
-
-/**
- * Verify ICC without app index.
- */
-add_test(function test_icc_without_app_index() {
- const ICCID = "123456789";
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- let iccStatus = {
- cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: -1,
- universalPINState: CARD_PINSTATE_DISABLED,
- apps: [
- {
- app_state: CARD_APPSTATE_READY
- }]
- };
-
- context.ICCRecordHelper.readICCID = function fakeReadICCID() {
- ril.iccInfo.iccid = ICCID;
- };
-
- ril._processICCStatus(iccStatus);
-
- // Should read icc id event if the app index is -1.
- equal(ril.iccInfo.iccid, ICCID);
- // cardState is "unknown" if the app index is -1.
- equal(ril.cardState, GECKO_CARDSTATE_UNKNOWN);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js
deleted file mode 100644
index 0d074da79..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify GsmPDUHelper.writeTimestamp
- */
-add_test(function test_write_timestamp() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
-
- // current date
- let dateInput = new Date();
- let dateOutput = new Date();
- helper.writeTimestamp(dateInput);
- dateOutput.setTime(helper.readTimestamp());
-
- equal(dateInput.getFullYear(), dateOutput.getFullYear());
- equal(dateInput.getMonth(), dateOutput.getMonth());
- equal(dateInput.getDate(), dateOutput.getDate());
- equal(dateInput.getHours(), dateOutput.getHours());
- equal(dateInput.getMinutes(), dateOutput.getMinutes());
- equal(dateInput.getSeconds(), dateOutput.getSeconds());
- equal(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
-
- // 2034-01-23 12:34:56 -0800 GMT
- let time = Date.UTC(2034, 1, 23, 12, 34, 56);
- time = time - (8 * 60 * 60 * 1000);
- dateInput.setTime(time);
- helper.writeTimestamp(dateInput);
- dateOutput.setTime(helper.readTimestamp());
-
- equal(dateInput.getFullYear(), dateOutput.getFullYear());
- equal(dateInput.getMonth(), dateOutput.getMonth());
- equal(dateInput.getDate(), dateOutput.getDate());
- equal(dateInput.getHours(), dateOutput.getHours());
- equal(dateInput.getMinutes(), dateOutput.getMinutes());
- equal(dateInput.getSeconds(), dateOutput.getSeconds());
- equal(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
-
- run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper.octectToBCD and GsmPDUHelper.BCDToOctet
- */
-add_test(function test_octect_BCD() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
-
- // 23
- let number = 23;
- let octet = helper.BCDToOctet(number);
- equal(helper.octetToBCD(octet), number);
-
- // 56
- number = 56;
- octet = helper.BCDToOctet(number);
- equal(helper.octetToBCD(octet), number);
-
- // 0x23
- octet = 0x23;
- number = helper.octetToBCD(octet);
- equal(helper.BCDToOctet(number), octet);
-
- // 0x56
- octet = 0x56;
- number = helper.octetToBCD(octet);
- equal(helper.BCDToOctet(number), octet);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js
deleted file mode 100644
index 29b83b76a..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js
+++ /dev/null
@@ -1,1042 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Test error message returned in onerror for readICCContacts.
- */
-add_test(function test_error_message_read_icc_contact () {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- function do_test(options, expectedErrorMsg) {
- ril.sendChromeMessage = function(message) {
- equal(message.errorMsg, expectedErrorMsg);
- }
- ril.readICCContacts(options);
- }
-
- // Error 1, didn't specify correct contactType.
- do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
- // Error 2, specifying a non-supported contactType.
- ril.appType = CARD_APPTYPE_USIM;
- do_test({contactType: "foo"}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
-
- // Error 3, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
- // but forget to add implemenetations for it.
- USIM_PBR_FIELDS.push("pbc");
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN},
- CONTACT_ERR_FIELD_NOT_SUPPORTED);
-
- run_next_test();
-});
-
-/**
- * Test error message returned in onerror for updateICCContact.
- */
-add_test(function test_error_message_update_icc_contact() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- const ICCID = "123456789";
- ril.iccInfo.iccid = ICCID;
-
- function do_test(options, expectedErrorMsg) {
- ril.sendChromeMessage = function(message) {
- equal(message.errorMsg, expectedErrorMsg);
- }
- ril.updateICCContact(options);
- }
-
- // Error 1, didn't specify correct contactType.
- do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
- // Error 2, specifying a correct contactType, but without providing 'contact'.
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN},
- CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
- // Error 3, specifying a non-supported contactType.
- ril.appType = CARD_APPTYPE_USIM;
- do_test({contactType: GECKO_CARDCONTACT_TYPE_SDN, contact: {}},
- CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
-
- // Error 4, without supplying pin2.
- do_test({contactType: GECKO_CARDCONTACT_TYPE_FDN,
- contact: {contactId: ICCID + "1"}},
- GECKO_ERROR_SIM_PIN2);
-
- // Error 5, No free record found in EF_ADN.
- let record = context.ICCRecordHelper;
- record.readPBR = function(onsuccess, onerror) {
- onsuccess([{adn: {fileId: 0x4f3a}}]);
- };
-
- let io = context.ICCIOHelper;
- io.loadLinearFixedEF = function(options) {
- options.totalRecords = 1;
- options.p1 = 1;
- options.callback(options);
- };
-
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN, contact: {}},
- CONTACT_ERR_NO_FREE_RECORD_FOUND);
-
- // Error 6, ICC IO Error.
- io.loadLinearFixedEF = function(options) {
- ril[REQUEST_SIM_IO](0, {
- errorMsg: GECKO_ERROR_GENERIC_FAILURE
- });
- };
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN,
- contact: {contactId: ICCID + "1"}},
- GECKO_ERROR_GENERIC_FAILURE);
-
- // Error 7, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
- // but forget to add implemenetations for it.
- USIM_PBR_FIELDS.push("pbc");
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN,
- contact: {contactId: ICCID + "1"}},
- CONTACT_ERR_FIELD_NOT_SUPPORTED);
-
- // Error 8, EF_PBR doesn't exist.
- record.readPBR = function(onsuccess, onerror) {
- onsuccess([]);
- };
-
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN,
- contact: {contactId: ICCID + "1"}},
- CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.readICCContacts
- */
-add_test(function test_read_icc_contacts() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- let ril = context.RIL;
- let test_data = [
- //Record 1.
- {
- comment: "Test read SIM adn contact",
- rawData: {
- simType: CARD_APPTYPE_SIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 2.
- {
- comment: "Test read SIM fdn contact",
- rawData: {
- simType: CARD_APPTYPE_SIM,
- contactType: GECKO_CARDCONTACT_TYPE_FDN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 3.
- {
- comment: "Test read USIM adn contact",
- rawData: {
- simType: CARD_APPTYPE_USIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- pbrs: [{adn:{fileId: 0x6f3a}, email: {}, anr0: {}}],
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- email: "hello@mail.com",
- anr: "123456",
- },
- expectedContact: [{
- pbrIndex: 0,
- recordId: 1,
- alphaId: "name",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }],
- },
- //Record 4.
- {
- comment: "Test read USIM adn contacts",
- rawData: {
- simType: CARD_APPTYPE_USIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- pbrs: [{adn:{fileId: 0x6f3a}, email: {}, anr0: {}},
- {adn:{fileId: 0x6f3b}, email: {}, anr0: {}}],
- adnLike: [{recordId: 1, alphaId: "name1", number: "111111"},
- {recordId: 2, alphaId: "name2", number: "222222"}],
- email: "hello@mail.com",
- anr: "123456",
- },
- expectedContact: [
- {
- pbrIndex: 0,
- recordId: 1,
- alphaId: "name1",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 0,
- recordId: 2,
- alphaId: "name2",
- number: "222222",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 1,
- recordId: 1,
- alphaId: "name1",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 1,
- recordId: 2,
- alphaId: "name2",
- number: "222222",
- email: "hello@mail.com",
- anr: ["123456"]
- }
- ],
- },
- //Record 5.
- {
- comment: "Test read USIM fdn contact",
- rawData: {
- simType: CARD_APPTYPE_USIM,
- contactType: GECKO_CARDCONTACT_TYPE_FDN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 6.
- {
- comment: "Test read RUIM adn contact",
- rawData: {
- simType: CARD_APPTYPE_RUIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 7.
- {
- comment: "Test read RUIM fdn contact",
- rawData: {
- simType: CARD_APPTYPE_RUIM,
- contactType: GECKO_CARDCONTACT_TYPE_FDN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 8.
- {
- comment: "Test read RUIM adn contact with enhanced phone book",
- rawData: {
- simType: CARD_APPTYPE_RUIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- pbrs: [{adn:{fileId: 0x6f3a}, email: {}, anr0: {}}],
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- email: "hello@mail.com",
- anr: "123456",
- enhancedPhoneBook: true,
- },
- expectedContact: [{
- pbrIndex: 0,
- recordId: 1,
- alphaId: "name",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }],
- },
- //Record 9.
- {
- comment: "Test read RUIM adn contacts with enhanced phone book",
- rawData: {
- simType: CARD_APPTYPE_RUIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- pbrs: [{adn:{fileId: 0x6f3a}, email: {}, anr0: {}},
- {adn:{fileId: 0x6f3b}, email: {}, anr0: {}}],
- adnLike: [{recordId: 1, alphaId: "name1", number: "111111"},
- {recordId: 2, alphaId: "name2", number: "222222"}],
- email: "hello@mail.com",
- anr: "123456",
- enhancedPhoneBook: true,
- },
- expectedContact: [
- {
- pbrIndex: 0,
- recordId: 1,
- alphaId: "name1",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 0,
- recordId: 2,
- alphaId: "name2",
- number: "222222",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 1,
- recordId: 1,
- alphaId: "name1",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 1,
- recordId: 2,
- alphaId: "name2",
- number: "222222",
- email: "hello@mail.com",
- anr: ["123456"]
- }
- ],
- },
- ];
-
- function do_test(aTestData, aExpectedContact) {
- ril.appType = aTestData.simType;
- ril._isCdma = (aTestData.simType === CARD_APPTYPE_RUIM);
- ril.iccInfoPrivate.cst = (aTestData.enhancedPhoneBook) ?
- [0x20, 0x0C, 0x0, 0x0, 0x0]:
- [0x20, 0x00, 0x0, 0x0, 0x0];
-
- ril.iccInfoPrivate.sst = (aTestData.simType === CARD_APPTYPE_SIM)?
- [0x20, 0x0, 0x0, 0x0, 0x0]:
- [0x2, 0x0, 0x0, 0x0, 0x0];
-
- // Override some functions to test.
- contactHelper.getContactFieldRecordId = function(pbr, contact, field, onsuccess, onerror) {
- onsuccess(1);
- };
-
- record.readPBR = function readPBR(onsuccess, onerror) {
- onsuccess(JSON.parse(JSON.stringify(aTestData.pbrs)));
- };
-
- record.readADNLike = function readADNLike(fileId, extFileId, onsuccess, onerror) {
- onsuccess(JSON.parse(JSON.stringify(aTestData.adnLike)));
- };
-
- record.readEmail = function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) {
- onsuccess(aTestData.email);
- };
-
- record.readANR = function readANR(fileId, fileType, recordNumber, onsuccess, onerror) {
- onsuccess(aTestData.anr);
- };
-
- let onsuccess = function onsuccess(contacts) {
- for (let i = 0; i < contacts.length; i++) {
- do_print("check contacts[" + i + "]:" + JSON.stringify(contacts[i]));
- deepEqual(contacts[i], aExpectedContact[i]);
- }
- };
-
- let onerror = function onerror(errorMsg) {
- do_print("readICCContacts failed: " + errorMsg);
- ok(false);
- };
-
- contactHelper.readICCContacts(aTestData.simType, aTestData.contactType, onsuccess, onerror);
- }
-
- for (let i = 0; i < test_data.length; i++) {
- do_print(test_data[i].comment);
- do_test(test_data[i].rawData, test_data[i].expectedContact);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM.
- */
-add_test(function test_update_icc_contact() {
- const ADN_RECORD_ID = 100;
- const ADN_SFI = 1;
- const IAP_FILE_ID = 0x4f17;
- const EMAIL_FILE_ID = 0x4f50;
- const EMAIL_RECORD_ID = 20;
- const ANR0_FILE_ID = 0x4f11;
- const ANR0_RECORD_ID = 30;
- const EXT_RECORD_ID = 0x01;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- let ril = context.RIL;
-
- function do_test(aSimType, aContactType, aContact, aPin2, aFileType, aHaveIapIndex, aEnhancedPhoneBook) {
- ril.appType = aSimType;
- ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
- ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x20, 0x0C, 0x28, 0x0, 0x20]
- : [0x20, 0x0, 0x28, 0x0, 0x20];
- ril.iccInfoPrivate.sst = (aSimType === CARD_APPTYPE_SIM)?
- [0x20, 0x0, 0x28, 0x0, 0x20]:
- [0x16, 0x0, 0x0, 0x0, 0x0];
-
- recordHelper.readPBR = function(onsuccess, onerror) {
- if (aFileType === ICC_USIM_TYPE1_TAG) {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE1_TAG},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE1_TAG},
- ext1: {fileId: ICC_EF_EXT1}
-
- }]);
- } else if (aFileType === ICC_USIM_TYPE2_TAG) {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN,
- sfi: ADN_SFI},
- iap: {fileId: IAP_FILE_ID},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 0},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 1},
- ext1: {fileId: ICC_EF_EXT1}
- }]);
- }
- };
-
- recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- if (aContactType === GECKO_CARDCONTACT_TYPE_FDN) {
- equal(fileId, ICC_EF_FDN);
- } else if (aContactType === GECKO_CARDCONTACT_TYPE_ADN) {
- equal(fileId, ICC_EF_ADN);
- }
-
- if (aContact.number.length > ADN_MAX_NUMBER_DIGITS) {
- equal(extRecordNumber, EXT_RECORD_ID);
- } else {
- equal(extRecordNumber, 0xff);
- }
-
- equal(pin2, aPin2);
- equal(contact.alphaId, aContact.alphaId);
- equal(contact.number, aContact.number);
- onsuccess({alphaId: contact.alphaId,
- number: contact.number.substring(0, ADN_MAX_NUMBER_DIGITS)});
- };
-
- recordHelper.getADNLikeExtensionRecordNumber = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess(EXT_RECORD_ID);
- };
-
- recordHelper.updateExtension = function(fileId, recordNumber, number, onsuccess, onerror) {
- onsuccess();
- };
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- onsuccess(EXT_RECORD_ID);
- };
-
- recordHelper.cleanEFRecord = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess();
- }
-
- recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
- equal(fileId, IAP_FILE_ID);
- equal(recordNumber, ADN_RECORD_ID);
- onsuccess((aHaveIapIndex) ? [EMAIL_RECORD_ID, ANR0_RECORD_ID]
- : [0xff, 0xff]);
- };
-
- recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
- equal(fileId, IAP_FILE_ID);
- equal(recordNumber, ADN_RECORD_ID);
- onsuccess();
- };
-
- recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
- equal(pbr.email.fileId, EMAIL_FILE_ID);
- if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
- equal(recordNumber, ADN_RECORD_ID);
- } else if (pbr.email.fileType === ICC_USIM_TYPE2_TAG) {
- equal(recordNumber, EMAIL_RECORD_ID);
- }
- equal(email, aContact.email);
- onsuccess(email);
- };
-
- recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
- equal(pbr.anr0.fileId, ANR0_FILE_ID);
- if (pbr.anr0.fileType === ICC_USIM_TYPE1_TAG) {
- equal(recordNumber, ADN_RECORD_ID);
- } else if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
- equal(recordNumber, ANR0_RECORD_ID);
- }
- if (Array.isArray(aContact.anr)) {
- equal(number, aContact.anr[0]);
- }
- onsuccess(number);
- };
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- let recordId = 0;
- if (fileId === EMAIL_FILE_ID) {
- recordId = EMAIL_RECORD_ID;
- } else if (fileId === ANR0_FILE_ID) {
- recordId = ANR0_RECORD_ID;
- }
- onsuccess(recordId);
- };
-
- let isSuccess = false;
- let onsuccess = function onsuccess(updatedContact) {
- equal(ADN_RECORD_ID, updatedContact.recordId);
- equal(aContact.alphaId, updatedContact.alphaId);
- equal(aContact.number.substring(0, ADN_MAX_NUMBER_DIGITS + EXT_MAX_NUMBER_DIGITS),
- updatedContact.number);
- if ((aSimType == CARD_APPTYPE_USIM || aSimType == CARD_APPTYPE_RUIM) &&
- (aFileType == ICC_USIM_TYPE1_TAG || aFileType == ICC_USIM_TYPE2_TAG)) {
- if (aContact.hasOwnProperty('email')) {
- equal(aContact.email, updatedContact.email);
- }
-
- if (aContact.hasOwnProperty('anr')) {
- equal(aContact.anr[0], updatedContact.anr[0]);
- }
- } else {
- equal(updatedContact.email, null);
- equal(updatedContact.anr, null);
- }
-
- do_print("updateICCContact success");
- isSuccess = true;
- };
-
- let onerror = function onerror(errorMsg) {
- do_print("updateICCContact failed: " + errorMsg);
- };
-
- contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
- ok(isSuccess);
- }
-
- let contacts = [
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test",
- number: "123456",
- email: "test@mail.com",
- anr: ["+654321"]
- },
- // a contact without email and anr.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test2",
- number: "123456",
- },
- // a contact with email but no anr.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test3",
- number: "123456",
- email: "test@mail.com"
- },
- // a contact with anr but no email.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test4",
- number: "123456",
- anr: ["+654321"]
- },
- // a contact number over 20 digits.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test4",
- number: "0123456789012345678901234567890123456789",
- anr: ["+654321"]
- },
- // a contact number over 40 digits.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test5",
- number: "01234567890123456789012345678901234567890123456789",
- anr: ["+654321"]
- }];
-
- for (let i = 0; i < contacts.length; i++) {
- let contact = contacts[i];
- // SIM
- do_print("Test update SIM adn contacts");
- do_test(CARD_APPTYPE_SIM, GECKO_CARDCONTACT_TYPE_ADN, contact);
-
- do_print("Test update SIM fdn contacts");
- do_test(CARD_APPTYPE_SIM, GECKO_CARDCONTACT_TYPE_FDN, contact, "1234");
-
- // USIM
- do_print("Test update USIM adn contacts");
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE1_TAG);
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE2_TAG, true);
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE2_TAG, false);
-
- do_print("Test update USIM fdn contacts");
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_FDN, contact, "1234");
-
- // RUIM
- do_print("Test update RUIM adn contacts");
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_ADN, contact);
-
- do_print("Test update RUIM fdn contacts");
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_FDN, contact, "1234");
-
- // RUIM with enhanced phone book
- do_print("Test update RUIM adn contacts with enhanced phone book");
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE1_TAG, null,true);
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE2_TAG, true, true);
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE2_TAG, false, true);
-
- do_print("Test update RUIM fdn contacts with enhanced phone book");
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_FDN, contact, "1234",
- null, true);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM and
- * insufficient space to store Type 2 USIM contact fields.
- */
-add_test(function test_update_icc_contact_full_email_and_anr_field() {
- const ADN_RECORD_ID = 100;
- const ADN_SFI = 1;
- const IAP_FILE_ID = 0x4f17;
- const EMAIL_FILE_ID = 0x4f50;
- const EMAIL_RECORD_ID = 20;
- const ANR0_FILE_ID = 0x4f11;
- const ANR0_RECORD_ID = 30;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- let ril = context.RIL;
-
- function do_test(aSimType, aContactType, aContact, aPin2) {
- ril.appType = CARD_APPTYPE_USIM;
- ril.iccInfoPrivate.sst = [0x2, 0x0, 0x0, 0x0, 0x0];
-
- recordHelper.readPBR = function(onsuccess, onerror) {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN,
- sfi: ADN_SFI},
- iap: {fileId: IAP_FILE_ID},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 0},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 1}
- }]);
- };
-
- recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- if (aContactType === GECKO_CARDCONTACT_TYPE_ADN) {
- equal(fileId, ICC_EF_ADN);
- }
- equal(pin2, aPin2);
- equal(contact.alphaId, aContact.alphaId);
- equal(contact.number, aContact.number);
- onsuccess({alphaId: contact.alphaId,
- number: contact.number});
- };
-
- recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
- equal(fileId, IAP_FILE_ID);
- equal(recordNumber, ADN_RECORD_ID);
- onsuccess([0xff, 0xff]);
- };
-
- recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
- equal(fileId, IAP_FILE_ID);
- equal(recordNumber, ADN_RECORD_ID);
- onsuccess();
- };
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- let recordId = 0;
- // emulate email and anr don't have free record.
- if (fileId === EMAIL_FILE_ID || fileId === ANR0_FILE_ID) {
- onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- } else {
- onsuccess(recordId);
- }
- };
-
- let isSuccess = false;
- let onsuccess = function onsuccess(updatedContact) {
- equal(ADN_RECORD_ID, updatedContact.recordId);
- equal(aContact.alphaId, updatedContact.alphaId);
- equal(updatedContact.email, null);
- equal(updatedContact.anr, null);
-
- do_print("updateICCContact success");
- isSuccess = true;
- };
-
- let onerror = function onerror(errorMsg) {
- do_print("updateICCContact failed: " + errorMsg);
- };
-
- contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
- ok(isSuccess);
- }
-
- let contact = {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test",
- number: "123456",
- email: "test@mail.com",
- anr: ["+654321"]
- };
-
- // USIM
- do_print("Test update USIM adn contacts");
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null);
-
- run_next_test();
-});
-
-/**
- * Verify updateICCContact with removal of anr and email with File Type 1.
- */
-add_test(function test_update_icc_contact_with_remove_type1_attr() {
- const ADN_RECORD_ID = 100;
- const IAP_FILE_ID = 0x4f17;
- const EMAIL_FILE_ID = 0x4f50;
- const EMAIL_RECORD_ID = 20;
- const ANR0_FILE_ID = 0x4f11;
- const ANR0_RECORD_ID = 30;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
-
- recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- onsuccess({alphaId: contact.alphaId,
- number: contact.number});
- };
-
- let contact = {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test2",
- number: "123456",
- };
-
- recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess([EMAIL_RECORD_ID, ANR0_RECORD_ID]);
- };
-
- recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
- ok(email == null);
- onsuccess(email);
- };
-
- recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
- ok(number == null);
- onsuccess(number);
- };
-
- function do_test(type) {
- recordHelper.readPBR = function(onsuccess, onerror) {
- if (type == ICC_USIM_TYPE1_TAG) {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE1_TAG},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE1_TAG}}]);
- } else {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN},
- iap: {fileId: IAP_FILE_ID},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 0},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 1}}]);
- }
- };
-
- let successCb = function(updatedContact) {
- equal(updatedContact.email, null);
- equal(updatedContact.anr, null);
- ok(true);
- };
-
- let errorCb = function(errorMsg) {
- do_print(errorMsg);
- ok(false);
- };
-
- contactHelper.updateICCContact(CARD_APPTYPE_USIM,
- GECKO_CARDCONTACT_TYPE_ADN,
- contact, null, successCb, errorCb);
- }
-
- do_test(ICC_USIM_TYPE1_TAG);
- do_test(ICC_USIM_TYPE2_TAG);
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.findFreeICCContact in SIM
- */
-add_test(function test_find_free_icc_contact_sim() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- // Correct record Id starts with 1, so put a null element at index 0.
- let records = [null];
- const MAX_RECORDS = 3;
- const PBR_INDEX = 0;
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- if (records.length > MAX_RECORDS) {
- onerror("No free record found.");
- return;
- }
-
- onsuccess(records.length);
- };
-
- let successCb = function(pbrIndex, recordId) {
- equal(pbrIndex, PBR_INDEX);
- records[recordId] = {};
- };
-
- let errorCb = function(errorMsg) {
- do_print(errorMsg);
- ok(false);
- };
-
- for (let i = 0; i < MAX_RECORDS; i++) {
- contactHelper.findFreeICCContact(CARD_APPTYPE_SIM,
- GECKO_CARDCONTACT_TYPE_ADN,
- successCb, errorCb);
- }
- // The 1st element, records[0], is null.
- equal(records.length - 1, MAX_RECORDS);
-
- // Now the EF is full, so finding a free one should result failure.
- successCb = function(pbrIndex, recordId) {
- ok(false);
- };
-
- errorCb = function(errorMsg) {
- ok(errorMsg === "No free record found.");
- };
- contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, GECKO_CARDCONTACT_TYPE_ADN,
- successCb, errorCb);
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.findFreeICCContact in USIM
- */
-add_test(function test_find_free_icc_contact_usim() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- const ADN1_FILE_ID = 0x6f3a;
- const ADN2_FILE_ID = 0x6f3b;
- const MAX_RECORDS = 3;
-
- // The adn in the first phonebook set has already two records, which means
- // only 1 free record remained.
- let pbrs = [{adn: {fileId: ADN1_FILE_ID, records: [null, {}, {}]}},
- {adn: {fileId: ADN2_FILE_ID, records: [null]}}];
-
- recordHelper.readPBR = function readPBR(onsuccess, onerror) {
- onsuccess(pbrs);
- };
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- let pbr = (fileId == ADN1_FILE_ID ? pbrs[0]: pbrs[1]);
- if (pbr.adn.records.length > MAX_RECORDS) {
- onerror("No free record found.");
- return;
- }
-
- onsuccess(pbr.adn.records.length);
- };
-
- let successCb = function(pbrIndex, recordId) {
- equal(pbrIndex, 0);
- pbrs[pbrIndex].adn.records[recordId] = {};
- };
-
- let errorCb = function(errorMsg) {
- ok(false);
- };
-
- contactHelper.findFreeICCContact(CARD_APPTYPE_USIM,
- GECKO_CARDCONTACT_TYPE_ADN,
- successCb, errorCb);
-
- // Now the EF_ADN in the 1st phonebook set is full, so the next free contact
- // will come from the 2nd phonebook set.
- successCb = function(pbrIndex, recordId) {
- equal(pbrIndex, 1);
- equal(recordId, 1);
- }
- contactHelper.findFreeICCContact(CARD_APPTYPE_USIM,
- GECKO_CARDCONTACT_TYPE_ADN,
- successCb, errorCb);
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.updateADNLikeWithExtension
- */
-add_test(function test_update_adn_like_with_extension() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let record = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- ril.appType = CARD_APPTYPE_SIM;
- // Correct record Id starts from 1, so put a null element at index 0.
- // ext_records contains data at index 1, and it only has 1 free record at index 2.
- let notFree = 0x01;
- let ext_records = [null, notFree, null];
-
- function do_test(contact, extRecordNumber, expectedExtRecordNumber, expectedNumber, expectedCleanEFRecord) {
- // Override some functions to test.
- record.getADNLikeExtensionRecordNumber = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess(extRecordNumber);
- }
-
- record.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- equal(extRecordNumber, expectedExtRecordNumber);
- onsuccess({alphaId: contact.alphaId,
- number: contact.number.substring(0, ADN_MAX_NUMBER_DIGITS)});
- }
-
- record.updateExtension = function(fileId, recordNumber, number, onsuccess, onerror) {
- if (recordNumber > ext_records.length) {
- onerror("updateExtension failed.");
- return;
- }
- ext_records[recordNumber] = number;
- onsuccess();
- }
-
- record.findFreeRecordId = function(fileId, onsuccess, onerror) {
- for (let i = 1; i < ext_records.length; i++) {
- if (!ext_records[i]) {
- onsuccess(i);
- return;
- }
- }
-
- onerror("No free record found.");
- }
-
- let isCleanEFRecord = false;
- record.cleanEFRecord = function(fileId, recordNumber, onsuccess, onerror) {
- if (recordNumber > ext_records.length) {
- onerror("cleanEFRecord failed.");
- return;
- }
- ext_records[recordNumber] = null;
- isCleanEFRecord = true;
- onsuccess();
- }
-
- let successCb = function successCb(updatedContact) {
- equal(updatedContact.number, expectedNumber);
- };
-
- let errorCb = function errorCb(errorMsg) {
- do_print("updateADNLikeWithExtension failed, msg = " + errorMsg);
- ok(false);
- };
-
- contactHelper.updateADNLikeWithExtension(ICC_EF_ADN, ICC_EF_EXT1, contact, null, successCb, errorCb);
-
- if (expectedCleanEFRecord) {
- ok(isCleanEFRecord);
- }
- }
-
- // Update extension record with previous extension record number.
- do_test({recordId: 1, alphaId: "test", number: "001122334455667788991234"}, 0x01, 0x01, "001122334455667788991234");
- // Update extension record and find a free record.
- do_test({recordId: 1, alphaId: "test", number: "001122334455667788995678"}, 0xff, 0x02, "001122334455667788995678");
- // Update extension record with no free extension record.
- do_test({recordId: 1, alphaId: "test", number: "001122334455667788994321"}, 0xff, 0xff, "00112233445566778899");
- // Update extension record with clean previous extension record.
- do_test({recordId: 1, alphaId: "test", number: "00112233445566778899"}, 0x01, 0xff, "00112233445566778899", true);
- // Update extension record with no extension record and previous extension record.
- do_test({recordId: 1, alphaId: "test", number: "00112233445566778899"}, 0xff, 0xff, "00112233445566778899");
-
- run_next_test();
-}); \ No newline at end of file
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js
deleted file mode 100644
index e690b1206..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify ICCIOHelper.loadLinearFixedEF with recordSize.
- */
-add_test(function test_load_linear_fixed_ef() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let io = context.ICCIOHelper;
-
- io.getResponse = function fakeGetResponse(options) {
- // When recordSize is provided, loadLinearFixedEF should call iccIO directly.
- ok(false);
- run_next_test();
- };
-
- ril.iccIO = function fakeIccIO(options) {
- ok(true);
- run_next_test();
- };
-
- io.loadLinearFixedEF({recordSize: 0x20});
-});
-
-/**
- * Verify ICCIOHelper.loadLinearFixedEF without recordSize.
- */
-add_test(function test_load_linear_fixed_ef() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let io = context.ICCIOHelper;
-
- io.getResponse = function fakeGetResponse(options) {
- ok(true);
- run_next_test();
- };
-
- ril.iccIO = function fakeIccIO(options) {
- // When recordSize is not provided, loadLinearFixedEF should call getResponse.
- ok(false);
- run_next_test();
- };
-
- io.loadLinearFixedEF({});
-});
-
-/**
- * Verify ICC IO Error.
- */
-add_test(function test_process_icc_io_error() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
-
- function do_test(sw1, sw2, expectedErrorMsg) {
- let called = false;
- function errorCb(errorMsg) {
- called = true;
- equal(errorMsg, expectedErrorMsg);
- }
-
- // Write sw1 and sw2 to buffer.
- buf.writeInt32(sw1);
- buf.writeInt32(sw2);
-
- context.RIL[REQUEST_SIM_IO](0, {fileId: 0xffff,
- command: 0xff,
- onerror: errorCb});
-
- // onerror callback should be triggered.
- ok(called);
- }
-
- let TEST_DATA = [
- // [sw1, sw2, expectError]
- [ICC_STATUS_ERROR_COMMAND_NOT_ALLOWED, 0xff, GECKO_ERROR_GENERIC_FAILURE],
- [ICC_STATUS_ERROR_WRONG_PARAMETERS, 0xff, GECKO_ERROR_GENERIC_FAILURE],
- ];
-
- for (let i = 0; i < TEST_DATA.length; i++) {
- do_test.apply(null, TEST_DATA[i]);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCIOHelper.processICCIOGetResponse for EF_TYPE_TRANSPARENT.
- */
-add_test(function test_icc_io_get_response_for_transparent_structure() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let iccioHelper = context.ICCIOHelper;
- let pduHelper = context.GsmPDUHelper;
-
- let responseArray = [
- // SIM response.
- [0x00, 0x00, 0x00, 0x0A, 0x2F, 0xE2, 0x04, 0x00, 0x0A, 0xA0, 0xAA, 0x00,
- 0x02, 0x00, 0x00],
- // USIM response.
- [0x62, 0x22, 0x82, 0x02, 0x41, 0x21, 0x83, 0x02, 0x2F, 0xE2, 0xA5, 0x09,
- 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x05,
- 0x8B, 0x03, 0x2F, 0x06, 0x0B, 0x80, 0x02, 0x00, 0x0A, 0x88, 0x01, 0x10]
- ];
-
- for (let i = 0; i < responseArray.length; i++) {
- let strLen = responseArray[i].length * 2;
- buf.writeInt32(strLen);
- for (let j = 0; j < responseArray[i].length; j++) {
- pduHelper.writeHexOctet(responseArray[i][j]);
- }
- buf.writeStringDelimiter(strLen);
-
- let options = {fileId: ICC_EF_ICCID,
- structure: EF_STRUCTURE_TRANSPARENT};
- iccioHelper.processICCIOGetResponse(options);
-
- equal(options.fileSize, 0x0A);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCIOHelper.processICCIOGetResponse for EF_TYPE_LINEAR_FIXED.
- */
-add_test(function test_icc_io_get_response_for_linear_fixed_structure() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let iccioHelper = context.ICCIOHelper;
- let pduHelper = context.GsmPDUHelper;
-
- let responseArray = [
- // SIM response.
- [0x00, 0x00, 0x00, 0x1A, 0x6F, 0x40, 0x04, 0x00, 0x11, 0xA0, 0xAA, 0x00,
- 0x02, 0x01, 0x1A],
- // USIM response.
- [0x62, 0x1E, 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01, 0x83, 0x02, 0x6F,
- 0x40, 0xA5, 0x03, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x07, 0x8B, 0x03, 0x6F,
- 0x06, 0x02, 0x80, 0x02, 0x00, 0x1A, 0x88, 0x00]
- ];
-
- for (let i = 0; i < responseArray.length; i++) {
- let strLen = responseArray[i].length * 2;
- buf.writeInt32(strLen);
- for (let j = 0; j < responseArray[i].length; j++) {
- pduHelper.writeHexOctet(responseArray[i][j]);
- }
- buf.writeStringDelimiter(strLen);
-
- let options = {fileId: ICC_EF_MSISDN,
- structure: EF_STRUCTURE_LINEAR_FIXED};
- iccioHelper.processICCIOGetResponse(options);
-
- equal(options.fileSize, 0x1A);
- equal(options.recordSize, 0x1A);
- equal(options.totalRecords, 0x01);
- }
-
- run_next_test();
-});
-
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js
deleted file mode 100644
index 91495b1b7..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js
+++ /dev/null
@@ -1,652 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify ICCPDUHelper#readICCUCS2String()
- */
-add_test(function test_read_icc_ucs2_string() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- // 0x80
- let text = "TEST";
- helper.writeUCS2String(text);
- // Also write two unused octets.
- let ffLen = 2;
- for (let i = 0; i < ffLen; i++) {
- helper.writeHexOctet(0xff);
- }
- equal(iccHelper.readICCUCS2String(0x80, (2 * text.length) + ffLen), text);
-
- // 0x81
- let array = [0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca,
- 0xff, 0xff];
- let len = array.length;
- for (let i = 0; i < len; i++) {
- helper.writeHexOctet(array[i]);
- }
- equal(iccHelper.readICCUCS2String(0x81, len), "Mozilla\u694a");
-
- // 0x82
- let array2 = [0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61,
- 0xca, 0xff, 0xff];
- let len2 = array2.length;
- for (let i = 0; i < len2; i++) {
- helper.writeHexOctet(array2[i]);
- }
- equal(iccHelper.readICCUCS2String(0x82, len2), "Mozilla\u694a");
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#writeICCUCS2String()
- */
-add_test(function test_write_icc_ucs2_string() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let alphaLen = 18;
- let test_data = [
- {
- encode: 0x80,
- // string only contain one character.
- data: "\u82b3"
- }, {
- encode: 0x80,
- // 2 UCS2 character not located in the same half-page.
- data: "Fire \u82b3\u8233"
- }, {
- encode: 0x80,
- // 2 UCS2 character not located in the same half-page.
- data: "\u694a\u704a"
- }, {
- encode: 0x81,
- // 2 UCS2 character within same half-page.
- data: "Fire \u6901\u697f"
- }, {
- encode: 0x81,
- // 2 UCS2 character within same half-page.
- data: "Fire \u6980\u69ff"
- }, {
- encode: 0x82,
- // 2 UCS2 character within same half-page, but bit 8 is different.
- data: "Fire \u0514\u0593"
- }, {
- encode: 0x82,
- // 2 UCS2 character over 0x81 can encode range.
- data: "Fire \u8000\u8001"
- }, {
- encode: 0x82,
- // 2 UCS2 character over 0x81 can encode range.
- data: "Fire \ufffd\ufffe"
- }];
-
- for (let i = 0; i < test_data.length; i++) {
- let test = test_data[i];
- let writtenStr = iccHelper.writeICCUCS2String(alphaLen, test.data);
- equal(writtenStr, test.data);
- equal(helper.readHexOctet(), test.encode);
- equal(iccHelper.readICCUCS2String(test.encode, alphaLen - 1), test.data);
- }
-
- // This string use 0x80 encoded and the maximum capacity is 17 octets.
- // Each alphabet takes 2 octets, thus the first 8 alphabets can be written.
- let str = "Mozilla \u82b3\u8233 On Fire";
- let writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
- equal(writtenStr, str.substring(0, 8));
- equal(helper.readHexOctet(), 0x80);
- equal(iccHelper.readICCUCS2String(0x80, alphaLen - 1), str.substring(0, 8));
-
- // This string use 0x81 encoded and the maximum capacity is 15 octets.
- // Each alphabet takes 1 octets, thus the first 15 alphabets can be written.
- str = "Mozilla \u6901\u697f On Fire";
- writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
- equal(writtenStr, str.substring(0, 15));
- equal(helper.readHexOctet(), 0x81);
- equal(iccHelper.readICCUCS2String(0x81, alphaLen - 1), str.substring(0, 15));
-
- // This string use 0x82 encoded and the maximum capacity is 14 octets.
- // Each alphabet takes 1 octets, thus the first 14 alphabets can be written.
- str = "Mozilla \u0514\u0593 On Fire";
- writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
- equal(writtenStr, str.substring(0, 14));
- equal(helper.readHexOctet(), 0x82);
- equal(iccHelper.readICCUCS2String(0x82, alphaLen - 1), str.substring(0, 14));
-
- run_next_test();
-});
-/**
- * Verify ICCPDUHelper#readDiallingNumber
- */
-add_test(function test_read_dialling_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let str = "123456789";
-
- helper.readHexOctet = function() {
- return 0x81;
- };
-
- helper.readSwappedNibbleExtendedBcdString = function(len) {
- return str.substring(0, len);
- };
-
- for (let i = 0; i < str.length; i++) {
- equal(str.substring(0, i - 1), // -1 for the TON
- iccHelper.readDiallingNumber(i));
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#read8BitUnpackedToString
- */
-add_test(function test_read_8bit_unpacked_to_string() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- // Test 1: Read GSM alphabets.
- // Write alphabets before ESCAPE.
- for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
- helper.writeHexOctet(i);
- }
-
- // Write two ESCAPEs to make it become ' '.
- helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
- helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
-
- for (let i = PDU_NL_EXTENDED_ESCAPE + 1; i < langTable.length; i++) {
- helper.writeHexOctet(i);
- }
-
- // Also write two unused fields.
- let ffLen = 2;
- for (let i = 0; i < ffLen; i++) {
- helper.writeHexOctet(0xff);
- }
-
- equal(iccHelper.read8BitUnpackedToString(PDU_NL_EXTENDED_ESCAPE),
- langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
- equal(iccHelper.read8BitUnpackedToString(2), " ");
- equal(iccHelper.read8BitUnpackedToString(langTable.length -
- PDU_NL_EXTENDED_ESCAPE - 1 + ffLen),
- langTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
-
- // Test 2: Read GSM extended alphabets.
- for (let i = 0; i < langShiftTable.length; i++) {
- helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
- helper.writeHexOctet(i);
- }
-
- // Read string before RESERVED_CONTROL.
- equal(iccHelper.read8BitUnpackedToString(PDU_NL_RESERVED_CONTROL * 2),
- langShiftTable.substring(0, PDU_NL_RESERVED_CONTROL));
- // ESCAPE + RESERVED_CONTROL will become ' '.
- equal(iccHelper.read8BitUnpackedToString(2), " ");
- // Read string between RESERVED_CONTROL and EXTENDED_ESCAPE.
- equal(iccHelper.read8BitUnpackedToString(
- (PDU_NL_EXTENDED_ESCAPE - PDU_NL_RESERVED_CONTROL - 1) * 2),
- langShiftTable.substring(PDU_NL_RESERVED_CONTROL + 1,
- PDU_NL_EXTENDED_ESCAPE));
- // ESCAPE + ESCAPE will become ' '.
- equal(iccHelper.read8BitUnpackedToString(2), " ");
- // Read remaining string.
- equal(iccHelper.read8BitUnpackedToString(
- (langShiftTable.length - PDU_NL_EXTENDED_ESCAPE - 1) * 2),
- langShiftTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#writeStringTo8BitUnpacked.
- *
- * Test writing GSM 8 bit alphabets.
- */
-add_test(function test_write_string_to_8bit_unpacked() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- // Length of trailing 0xff.
- let ffLen = 2;
- let str;
-
- // Test 1, write GSM alphabets.
- let writtenStr = iccHelper.writeStringTo8BitUnpacked(langTable.length + ffLen, langTable);
- equal(writtenStr, langTable);
-
- for (let i = 0; i < langTable.length; i++) {
- equal(helper.readHexOctet(), i);
- }
-
- for (let i = 0; i < ffLen; i++) {
- equal(helper.readHexOctet(), 0xff);
- }
-
- // Test 2, write GSM extended alphabets.
- str = "\u000c\u20ac";
- writtenStr = iccHelper.writeStringTo8BitUnpacked(4, str);
- equal(writtenStr, str);
- equal(iccHelper.read8BitUnpackedToString(4), str);
-
- // Test 3, write GSM and GSM extended alphabets.
- // \u000c, \u20ac are from gsm extended alphabets.
- // \u00a3 is from gsm alphabet.
- str = "\u000c\u20ac\u00a3";
-
- // 2 octets * 2 = 4 octets for 2 gsm extended alphabets,
- // 1 octet for 1 gsm alphabet,
- // 2 octes for trailing 0xff.
- // "Totally 7 octets are to be written."
- writtenStr = iccHelper.writeStringTo8BitUnpacked(7, str);
- equal(writtenStr, str);
- equal(iccHelper.read8BitUnpackedToString(7), str);
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#writeStringTo8BitUnpacked with maximum octets written.
- */
-add_test(function test_write_string_to_8bit_unpacked_with_max_octets_written() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- // The maximum of the number of octets that can be written is 3.
- // Only 3 characters shall be written even the length of the string is 4.
- let writtenStr = iccHelper.writeStringTo8BitUnpacked(3, langTable.substring(0, 4));
- equal(writtenStr, langTable.substring(0, 3));
- helper.writeHexOctet(0xff); // dummy octet.
- for (let i = 0; i < 3; i++) {
- equal(helper.readHexOctet(), i);
- }
- ok(helper.readHexOctet() != 4);
-
- // \u000c is GSM extended alphabet, 2 octets.
- // \u00a3 is GSM alphabet, 1 octet.
- let str = "\u000c\u00a3";
- writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
- equal(writtenStr, str.substring(0, 2));
- equal(iccHelper.read8BitUnpackedToString(3), str);
-
- str = "\u00a3\u000c";
- writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
- equal(writtenStr, str.substring(0, 2));
- equal(iccHelper.read8BitUnpackedToString(3), str);
-
- // 2 GSM extended alphabets cost 4 octets, but maximum is 3, so only the 1st
- // alphabet can be written.
- str = "\u000c\u000c";
- writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
- helper.writeHexOctet(0xff); // dummy octet.
- equal(writtenStr, str.substring(0, 1));
- equal(iccHelper.read8BitUnpackedToString(4), str.substring(0, 1));
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readAlphaIdentifier
- */
-add_test(function test_read_alpha_identifier() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- // UCS2: 0x80
- let text = "TEST";
- helper.writeHexOctet(0x80);
- helper.writeUCS2String(text);
- // Also write two unused octets.
- let ffLen = 2;
- for (let i = 0; i < ffLen; i++) {
- helper.writeHexOctet(0xff);
- }
- equal(iccHelper.readAlphaIdentifier(1 + (2 * text.length) + ffLen), text);
-
- // UCS2: 0x81
- let array = [0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
- for (let i = 0; i < array.length; i++) {
- helper.writeHexOctet(array[i]);
- }
- equal(iccHelper.readAlphaIdentifier(array.length), "Mozilla\u694a");
-
- // UCS2: 0x82
- let array2 = [0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
- for (let i = 0; i < array2.length; i++) {
- helper.writeHexOctet(array2[i]);
- }
- equal(iccHelper.readAlphaIdentifier(array2.length), "Mozilla\u694a");
-
- // GSM 8 Bit Unpacked
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
- helper.writeHexOctet(i);
- }
- equal(iccHelper.readAlphaIdentifier(PDU_NL_EXTENDED_ESCAPE),
- langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeAlphaIdentifier
- */
-add_test(function test_write_alpha_identifier() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- // Length of trailing 0xff.
- let ffLen = 2;
-
- // Removal
- let writenAlphaId = iccHelper.writeAlphaIdentifier(10, null);
- equal(writenAlphaId, "");
- equal(iccHelper.readAlphaIdentifier(10), "");
-
- // GSM 8 bit
- let str = "Mozilla";
- writenAlphaId = iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
- equal(writenAlphaId , str);
- equal(iccHelper.readAlphaIdentifier(str.length + ffLen), str);
-
- // UCS2
- str = "Mozilla\u8000";
- writenAlphaId = iccHelper.writeAlphaIdentifier(str.length * 2 + ffLen, str);
- equal(writenAlphaId , str);
- // * 2 for each character will be encoded to UCS2 alphabets.
- equal(iccHelper.readAlphaIdentifier(str.length * 2 + ffLen), str);
-
- // Test with maximum octets written.
- // 1 coding scheme (0x80) and 1 UCS2 character, total 3 octets.
- str = "\u694a";
- writenAlphaId = iccHelper.writeAlphaIdentifier(3, str);
- equal(writenAlphaId , str);
- equal(iccHelper.readAlphaIdentifier(3), str);
-
- // 1 coding scheme (0x80) and 2 UCS2 characters, total 5 octets.
- // numOctets is limited to 4, so only 1 UCS2 character can be written.
- str = "\u694a\u69ca";
- writenAlphaId = iccHelper.writeAlphaIdentifier(4, str);
- helper.writeHexOctet(0xff); // dummy octet.
- equal(writenAlphaId , str.substring(0, 1));
- equal(iccHelper.readAlphaIdentifier(5), str.substring(0, 1));
-
- // Write 0 octet.
- writenAlphaId = iccHelper.writeAlphaIdentifier(0, "1");
- helper.writeHexOctet(0xff); // dummy octet.
- equal(writenAlphaId, "");
- equal(iccHelper.readAlphaIdentifier(1), "");
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readAlphaIdDiallingNumber
- */
-add_test(function test_read_alpha_id_dialling_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let buf = context.Buf;
- const recordSize = 32;
-
- function testReadAlphaIdDiallingNumber(contact) {
- iccHelper.readAlphaIdentifier = function() {
- return contact.alphaId;
- };
-
- iccHelper.readNumberWithLength = function() {
- return contact.number;
- };
-
- let strLen = recordSize * 2;
- buf.writeInt32(strLen); // fake length
- helper.writeHexOctet(0xff); // fake CCP
- helper.writeHexOctet(0xff); // fake EXT1
- buf.writeStringDelimiter(strLen);
-
- let contactR = iccHelper.readAlphaIdDiallingNumber(recordSize);
- if (contact.alphaId == "" && contact.number == "") {
- equal(contactR, null);
- } else {
- equal(contactR.alphaId, contact.alphaId);
- equal(contactR.number, contact.number);
- }
- }
-
- testReadAlphaIdDiallingNumber({alphaId: "AlphaId", number: "0987654321"});
- testReadAlphaIdDiallingNumber({alphaId: "", number: ""});
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeAlphaIdDiallingNumber
- */
-add_test(function test_write_alpha_id_dialling_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.ICCPDUHelper;
- const recordSize = 32;
-
- // Write a normal contact.
- let contactW = {
- alphaId: "Mozilla",
- number: "1234567890"
- };
-
- let writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
- contactW.alphaId,
- contactW.number, 0xff);
-
- let contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(writtenContact.alphaId, contactR.alphaId);
- equal(writtenContact.number, contactR.number);
- equal(0xff, contactR.extRecordNumber);
-
- // Write a contact with alphaId encoded in UCS2 and number has '+'.
- let contactUCS2 = {
- alphaId: "火狐",
- number: "+1234567890"
- };
-
- writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
- contactUCS2.alphaId,
- contactUCS2.number, 0xff);
- contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(writtenContact.alphaId, contactR.alphaId);
- equal(writtenContact.number, contactR.number);
- equal(0xff, contactR.extRecordNumber);
-
- // Write a null contact (Removal).
- writtenContact = helper.writeAlphaIdDiallingNumber(recordSize);
- contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(contactR, null);
- equal(writtenContact.alphaId, "");
- equal(writtenContact.number, "");
-
- // Write a longer alphaId/dialling number
- // Dialling Number : Maximum 20 digits(10 octets).
- // Alpha Identifier: 32(recordSize) - 14 (10 octets for Dialling Number, 1
- // octet for TON/NPI, 1 for number length octet, and 2 for
- // Ext) = Maximum 18 octets.
- let longContact = {
- alphaId: "AAAAAAAAABBBBBBBBBCCCCCCCCC",
- number: "123456789012345678901234567890",
- };
-
- writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
- longContact.alphaId,
- longContact.number, 0xff);
- contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(writtenContact.alphaId, contactR.alphaId);
- equal(writtenContact.number, contactR.number);
- equal(0xff, contactR.extRecordNumber);
-
- // Add '+' to number and test again.
- longContact.number = "+123456789012345678901234567890";
- writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
- longContact.alphaId,
- longContact.number, 0xff);
- contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(writtenContact.alphaId, contactR.alphaId);
- equal(writtenContact.number, contactR.number);
- equal(0xff, contactR.extRecordNumber);
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeDiallingNumber
- */
-add_test(function test_write_dialling_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.ICCPDUHelper;
-
- // with +
- let number = "+123456";
- let len = 4;
- helper.writeDiallingNumber(number);
- equal(helper.readDiallingNumber(len), number);
-
- // without +
- number = "987654";
- len = 4;
- helper.writeDiallingNumber(number);
- equal(helper.readDiallingNumber(len), number);
-
- number = "9876543";
- len = 5;
- helper.writeDiallingNumber(number);
- equal(helper.readDiallingNumber(len), number);
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readNumberWithLength
- */
-add_test(function test_read_number_with_length() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- let numbers = [
- {
- number: "123456789",
- expectedNumber: "123456789"
- },
- {
- number: "",
- expectedNumber: ""
- },
- // Invalid length of BCD number/SSC contents
- {
- number: "12345678901234567890123",
- expectedNumber: ""
- },
- ];
-
- // To avoid obtaining wrong buffer content.
- context.Buf.seekIncoming = function(offset) {
- };
-
- function do_test(aNumber, aExpectedNumber) {
- iccHelper.readDiallingNumber = function(numLen) {
- return aNumber.substring(0, numLen);
- };
-
- if (aNumber) {
- helper.writeHexOctet(aNumber.length + 1);
- } else {
- helper.writeHexOctet(0xff);
- }
-
- equal(iccHelper.readNumberWithLength(), aExpectedNumber);
- }
-
- for (let i = 0; i < numbers.length; i++) {
- do_test(numbers[i].number, numbers[i].expectedNumber);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeNumberWithLength
- */
-add_test(function test_write_number_with_length() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- function test(number, expectedNumber) {
- expectedNumber = expectedNumber || number;
- let writeNumber = iccHelper.writeNumberWithLength(number);
- equal(writeNumber, expectedNumber);
- let numLen = helper.readHexOctet();
- equal(expectedNumber, iccHelper.readDiallingNumber(numLen));
- for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
- equal(0xff, helper.readHexOctet());
- }
- }
-
- // without +
- test("123456789");
-
- // with +
- test("+987654321");
-
- // extended BCD coding
- test("1*2#3,4*5#6,");
-
- // with + and extended BCD coding
- test("+1*2#3,4*5#6,");
-
- // non-supported characters should not be written.
- test("(1)23-456+789", "123456789");
-
- test("++(01)2*3-4#5,6+7(8)9*0#1,", "+012*34#5,6789*0#1,");
-
- // over maximum 20 digits should be truncated.
- test("012345678901234567890123456789", "01234567890123456789");
-
- // null
- iccHelper.writeNumberWithLength(null);
- for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES + 1); i++) {
- equal(0xff, helper.readHexOctet());
- }
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js
deleted file mode 100644
index 00c55873d..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js
+++ /dev/null
@@ -1,1080 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify ICCRecordHelper.readPBR
- */
-add_test(function test_read_pbr() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let pbr_1 = [
- 0xa8, 0x05, 0xc0, 0x03, 0x4f, 0x3a, 0x01
- ];
-
- // Write data size
- buf.writeInt32(pbr_1.length * 2);
-
- // Write pbr
- for (let i = 0; i < pbr_1.length; i++) {
- helper.writeHexOctet(pbr_1[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(pbr_1.length * 2);
-
- options.totalRecords = 2;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- io.loadNextRecord = function fakeLoadNextRecord(options) {
- let pbr_2 = [
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- ];
-
- options.p1++;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let successCb = function successCb(pbrs) {
- equal(pbrs[0].adn.fileId, 0x4f3a);
- equal(pbrs.length, 1);
- };
-
- let errorCb = function errorCb(errorMsg) {
- do_print("Reading EF_PBR failed, msg = " + errorMsg);
- ok(false);
- };
-
- record.readPBR(successCb, errorCb);
-
- // Check cache pbrs when 2nd call
- let ifLoadEF = false;
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- ifLoadEF = true;
- }
- record.readPBR(successCb, errorCb);
- ok(!ifLoadEF);
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.readEmail
- */
-add_test(function test_read_email() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let recordSize;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let email_1 = [
- 0x65, 0x6D, 0x61, 0x69, 0x6C,
- 0x00, 0x6D, 0x6F, 0x7A, 0x69,
- 0x6C, 0x6C, 0x61, 0x2E, 0x63,
- 0x6F, 0x6D, 0x02, 0x23];
-
- // Write data size
- buf.writeInt32(email_1.length * 2);
-
- // Write email
- for (let i = 0; i < email_1.length; i++) {
- helper.writeHexOctet(email_1[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(email_1.length * 2);
-
- recordSize = email_1.length;
- options.recordSize = recordSize;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function doTestReadEmail(type, expectedResult) {
- let fileId = 0x6a75;
- let recordNumber = 1;
-
- // fileId and recordNumber are dummy arguments.
- record.readEmail(fileId, type, recordNumber, function(email) {
- equal(email, expectedResult);
- });
- };
-
- doTestReadEmail(ICC_USIM_TYPE1_TAG, "email@mozilla.com$#");
- doTestReadEmail(ICC_USIM_TYPE2_TAG, "email@mozilla.com");
- equal(record._emailRecordSize, recordSize);
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateEmail
- */
-add_test(function test_update_email() {
- const recordSize = 0x20;
- const recordNumber = 1;
- const fileId = 0x4f50;
- const NUM_TESTS = 2;
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let ril = context.RIL;
- ril.appType = CARD_APPTYPE_USIM;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
- let pbr = {email: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
- adn: {sfi: 1}};
- let count = 0;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- function do_test(pbr, expectedEmail, expectedAdnRecordId) {
- buf.sendParcel = function() {
- count++;
-
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
- // p1.
- equal(this.readInt32(), recordNumber);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), recordSize);
-
- // data.
- let strLen = this.readInt32();
- let email;
- if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
- email = iccHelper.read8BitUnpackedToString(recordSize);
- } else {
- email = iccHelper.read8BitUnpackedToString(recordSize - 2);
- equal(pduHelper.readHexOctet(), pbr.adn.sfi);
- equal(pduHelper.readHexOctet(), expectedAdnRecordId);
- }
- this.readStringDelimiter(strLen);
- equal(email, expectedEmail);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
-
- if (count == NUM_TESTS) {
- run_next_test();
- }
- };
- recordHelper.updateEmail(pbr, recordNumber, expectedEmail, expectedAdnRecordId);
- }
-
- do_test(pbr, "test@mail.com");
- pbr.email.fileType = ICC_USIM_TYPE2_TAG;
- do_test(pbr, "test@mail.com", 1);
-});
-
-/**
- * Verify ICCRecordHelper.readANR
- */
-add_test(function test_read_anr() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let recordSize;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let anr_1 = [
- 0x01, 0x05, 0x81, 0x10, 0x32,
- 0x54, 0xF6, 0xFF, 0xFF];
-
- // Write data size
- buf.writeInt32(anr_1.length * 2);
-
- // Write anr
- for (let i = 0; i < anr_1.length; i++) {
- helper.writeHexOctet(anr_1[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(anr_1.length * 2);
-
- recordSize = anr_1.length;
- options.recordSize = recordSize;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function doTestReadAnr(fileType, expectedResult) {
- let fileId = 0x4f11;
- let recordNumber = 1;
-
- // fileId and recordNumber are dummy arguments.
- record.readANR(fileId, fileType, recordNumber, function(anr) {
- equal(anr, expectedResult);
- });
- };
-
- doTestReadAnr(ICC_USIM_TYPE1_TAG, "0123456");
- equal(record._anrRecordSize, recordSize);
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateANR
- */
-add_test(function test_update_anr() {
- const recordSize = 0x20;
- const recordNumber = 1;
- const fileId = 0x4f11;
- const NUM_TESTS = 2;
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let ril = context.RIL;
- ril.appType = CARD_APPTYPE_USIM;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
- let pbr = {anr0: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
- adn: {sfi: 1}};
- let count = 0;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- function do_test(pbr, expectedANR, expectedAdnRecordId) {
- buf.sendParcel = function() {
- count++;
-
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
- // p1.
- equal(this.readInt32(), recordNumber);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), recordSize);
-
- // data.
- let strLen = this.readInt32();
- // EF_AAS, ignore.
- pduHelper.readHexOctet();
- equal(iccHelper.readNumberWithLength(), expectedANR);
- // EF_CCP, ignore.
- pduHelper.readHexOctet();
- // EF_EXT1, ignore.
- pduHelper.readHexOctet();
- if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
- equal(pduHelper.readHexOctet(), pbr.adn.sfi);
- equal(pduHelper.readHexOctet(), expectedAdnRecordId);
- }
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
-
- if (count == NUM_TESTS) {
- run_next_test();
- }
- };
- recordHelper.updateANR(pbr, recordNumber, expectedANR, expectedAdnRecordId);
- }
-
- do_test(pbr, "+123456789");
- pbr.anr0.fileType = ICC_USIM_TYPE2_TAG;
- do_test(pbr, "123456789", 1);
-});
-
-/**
- * Verify ICCRecordHelper.readIAP
- */
-add_test(function test_read_iap() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let recordSize;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let iap_1 = [0x01, 0x02];
-
- // Write data size/
- buf.writeInt32(iap_1.length * 2);
-
- // Write iap.
- for (let i = 0; i < iap_1.length; i++) {
- helper.writeHexOctet(iap_1[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(iap_1.length * 2);
-
- recordSize = iap_1.length;
- options.recordSize = recordSize;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function doTestReadIAP(expectedIAP) {
- const fileId = 0x4f17;
- const recordNumber = 1;
-
- let successCb = function successCb(iap) {
- for (let i = 0; i < iap.length; i++) {
- equal(expectedIAP[i], iap[i]);
- }
- run_next_test();
- }.bind(this);
-
- let errorCb = function errorCb(errorMsg) {
- do_print(errorMsg);
- ok(false);
- run_next_test();
- }.bind(this);
-
- record.readIAP(fileId, recordNumber, successCb, errorCb);
- };
-
- doTestReadIAP([1, 2]);
-});
-
-/**
- * Verify ICCRecordHelper.updateIAP
- */
-add_test(function test_update_iap() {
- const recordSize = 2;
- const recordNumber = 1;
- const fileId = 0x4f17;
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- ril.appType = CARD_APPTYPE_USIM;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
- let count = 0;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- function do_test(expectedIAP) {
- buf.sendParcel = function() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
- // p1.
- equal(this.readInt32(), recordNumber);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), recordSize);
-
- // data.
- let strLen = this.readInt32();
- for (let i = 0; i < recordSize; i++) {
- equal(expectedIAP[i], pduHelper.readHexOctet());
- }
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
-
- run_next_test();
- };
- recordHelper.updateIAP(fileId, recordNumber, expectedIAP);
- }
-
- do_test([1, 2]);
-});
-
-/**
- * Verify ICCRecordHelper.readADNLike.
- */
-add_test(function test_read_adn_like() {
- const RECORD_SIZE = 0x20;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let ril = context.RIL;
-
- function do_test(extFileId, rawEF, expectedExtRecordNumber, expectedNumber) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(rawEF.length * 2);
-
- // Write adn
- for (let i = 0; i < rawEF.length; i += 2) {
- helper.writeHexOctet(parseInt(rawEF.substr(i, 2), 16));
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(rawEF.length * 2);
-
- options.p1 = 1;
- options.recordSize = RECORD_SIZE;
- options.totalRecords = 1;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readExtension = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess("1234");
- }
-
- let successCb = function successCb(contacts) {
- ok(contacts[0].number == expectedNumber);
- };
-
- let errorCb = function errorCb(errorMsg) {
- do_print("Reading ADNLike failed, msg = " + errorMsg);
- ok(false);
- };
-
- record.readADNLike(ICC_EF_ADN, extFileId, successCb, errorCb);
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- // Valid extension
- do_test(ICC_EF_EXT1,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ff01",
- 0x01,"998877665544332211001234");
- // Empty extension
- do_test(ICC_EF_EXT1,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ffff",
- 0xff, "99887766554433221100");
- // Unsupport extension
- do_test(null,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ffff",
- 0xff, "99887766554433221100");
- // Empty dialling number contact
- do_test(null,"436f6e74616374303031ffffffffffffffffffffffffffffffffffffffffffff",
- 0xff, "");
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateADNLike.
- */
-add_test(function test_update_adn_like() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let record = context.ICCRecordHelper;
- let io = context.ICCIOHelper;
- let pdu = context.ICCPDUHelper;
- let buf = context.Buf;
-
- ril.appType = CARD_APPTYPE_SIM;
- const recordSize = 0x20;
- let fileId;
-
- // Override.
- io.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- buf.sendParcel = function() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- equal(this.readString(), EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
-
- // p1.
- equal(this.readInt32(), 1);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), 0x20);
-
- // data.
- let contact = pdu.readAlphaIdDiallingNumber(0x20);
- equal(contact.alphaId, "test");
- equal(contact.number, "123456");
- equal(contact.extRecordNumber, "0xff");
-
- // pin2.
- if (fileId == ICC_EF_ADN) {
- equal(this.readString(), null);
- } else {
- equal(this.readString(), "1111");
- }
-
- // AID. Ignore because it's from modem.
- this.readInt32();
-
- if (fileId == ICC_EF_FDN) {
- run_next_test();
- }
- };
-
- fileId = ICC_EF_ADN;
- record.updateADNLike(fileId, 0xff,
- {recordId: 1, alphaId: "test", number: "123456"});
-
- fileId = ICC_EF_FDN;
- record.updateADNLike(fileId, 0xff,
- {recordId: 1, alphaId: "test", number: "123456"},
- "1111");
-});
-
-/**
- * Verify ICCRecordHelper.findFreeRecordId.
- */
-add_test(function test_find_free_record_id() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let ril = context.RIL;
-
- function writeRecord(record) {
- // Write data size
- buf.writeInt32(record.length * 2);
-
- for (let i = 0; i < record.length; i++) {
- pduHelper.writeHexOctet(record[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(record.length * 2);
- }
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Some random data.
- let record = [0x12, 0x34, 0x56, 0x78, 0x90];
- options.p1 = 1;
- options.totalRecords = 2;
- writeRecord(record);
- if (options.callback) {
- options.callback(options);
- }
- };
-
- ril.iccIO = function fakeIccIO(options) {
- // Unused bytes.
- let record = [0xff, 0xff, 0xff, 0xff, 0xff];
- writeRecord(record);
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let fileId = 0x0000; // Dummy.
- recordHelper.findFreeRecordId(
- fileId,
- function(recordId) {
- equal(recordId, 2);
- run_next_test();
- }.bind(this),
- function(errorMsg) {
- do_print(errorMsg);
- ok(false);
- run_next_test();
- }.bind(this));
-});
-
-/**
- * Verify ICCRecordHelper.fetchICCRecords.
- */
-add_test(function test_fetch_icc_recodes() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let iccRecord = context.ICCRecordHelper;
- let simRecord = context.SimRecordHelper;
- let ruimRecord = context.RuimRecordHelper;
- let fetchTag = 0x00;
-
- simRecord.fetchSimRecords = function() {
- fetchTag = 0x01;
- };
-
- ruimRecord.fetchRuimRecords = function() {
- fetchTag = 0x02;
- };
-
- RIL.appType = CARD_APPTYPE_SIM;
- iccRecord.fetchICCRecords();
- equal(fetchTag, 0x01);
-
- RIL.appType = CARD_APPTYPE_RUIM;
- iccRecord.fetchICCRecords();
- equal(fetchTag, 0x02);
-
- RIL.appType = CARD_APPTYPE_USIM;
- iccRecord.fetchICCRecords();
- equal(fetchTag, 0x01);
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_ICCID.
- */
-add_test(function test_handling_iccid() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.ICCRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- ril.reportStkServiceIsRunning = function fakeReportStkServiceIsRunning() {
- };
-
- function do_test(rawICCID, expectedICCID) {
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(rawICCID.length);
-
- // Write data
- for (let i = 0; i < rawICCID.length; i += 2) {
- helper.writeHexOctet(parseInt(rawICCID.substr(i, 2), 16));
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(rawICCID.length);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readICCID();
-
- equal(ril.iccInfo.iccid, expectedICCID);
- }
-
- // Invalid value 0xE at high nibbile + low nibbile contains 0xF.
- do_test("9868002E90909F001519", "89860020909");
- // Invalid value 0xD at low nibbile.
- do_test("986800D2909090001519", "8986002090909005191");
- // Invalid value 0xC at low nibbile.
- do_test("986800C2909090001519", "8986002090909005191");
- // Invalid value 0xB at low nibbile.
- do_test("986800B2909090001519", "8986002090909005191");
- // Invalid value 0xA at low nibbile.
- do_test("986800A2909090001519", "8986002090909005191");
- // Valid ICCID.
- do_test("98101430121181157002", "89014103211118510720");
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.readExtension
- */
-add_test(function test_read_extension() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function do_test(rawExtension, expectedExtensionNumber) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(rawExtension.length * 2);
-
- // Write ext
- for (let i = 0; i < rawExtension.length; i += 2) {
- helper.writeHexOctet(parseInt(rawExtension.substr(i, 2), 16));
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(rawExtension.length);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let successCb = function successCb(number) {
- do_print("extension number:" + number);
- equal(number, expectedExtensionNumber);
- };
-
- let errorCb = function errorCb() {
- ok(expectedExtensionNumber == null);
- };
-
- record.readExtension(0x6f4a, 1, successCb, errorCb);
- }
-
- // Test unsupported record type 0x01
- do_test("010a10325476981032547698ff", "");
- // Test invalid length 0xc1
- do_test("020c10325476981032547698ff", null);
- // Test extension chain which we don't support
- do_test("020a1032547698103254769802", "01234567890123456789");
- // Test valid Extension
- do_test("020a10325476981032547698ff", "01234567890123456789");
- // Test valid Extension
- do_test("0209103254769810325476ffff", "012345678901234567");
- // Test empty Extension
- do_test("02ffffffffffffffffffffffff", "");
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateExtension
- */
-add_test(function test_update_extension() {
- const RECORD_SIZE = 13;
- const RECORD_NUMBER = 1;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = RECORD_SIZE;
- ril.iccIO(options);
- };
-
- function do_test(fileId, number, expectedNumber) {
- buf.sendParcel = function() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- if (ril.appType == CARD_APPTYPE_SIM || ril.appType == CARD_APPTYPE_RUIM) {
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
- } else{
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
- }
-
- // p1.
- equal(this.readInt32(), RECORD_NUMBER);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), RECORD_SIZE);
-
- // data.
- let strLen = this.readInt32();
- // Extension record
- let recordType = pduHelper.readHexOctet();
-
- equal(recordType, 0x02);
- equal(pduHelper.readHexOctet(), 10);
- equal(
- pduHelper.readSwappedNibbleExtendedBcdString(EXT_MAX_NUMBER_DIGITS - 1),
- expectedNumber);
-
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
- };
-
- recordHelper.updateExtension(fileId, RECORD_NUMBER, number);
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
- // We don't support extension chain.
- do_test(ICC_EF_EXT1, "012345678901234567891234", "01234567890123456789");
-
- ril.appType = CARD_APPTYPE_USIM;
- do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
-
- ril.appType = CARD_APPTYPE_RUIM;
- do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.cleanEFRecord
- */
-add_test(function test_clean_ef_record() {
- const RECORD_SIZE = 13;
- const RECORD_NUMBER = 1;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = RECORD_SIZE;
- ril.iccIO(options);
- };
-
- function do_test(fileId) {
- buf.sendParcel = function() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- if (ril.appType == CARD_APPTYPE_SIM || ril.appType == CARD_APPTYPE_RUIM) {
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
- } else{
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
- }
-
- // p1.
- equal(this.readInt32(), RECORD_NUMBER);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), RECORD_SIZE);
-
- // data.
- let strLen = this.readInt32();
- // Extension record
- for (let i = 0; i < RECORD_SIZE; i++) {
- equal(pduHelper.readHexOctet(), 0xff);
- }
-
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
- };
-
- recordHelper.cleanEFRecord(fileId, RECORD_NUMBER);
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- do_test(ICC_EF_EXT1);
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.getADNLikeExtensionRecordNumber
- */
-add_test(function test_get_adn_like_extension_record_number() {
- const RECORD_SIZE = 0x20;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function do_test(rawEF, expectedRecordNumber) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(rawEF.length * 2);
-
- // Write ext
- for (let i = 0; i < rawEF.length; i += 2) {
- helper.writeHexOctet(parseInt(rawEF.substr(i, 2), 16));
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(rawEF.length);
- options.recordSize = RECORD_SIZE;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let isSuccess = false;
- let successCb = function successCb(number) {
- equal(number, expectedRecordNumber);
- isSuccess = true;
- };
-
- let errorCb = function errorCb(errorMsg) {
- do_print("Reading ADNLike failed, msg = " + errorMsg);
- ok(false);
- };
-
- record.getADNLikeExtensionRecordNumber(ICC_EF_ADN, 1, successCb, errorCb);
- ok(isSuccess);
- }
-
- // Valid Extension, Alpha Id(Encoded with GSM 8 bit): "Contact001",
- // Dialling Number: 99887766554433221100, Ext1: 0x01
- do_test("436f6e74616374303031ffffffffffffffff0b8199887766554433221100ff01", 0x01);
- // Empty Extension, Alpha Id(Encoded with GSM 8 bit): "Contact001", Ext1: 0xff
- do_test("436f6e74616374303031ffffffffffffffffffffffffffffffffffffffffffff", 0xff);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js
deleted file mode 100644
index b23d0b598..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js
+++ /dev/null
@@ -1,326 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify ICCUtilsHelper.isICCServiceAvailable.
- */
-add_test(function test_is_icc_service_available() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ICCUtilsHelper = context.ICCUtilsHelper;
- let RIL = context.RIL;
-
- function test_table(sst, geckoService, simEnabled, usimEnabled) {
- RIL.iccInfoPrivate.sst = sst;
- RIL.appType = CARD_APPTYPE_SIM;
- equal(ICCUtilsHelper.isICCServiceAvailable(geckoService), simEnabled);
- RIL.appType = CARD_APPTYPE_USIM;
- equal(ICCUtilsHelper.isICCServiceAvailable(geckoService), usimEnabled);
- }
-
- test_table([0x08], "ADN", true, false);
- test_table([0x08], "FDN", false, false);
- test_table([0x08], "SDN", false, true);
-
- run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.isGsm8BitAlphabet
- */
-add_test(function test_is_gsm_8bit_alphabet() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ICCUtilsHelper = context.ICCUtilsHelper;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- equal(ICCUtilsHelper.isGsm8BitAlphabet(langTable), true);
- equal(ICCUtilsHelper.isGsm8BitAlphabet(langShiftTable), true);
- equal(ICCUtilsHelper.isGsm8BitAlphabet("\uaaaa"), false);
-
- run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.parsePbrTlvs
- */
-add_test(function test_parse_pbr_tlvs() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
-
- let pbrTlvs = [
- {tag: ICC_USIM_TYPE1_TAG,
- length: 0x0F,
- value: [{tag: ICC_USIM_EFADN_TAG,
- length: 0x03,
- value: [0x4F, 0x3A, 0x02]},
- {tag: ICC_USIM_EFIAP_TAG,
- length: 0x03,
- value: [0x4F, 0x25, 0x01]},
- {tag: ICC_USIM_EFPBC_TAG,
- length: 0x03,
- value: [0x4F, 0x09, 0x04]}]
- },
- {tag: ICC_USIM_TYPE2_TAG,
- length: 0x05,
- value: [{tag: ICC_USIM_EFEMAIL_TAG,
- length: 0x03,
- value: [0x4F, 0x50, 0x0B]},
- {tag: ICC_USIM_EFANR_TAG,
- length: 0x03,
- value: [0x4F, 0x11, 0x02]},
- {tag: ICC_USIM_EFANR_TAG,
- length: 0x03,
- value: [0x4F, 0x12, 0x03]}]
- },
- {tag: ICC_USIM_TYPE3_TAG,
- length: 0x0A,
- value: [{tag: ICC_USIM_EFCCP1_TAG,
- length: 0x03,
- value: [0x4F, 0x3D, 0x0A]},
- {tag: ICC_USIM_EFEXT1_TAG,
- length: 0x03,
- value: [0x4F, 0x4A, 0x03]}]
- },
- ];
-
- let pbr = context.ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
- equal(pbr.adn.fileId, 0x4F3a);
- equal(pbr.iap.fileId, 0x4F25);
- equal(pbr.pbc.fileId, 0x4F09);
- equal(pbr.email.fileId, 0x4F50);
- equal(pbr.anr0.fileId, 0x4f11);
- equal(pbr.anr1.fileId, 0x4f12);
- equal(pbr.ccp1.fileId, 0x4F3D);
- equal(pbr.ext1.fileId, 0x4F4A);
-
- run_next_test();
-});
-
-/**
- * Verify MCC and MNC parsing
- */
-add_test(function test_mcc_mnc_parsing() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.ICCUtilsHelper;
-
- function do_test(imsi, mncLength, expectedMcc, expectedMnc) {
- let result = helper.parseMccMncFromImsi(imsi, mncLength);
-
- if (!imsi) {
- equal(result, null);
- return;
- }
-
- equal(result.mcc, expectedMcc);
- equal(result.mnc, expectedMnc);
- }
-
- // Test the imsi is null.
- do_test(null, null, null, null);
-
- // Test MCC is Taiwan
- do_test("466923202422409", 0x02, "466", "92");
- do_test("466923202422409", 0x03, "466", "923");
- do_test("466923202422409", null, "466", "92");
-
- // Test MCC is US
- do_test("310260542718417", 0x02, "310", "26");
- do_test("310260542718417", 0x03, "310", "260");
- do_test("310260542718417", null, "310", "260");
-
- run_next_test();
-});
-
-add_test(function test_get_network_name_from_icc() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ICCUtilsHelper = context.ICCUtilsHelper;
-
- function testGetNetworkNameFromICC(operatorData, expectedResult) {
- let result = ICCUtilsHelper.getNetworkNameFromICC(operatorData.mcc,
- operatorData.mnc,
- operatorData.lac);
-
- if (expectedResult == null) {
- equal(result, expectedResult);
- } else {
- equal(result.fullName, expectedResult.longName);
- equal(result.shortName, expectedResult.shortName);
- }
- }
-
- // Before EF_OPL and EF_PNN have been loaded.
- testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000}, null);
- testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x2000}, null);
-
- // Set HPLMN
- RIL.iccInfo.mcc = "123";
- RIL.iccInfo.mnc = "456";
-
- RIL.voiceRegistrationState = {
- cell: {
- gsmLocationAreaCode: 0x1000
- }
- };
- RIL.operator = {};
-
- // Set EF_PNN
- RIL.iccInfoPrivate = {
- PNN: [
- {"fullName": "PNN1Long", "shortName": "PNN1Short"},
- {"fullName": "PNN2Long", "shortName": "PNN2Short"},
- {"fullName": "PNN3Long", "shortName": "PNN3Short"},
- {"fullName": "PNN4Long", "shortName": "PNN4Short"},
- {"fullName": "PNN5Long", "shortName": "PNN5Short"},
- {"fullName": "PNN6Long", "shortName": "PNN6Short"},
- {"fullName": "PNN7Long", "shortName": "PNN7Short"},
- {"fullName": "PNN8Long", "shortName": "PNN8Short"}
- ]
- };
-
- // EF_OPL isn't available
- ICCUtilsHelper.isICCServiceAvailable = function fakeIsICCServiceAvailable(service) {
- return false;
- };
-
- // EF_OPL isn't available and current isn't in HPLMN,
- testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x1000}, null);
-
- // EF_OPL isn't available and current is in HPLMN,
- // the first record of PNN should be returned.
- testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000},
- {longName: "PNN1Long", shortName: "PNN1Short"});
-
- // EF_OPL is available
- ICCUtilsHelper.isICCServiceAvailable = function fakeIsICCServiceAvailable(service) {
- return service === "OPL";
- };
-
- // Set EF_OPL
- RIL.iccInfoPrivate.OPL = [
- {
- "mcc": "123",
- "mnc": "456",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 4
- },
- {
- "mcc": "321",
- "mnc": "654",
- "lacTacStart": 0,
- "lacTacEnd": 0x0010,
- "pnnRecordId": 3
- },
- {
- "mcc": "321",
- "mnc": "654",
- "lacTacStart": 0x0100,
- "lacTacEnd": 0x1010,
- "pnnRecordId": 2
- },
- {
- "mcc": ";;;",
- "mnc": "01",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 5
- },
- {
- "mcc": "00;",
- "mnc": "02",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 6
- },
- {
- "mcc": "001",
- "mnc": ";;",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 7
- },
- {
- "mcc": "002",
- "mnc": "0;",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 8
- }
- ];
-
- // Both EF_PNN and EF_OPL are presented, and current PLMN is HPLMN,
- testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000},
- {longName: "PNN4Long", shortName: "PNN4Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the second PNN record.
- testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x1000},
- {longName: "PNN2Long", shortName: "PNN2Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the thrid PNN record.
- testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x0001},
- {longName: "PNN3Long", shortName: "PNN3Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the 5th PNN record after wild char (ie: ';') handling.
- testGetNetworkNameFromICC({mcc: "001", mnc: "01", lac: 0x0001},
- {longName: "PNN5Long", shortName: "PNN5Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the 6th PNN record after wild char (ie: ';') handling.
- testGetNetworkNameFromICC({mcc: "001", mnc: "02", lac: 0x0001},
- {longName: "PNN6Long", shortName: "PNN6Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the 7th PNN record after wild char (ie: ';') handling.
- testGetNetworkNameFromICC({mcc: "001", mnc: "03", lac: 0x0001},
- {longName: "PNN7Long", shortName: "PNN7Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the 8th PNN record after wild char (ie: ';') handling.
- testGetNetworkNameFromICC({mcc: "002", mnc: "03", lac: 0x0001},
- {longName: "PNN8Long", shortName: "PNN8Short"});
-
- run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.isCphsServiceAvailable.
- */
-add_test(function test_is_cphs_service_available() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ICCUtilsHelper = context.ICCUtilsHelper;
- let RIL = context.RIL;
- RIL.iccInfoPrivate.cphsSt = new Uint8Array(2);
-
- function test_table(cphsSt, geckoService) {
- RIL.iccInfoPrivate.cphsSt.set(cphsSt);
-
- for (let service in GECKO_ICC_SERVICES.cphs) {
- equal(ICCUtilsHelper.isCphsServiceAvailable(service),
- geckoService == service);
- }
- }
-
- test_table([0x03, 0x00], "CSP");
- test_table([0x0C, 0x00], "SST");
- test_table([0x30, 0x00], "MBN");
- test_table([0xC0, 0x00], "ONSF");
- test_table([0x00, 0x03], "INFO_NUM");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js b/dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js
deleted file mode 100644
index 8bcd26ffe..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js
+++ /dev/null
@@ -1,771 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify IconLoader.loadIcons with recordNumbers array length being 1.
- * Query images of one record at a time.
- */
-add_test(function test_load_icon_basic() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let iconLoader = context.IconLoader;
- let simRecordHelper = context.SimRecordHelper;
-
- let test_data = [
- {rawData: [
- {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- width: 0x10,
- height: 0x10,
- body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
- 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff]}],
- expected: [
- {width: 0x10,
- height: 0x10,
- pixels: [/* 1st byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 2nd byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 3rd byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 4th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 5th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 6th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 7th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 8th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 9th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 10th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 11th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 12th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 13th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 14th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 15th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 16th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 17th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 18th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 19th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 20th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 21th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 22th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 23th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 24th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 25th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 26th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 27th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 28th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 29th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 30th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 31th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 32th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff]}]},
- {rawData: [
- {codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- width: 0x10,
- height: 0x10,
- bitsPerImgPoint: 0x04,
- numOfClutEntries: 0x10,
- body: [0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xcc, 0xfc, 0xcc,
- 0xcf, 0xcf, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf,
- 0xcc, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcc,
- 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc,
- 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc, 0xcf,
- 0xfc, 0xcc, 0xfc, 0xcc, 0xcf, 0xcf, 0xfc, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
- 0x99, 0x99],
- clut: [0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
- 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80,
- 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80,
- 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xff]}],
- expected: [
- {width: 0x10,
- height: 0x10,
- pixels: [0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff]}]},
- {rawData: [
- {codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- width: 0x03,
- height: 0x03,
- bitsPerImgPoint: 0x05,
- numOfClutEntries: 0x20,
- body: [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
- clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
- 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
- 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f]},
- {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- width: 0x10,
- height: 0x10,
- body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
- 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff]}],
- expected: [
- {width: 0x03,
- height: 0x03,
- pixels: [0x000102ff, 0x060708ff, 0x0c0d0eff, 0x121314ff, 0x18191aff,
- 0x1e1f20ff, 0x242526ff, 0x2a2b2cff, 0x333435ff]},
- {width: 0x10,
- height: 0x10,
- pixels: [/* 1st byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 2nd byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 3rd byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 4th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 5th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 6th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 7th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 8th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 9th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 10th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 11th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 12th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 13th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 14th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 15th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 16th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 17th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 18th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 19th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 20th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 21th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 22th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 23th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 24th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 25th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 26th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 27th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 28th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 29th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 30th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 31th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 32th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff]}]},
- {rawData: [
- {codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- width: 0x04,
- height: 0x04,
- bitsPerImgPoint: 0x04,
- numOfClutEntries: 0x10,
- body: [0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88],
- clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
- 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f]}],
- expected: [
- {width: 0x04,
- height: 0x04,
- pixels: [0x00000000, 0x00000000, 0x2a2b2cff, 0x2a2b2cff, 0x272829ff,
- 0x272829ff, 0x242526ff, 0x242526ff, 0x212223ff, 0x212223ff,
- 0x1e1f20ff, 0x1e1f20ff, 0x1b1c1dff, 0x1b1c1dff, 0x18191aff,
- 0x18191aff]}]}];
-
- function do_test(test_data, expected) {
- simRecordHelper.readIMG = function fakeReadIMG(recordNumber, onsuccess, onerror) {
- onsuccess(test_data);
- };
-
- let onsuccess = function(icons) {
- // Query one record at a time.
- equal(icons.length, 1);
- equal(icons[0].length, expected.length);
- for (let i = 0; i < icons[0].length; i++) {
- // Read the i_th image of the record.
- let icon = icons[0][i];
- let exp = expected[i];
- equal(icon.width, exp.width);
- equal(icon.height, exp.height);
- equal(icon.pixels.length, exp.pixels.length);
- for (let j = 0; j < icon.pixels.length; j++) {
- equal(icon.pixels[j], exp.pixels[j]);
- }
- }
- };
-
- iconLoader.loadIcons([0], onsuccess);
- }
-
- for (let i = 0; i < test_data.length; i++) {
- do_test(test_data[i].rawData, test_data[i].expected);
- }
-
- run_next_test();
-});
-
-/**
- * Verify IconLoader.loadIcons.
- */
-add_test(function test_load_icons() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let iconLoader = context.IconLoader;
- let simRecordHelper = context.SimRecordHelper;
-
- let test_data = {
- rawData: [
- // Record 1.
- [{codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- width: 0x10,
- height: 0x10,
- body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
- 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff]}],
- // Record 2.
- [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- width: 0x10,
- height: 0x10,
- bitsPerImgPoint: 0x04,
- numOfClutEntries: 0x10,
- body: [0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xcc, 0xfc, 0xcc,
- 0xcf, 0xcf, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf,
- 0xcc, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcc,
- 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc,
- 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc, 0xcf,
- 0xfc, 0xcc, 0xfc, 0xcc, 0xcf, 0xcf, 0xfc, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
- 0x99, 0x99],
- clut: [0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
- 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80,
- 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80,
- 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xff]}],
- // Record 3.
- [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- width: 0x03,
- height: 0x03,
- bitsPerImgPoint: 0x05,
- numOfClutEntries: 0x20,
- body: [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
- clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
- 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
- 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f]},
- {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- width: 0x10,
- height: 0x10,
- body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
- 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff]}],
- // Record 4.
- [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- width: 0x04,
- height: 0x04,
- bitsPerImgPoint: 0x04,
- numOfClutEntries: 0x10,
- body: [0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88],
- clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
- 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f]}]],
- expected: [
- // Record 1.
- [{width: 0x10,
- height: 0x10,
- pixels: [/* 1st byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 2nd byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 3rd byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 4th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 5th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 6th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 7th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 8th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 9th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 10th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 11th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 12th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 13th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 14th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 15th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 16th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 17th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 18th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 19th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 20th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 21th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 22th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 23th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 24th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 25th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 26th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 27th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 28th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 29th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 30th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 31th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 32th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff]}],
- // Record 2.
- [{width: 0x10,
- height: 0x10,
- pixels: [0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff]}],
- // Record 3.
- [{width: 0x03,
- height: 0x03,
- pixels: [0x000102ff, 0x060708ff, 0x0c0d0eff, 0x121314ff, 0x18191aff,
- 0x1e1f20ff, 0x242526ff, 0x2a2b2cff, 0x333435ff]},
- {width: 0x10,
- height: 0x10,
- pixels: [/* 1st byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 2nd byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 3rd byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 4th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 5th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 6th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 7th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 8th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 9th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 10th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 11th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 12th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 13th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 14th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 15th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 16th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 17th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 18th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 19th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 20th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 21th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 22th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 23th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 24th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 25th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 26th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 27th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 28th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 29th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 30th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 31th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 32th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff]}],
- // Record 4.
- [{width: 0x04,
- height: 0x04,
- pixels: [0x00000000, 0x00000000, 0x2a2b2cff, 0x2a2b2cff, 0x272829ff,
- 0x272829ff, 0x242526ff, 0x242526ff, 0x212223ff, 0x212223ff,
- 0x1e1f20ff, 0x1e1f20ff, 0x1b1c1dff, 0x1b1c1dff, 0x18191aff,
- 0x18191aff]}]]};
-
- function do_test() {
- simRecordHelper.readIMG = function fakeReadIMG(recordNumber, onsuccess, onerror) {
- onsuccess(test_data.rawData[recordNumber]);
- };
-
- let onsuccess = function(icons) {
- equal(icons.length, test_data.expected.length);
- for (let i = 0; i < icons.length; i++) {
- for (let j = 0; j < icons[i].length; j++) {
- // Read the j_th image from the i_th record.
- let icon = icons[i][j];
- let expected = test_data.expected[i][j];
- equal(icon.width, expected.width);
- equal(icon.height, expected.height);
- equal(icon.pixels.length, expected.pixels.length);
- for (let k = 0; k < icon.pixels.length; k++) {
- equal(icon.pixels[k], expected.pixels[k]);
- }
- }
- }
- };
-
- let recordNumbers = [0, 1, 2, 3];
- iconLoader.loadIcons(recordNumbers, onsuccess);
- }
-
- do_test();
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js
deleted file mode 100644
index 6500cc663..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js
+++ /dev/null
@@ -1,1648 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify reading EF_AD and parsing MCC/MNC
- */
-add_test(function test_reading_ad_and_parsing_mcc_mnc() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function do_test(mncLengthInEf, imsi, expectedMcc, expectedMnc) {
- ril.iccInfoPrivate.imsi = imsi;
-
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- let ad = [0x00, 0x00, 0x00];
- if (typeof mncLengthInEf === 'number') {
- ad.push(mncLengthInEf);
- }
-
- // Write data size
- buf.writeInt32(ad.length * 2);
-
- // Write data
- for (let i = 0; i < ad.length; i++) {
- helper.writeHexOctet(ad[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(ad.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readAD();
-
- equal(ril.iccInfo.mcc, expectedMcc);
- equal(ril.iccInfo.mnc, expectedMnc);
- }
-
- do_test(undefined, "466923202422409", "466", "92" );
- do_test(0x00, "466923202422409", "466", "92" );
- do_test(0x01, "466923202422409", "466", "92" );
- do_test(0x02, "466923202422409", "466", "92" );
- do_test(0x03, "466923202422409", "466", "923");
- do_test(0x04, "466923202422409", "466", "92" );
- do_test(0xff, "466923202422409", "466", "92" );
-
- do_test(undefined, "310260542718417", "310", "260");
- do_test(0x00, "310260542718417", "310", "260");
- do_test(0x01, "310260542718417", "310", "260");
- do_test(0x02, "310260542718417", "310", "26" );
- do_test(0x03, "310260542718417", "310", "260");
- do_test(0x04, "310260542718417", "310", "260");
- do_test(0xff, "310260542718417", "310", "260");
-
- run_next_test();
-});
-
-add_test(function test_reading_optional_efs() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let gsmPdu = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function buildSST(supportedEf) {
- let sst = [];
- let len = supportedEf.length;
- for (let i = 0; i < len; i++) {
- let index, bitmask, iccService;
- if (ril.appType === CARD_APPTYPE_SIM) {
- iccService = GECKO_ICC_SERVICES.sim[supportedEf[i]];
- iccService -= 1;
- index = Math.floor(iccService / 4);
- bitmask = 2 << ((iccService % 4) << 1);
- } else if (ril.appType === CARD_APPTYPE_USIM){
- iccService = GECKO_ICC_SERVICES.usim[supportedEf[i]];
- iccService -= 1;
- index = Math.floor(iccService / 8);
- bitmask = 1 << ((iccService % 8) << 0);
- }
-
- if (sst) {
- sst[index] |= bitmask;
- }
- }
- return sst;
- }
-
- ril.updateCellBroadcastConfig = function fakeUpdateCellBroadcastConfig() {
- // Ignore updateCellBroadcastConfig after reading SST
- };
-
- function do_test(sst, supportedEf) {
- // Clone supportedEf to local array for testing
- let testEf = supportedEf.slice(0);
-
- record.readMSISDN = function fakeReadMSISDN() {
- testEf.splice(testEf.indexOf("MSISDN"), 1);
- };
-
- record.readMBDN = function fakeReadMBDN() {
- testEf.splice(testEf.indexOf("MDN"), 1);
- };
-
- record.readMWIS = function fakeReadMWIS() {
- testEf.splice(testEf.indexOf("MWIS"), 1);
- };
-
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(sst.length * 2);
-
- // Write data
- for (let i = 0; i < sst.length; i++) {
- gsmPdu.writeHexOctet(sst[i] || 0);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(sst.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
-
- if (testEf.length !== 0) {
- do_print("Un-handled EF: " + JSON.stringify(testEf));
- ok(false);
- }
- };
-
- record.readSST();
- }
-
- // TODO: Add all necessary optional EFs eventually
- let supportedEf = ["MSISDN", "MDN", "MWIS"];
- ril.appType = CARD_APPTYPE_SIM;
- do_test(buildSST(supportedEf), supportedEf);
- ril.appType = CARD_APPTYPE_USIM;
- do_test(buildSST(supportedEf), supportedEf);
-
- run_next_test();
-});
-
-/**
- * Verify fetchSimRecords.
- */
-add_test(function test_fetch_sim_records() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let iccRecord = context.ICCRecordHelper;
- let simRecord = context.SimRecordHelper;
-
- function testFetchSimRecordes(expectCalled, expectCphsSuccess) {
- let ifCalled = [];
-
- RIL.getIMSI = function() {
- ifCalled.push("getIMSI");
- };
-
- simRecord.readAD = function() {
- ifCalled.push("readAD");
- };
-
- simRecord.readCphsInfo = function(onsuccess, onerror) {
- ifCalled.push("readCphsInfo");
- if (expectCphsSuccess) {
- onsuccess();
- } else {
- onerror();
- }
- };
-
- simRecord.readSST = function() {
- ifCalled.push("readSST");
- };
-
- simRecord.fetchSimRecords();
-
- for (let i = 0; i < expectCalled.length; i++ ) {
- if (ifCalled[i] != expectCalled[i]) {
- do_print(expectCalled[i] + " is not called.");
- ok(false);
- }
- }
- }
-
- let expectCalled = ["getIMSI", "readAD", "readCphsInfo", "readSST"];
- testFetchSimRecordes(expectCalled, true);
- testFetchSimRecordes(expectCalled, false);
-
- run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.readMWIS
- */
-add_test(function test_read_mwis() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let recordHelper = context.SimRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let mwisData;
- let postedMessage;
-
- worker.postMessage = function fakePostMessage(message) {
- postedMessage = message;
- };
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- if (mwisData) {
- // Write data size
- buf.writeInt32(mwisData.length * 2);
-
- // Write MWIS
- for (let i = 0; i < mwisData.length; i++) {
- helper.writeHexOctet(mwisData[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(mwisData.length * 2);
-
- options.recordSize = mwisData.length;
- if (options.callback) {
- options.callback(options);
- }
- } else {
- do_print("mwisData[] is not set.");
- }
- };
-
- function buildMwisData(isActive, msgCount) {
- if (msgCount < 0 || msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) {
- msgCount = 0;
- } else if (msgCount > 255) {
- msgCount = 255;
- }
-
- mwisData = [ (isActive) ? 0x01 : 0x00,
- msgCount,
- 0xFF, 0xFF, 0xFF ];
- }
-
- function do_test(isActive, msgCount) {
- buildMwisData(isActive, msgCount);
- recordHelper.readMWIS();
-
- equal("iccmwis", postedMessage.rilMessageType);
- equal(isActive, postedMessage.mwi.active);
- equal((isActive) ? msgCount : 0, postedMessage.mwi.msgCount);
- }
-
- do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
- do_test(true, 1);
- do_test(true, 255);
-
- do_test(false, 0);
- do_test(false, 255); // Test the corner case when mwi is disable with incorrect msgCount.
-
- run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.updateMWIS
- */
-add_test(function test_update_mwis() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- ril.appType = CARD_APPTYPE_USIM;
- ril.iccInfoPrivate.mwis = [0x00, 0x00, 0x00, 0x00, 0x00];
- let recordHelper = context.SimRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
- let recordSize = ril.iccInfoPrivate.mwis.length;
- let recordNum = 1;
-
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- function do_test(isActive, count) {
- let mwis = ril.iccInfoPrivate.mwis;
- let isUpdated = false;
-
- function buildMwisData() {
- let result = mwis.slice(0);
- result[0] = isActive? (mwis[0] | 0x01) : (mwis[0] & 0xFE);
- result[1] = (count === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : count;
-
- return result;
- }
-
- buf.sendParcel = function() {
- isUpdated = true;
-
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), ICC_EF_MWIS);
-
- // pathId.
- equal(this.readString(),
- EF_PATH_MF_SIM + ((ril.appType === CARD_APPTYPE_USIM) ? EF_PATH_ADF_USIM : EF_PATH_DF_GSM));
-
- // p1.
- equal(this.readInt32(), recordNum);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), recordSize);
-
- // data.
- let strLen = this.readInt32();
- equal(recordSize * 2, strLen);
- let expectedMwis = buildMwisData();
- for (let i = 0; i < recordSize; i++) {
- equal(expectedMwis[i], pduHelper.readHexOctet());
- }
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
- };
-
- ok(!isUpdated);
-
- recordHelper.updateMWIS({ active: isActive,
- msgCount: count });
-
- ok((ril.iccInfoPrivate.mwis) ? isUpdated : !isUpdated);
- }
-
- do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
- do_test(true, 1);
- do_test(true, 255);
-
- do_test(false, 0);
-
- // Test if Path ID is correct for SIM.
- ril.appType = CARD_APPTYPE_SIM;
- do_test(false, 0);
-
- // Test if loadLinearFixedEF() is not invoked in updateMWIS() when
- // EF_MWIS is not loaded/available.
- delete ril.iccInfoPrivate.mwis;
- do_test(false, 0);
-
- run_next_test();
-});
-
-/**
- * Verify the call flow of receiving Class 2 SMS stored in SIM:
- * 1. UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM.
- * 2. SimRecordHelper.readSMS().
- * 3. sendChromeMessage() with rilMessageType == "sms-received".
- */
-add_test(function test_read_new_sms_on_sim() {
- // Instead of reusing newUint8Worker defined in this file,
- // we define our own worker to fake the methods in WorkerBuffer dynamically.
- function newSmsOnSimWorkerHelper() {
- let _postedMessage;
- let _worker = newWorker({
- postRILMessage: function(data) {
- },
- postMessage: function(message) {
- _postedMessage = message;
- }
- });
-
- _worker.debug = do_print;
-
- return {
- get postedMessage() {
- return _postedMessage;
- },
- get worker() {
- return _worker;
- },
- fakeWokerBuffer: function() {
- let context = _worker.ContextPool._contexts[0];
- let index = 0; // index for read
- let buf = [];
- context.Buf.writeUint8 = function(value) {
- buf.push(value);
- };
- context.Buf.readUint8 = function() {
- return buf[index++];
- };
- context.Buf.seekIncoming = function(offset) {
- index += offset;
- };
- context.Buf.getReadAvailable = function() {
- return buf.length - index;
- };
- }
- };
- }
-
- let workerHelper = newSmsOnSimWorkerHelper();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.ICCIOHelper.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // SimStatus: Unread, SMSC:+0123456789, Sender: +9876543210, Text: How are you?
- let SimSmsPduHex = "0306911032547698040A9189674523010000208062917314080CC8F71D14969741F977FD07"
- // In 4.2.25 EF_SMS Short Messages of 3GPP TS 31.102:
- // 1. Record length == 176 bytes.
- // 2. Any bytes in the record following the TPDU shall be filled with 'FF'.
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
-
- workerHelper.fakeWokerBuffer();
-
- context.Buf.writeString(SimSmsPduHex);
-
- options.recordSize = 176; // Record length is fixed to 176 bytes.
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function newSmsOnSimParcel() {
- let data = new Uint8Array(4 + 4); // Int32List with 1 element.
- let offset = 0;
-
- function writeInt(value) {
- data[offset++] = value & 0xFF;
- data[offset++] = (value >> 8) & 0xFF;
- data[offset++] = (value >> 16) & 0xFF;
- data[offset++] = (value >> 24) & 0xFF;
- }
-
- writeInt(1); // Length of Int32List
- writeInt(1); // RecordNum = 1.
-
- return newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM,
- data);
- }
-
- function do_test() {
- worker.onRILMessage(0, newSmsOnSimParcel());
-
- let postedMessage = workerHelper.postedMessage;
-
- equal("sms-received", postedMessage.rilMessageType);
- equal("+0123456789", postedMessage.SMSC);
- equal("+9876543210", postedMessage.sender);
- equal("How are you?", postedMessage.body);
- }
-
- do_test();
-
- run_next_test();
-});
-
-/**
- * Verify the result of updateDisplayCondition after reading EF_SPDI | EF_SPN.
- */
-add_test(function test_update_display_condition() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function do_test_spdi() {
- // No EF_SPN, but having EF_SPDI.
- // It implies "ril.iccInfoPrivate.spnDisplayCondition = undefined;".
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // PLMN lists are : 234-136 and 466-92.
- let spdi = [0xA3, 0x0B, 0x80, 0x09, 0x32, 0x64, 0x31, 0x64, 0x26, 0x9F,
- 0xFF, 0xFF, 0xFF];
-
- // Write data size.
- buf.writeInt32(spdi.length * 2);
-
- // Write data.
- for (let i = 0; i < spdi.length; i++) {
- helper.writeHexOctet(spdi[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(spdi.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readSPDI();
-
- equal(ril.iccInfo.isDisplayNetworkNameRequired, true);
- equal(ril.iccInfo.isDisplaySpnRequired, false);
- }
-
- function do_test_spn(displayCondition,
- expectedPlmnNameDisplay,
- expectedSpnDisplay) {
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // "Android" as Service Provider Name.
- let spn = [0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64];
- if (typeof displayCondition === 'number') {
- spn.unshift(displayCondition);
- }
-
- // Write data size.
- buf.writeInt32(spn.length * 2);
-
- // Write data.
- for (let i = 0; i < spn.length; i++) {
- helper.writeHexOctet(spn[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(spn.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readSPN();
-
- equal(ril.iccInfo.isDisplayNetworkNameRequired, expectedPlmnNameDisplay);
- equal(ril.iccInfo.isDisplaySpnRequired, expectedSpnDisplay);
- }
-
- // Create empty operator object.
- ril.operator = {};
- // Setup SIM MCC-MNC to 310-260 as home network.
- ril.iccInfo.mcc = 310;
- ril.iccInfo.mnc = 260;
-
- do_test_spdi();
-
- // No network.
- do_test_spn(0x00, true, true);
- do_test_spn(0x01, true, true);
- do_test_spn(0x02, true, false);
- do_test_spn(0x03, true, false);
-
- // Home network.
- ril.operator.mcc = 310;
- ril.operator.mnc = 260;
- do_test_spn(0x00, false, true);
- do_test_spn(0x01, true, true);
- do_test_spn(0x02, false, true);
- do_test_spn(0x03, true, true);
-
- // Not HPLMN but in PLMN list.
- ril.iccInfoPrivate.SPDI = [{"mcc":"234","mnc":"136"},{"mcc":"466","mnc":"92"}];
- ril.operator.mcc = 466;
- ril.operator.mnc = 92;
- do_test_spn(0x00, false, true);
- do_test_spn(0x01, true, true);
- do_test_spn(0x02, false, true);
- do_test_spn(0x03, true, true);
- ril.iccInfoPrivate.SPDI = null; // reset SPDI to null;
-
- // Non-Home network.
- ril.operator.mcc = 466;
- ril.operator.mnc = 01;
- do_test_spn(0x00, true, true);
- do_test_spn(0x01, true, true);
- do_test_spn(0x02, true, false);
- do_test_spn(0x03, true, false);
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with ICC_IMG_CODING_SCHEME_BASIC
- */
-add_test(function test_reading_img_basic() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- {img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06],
- iidf: [
- [/* Header */
- 0x05, 0x05,
- /* Image body */
- 0x11, 0x33, 0x55, 0xfe]],
- expected: [
- {width: 0x05,
- height: 0x05,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x11, 0x33, 0x55, 0xfe]}]},
- {img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06,
- /* Padding */
- 0xff, 0xff],
- iidf: [
- [/* Header */
- 0x05, 0x05,
- /* Image body */
- 0x11, 0x33, 0x55, 0xfe]],
- expected: [
- {width: 0x05,
- height: 0x05,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x11, 0x33, 0x55, 0xfe]}]},
- {img: [0x02, 0x10, 0x01, 0x11, 0x4f, 0x04, 0x00, 0x05, 0x00, 0x04, 0x10,
- 0x01, 0x11, 0x4f, 0x05, 0x00, 0x05, 0x00, 0x04],
- iidf: [
- [/* Data offset */
- 0xff, 0xff, 0xff, 0xff, 0xff,
- /* Header */
- 0x10, 0x01,
- /* Image body */
- 0x11, 0x99,
- /* Trailing data */
- 0xff, 0xff, 0xff],
- [/* Data offset */
- 0xff, 0xff, 0xff, 0xff, 0xff,
- /* Header */
- 0x10, 0x01,
- /* Image body */
- 0x99, 0x11]],
- expected: [
- {width: 0x10,
- height: 0x01,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x11, 0x99]},
- {width: 0x10,
- height: 0x01,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x99, 0x11]}]},
- {img: [0x01, 0x28, 0x20, 0x11, 0x4f, 0xac, 0x00, 0x0b, 0x00, 0xa2],
- iidf: [
- [/* Data offset */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- /* Header */
- 0x28, 0x20,
- /* Image body */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
- 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
- 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
- 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
- 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x00, 0x01, 0x02,
- 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
- 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
- 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f]],
- expected: [
- {width: 0x28,
- height: 0x20,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
- 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
- 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
- 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
- 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
- 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x00, 0x01, 0x02, 0x03,
- 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
- 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
- 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f]}]}];
-
- function do_test(img, iidf, expected) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let instanceIndex = 0;
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf[instanceIndex].length * 2);
-
- // Write data
- for (let i = 0; i < iidf[instanceIndex].length; i++) {
- helper.writeHexOctet(iidf[instanceIndex][i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
-
- instanceIndex++;
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function(icons) {
- equal(icons.length, expected.length);
- for (let i = 0; i < icons.length; i++) {
- let icon = icons[i];
- let exp = expected[i];
- equal(icon.width, exp.width);
- equal(icon.height, exp.height);
- equal(icon.codingScheme, exp.codingScheme);
-
- equal(icon.body.length, exp.body.length);
- for (let j = 0; j < icon.body.length; j++) {
- equal(icon.body[j], exp.body[j]);
- }
- }
- };
- record.readIMG(0, onsuccess);
- }
-
- for (let i = 0; i< test_data.length; i++) {
- do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
- }
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with the case data length is not enough
- */
-add_test(function test_reading_img_length_error() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- {/* Offset length not enough, should be 4. */
- img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x04, 0x00, 0x06],
- iidf: [0xff, 0xff, 0xff, // Offset.
- 0x05, 0x05, 0x11, 0x22, 0x33, 0xfe]},
- {/* iidf data length not enough, should be 6. */
- img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06],
- iidf: [0x05, 0x05, 0x11, 0x22, 0x33]}];
-
- function do_test(img, iidf) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf.length * 2);
-
- // Write data
- for (let i = 0; i < iidf.length; i++) {
- helper.writeHexOctet(iidf[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function() {
- do_print("onsuccess shouldn't be called.");
- ok(false);
- };
-
- let onerror = function() {
- do_print("onerror called as expected.");
- ok(true);
- };
-
- record.readIMG(0, onsuccess, onerror);
- }
-
- for (let i = 0; i < test_data.length; i++) {
- do_test(test_data[i].img, test_data[i].iidf);
- }
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with an invalid fileId
- */
-add_test(function test_reading_img_invalid_fileId() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- // Test invalid fileId: 0x5f00.
- let img_test = [0x01, 0x05, 0x05, 0x11, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x06];
- let iidf_test = [0x05, 0x05, 0x11, 0x22, 0x33, 0xfe];
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img_test.length * 2);
-
- // Write data
- for (let i = 0; i < img_test.length; i++) {
- helper.writeHexOctet(img_test[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img_test.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf_test.length * 2);
-
- // Write data
- for (let i = 0; i < iidf_test.length; i++) {
- helper.writeHexOctet(iidf_test[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf_test.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function() {
- do_print("onsuccess shouldn't be called.");
- ok(false);
- };
-
- let onerror = function() {
- do_print("onerror called as expected.");
- ok(true);
- };
-
- record.readIMG(0, onsuccess, onerror);
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG with a wrong record length
- */
-add_test(function test_reading_img_wrong_record_length() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00],
- [0x02, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06]];
-
- function do_test(img) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function() {
- do_print("onsuccess shouldn't be called.");
- ok(false);
- };
-
- let onerror = function() {
- do_print("onerror called as expected.");
- ok(true);
- };
-
- record.readIMG(0, onsuccess, onerror);
- }
-
- for (let i = 0; i < test_data.length; i++) {
- do_test(test_data[i]);
- }
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with ICC_IMG_CODING_SCHEME_COLOR
- */
-add_test(function test_reading_img_color() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- {img: [0x01, 0x05, 0x05, 0x21, 0x4f, 0x11, 0x00, 0x00, 0x00, 0x13],
- iidf: [
- [/* Header */
- 0x05, 0x05, 0x03, 0x08, 0x00, 0x13,
- /* Image body */
- 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0,
- 0xb0, 0xc0, 0xd0,
- /* Clut entries */
- 0x00, 0x01, 0x02,
- 0x10, 0x11, 0x12,
- 0x20, 0x21, 0x22,
- 0x30, 0x31, 0x32,
- 0x40, 0x41, 0x42,
- 0x50, 0x51, 0x52,
- 0x60, 0x61, 0x62,
- 0x70, 0x71, 0x72]],
- expected: [
- {width: 0x05,
- height: 0x05,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- bitsPerImgPoint: 0x03,
- numOfClutEntries: 0x08,
- body: [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0,
- 0xc0, 0xd0],
- clut: [0x00, 0x01, 0x02,
- 0x10, 0x11, 0x12,
- 0x20, 0x21, 0x22,
- 0x30, 0x31, 0x32,
- 0x40, 0x41, 0x42,
- 0x50, 0x51, 0x52,
- 0x60, 0x61, 0x62,
- 0x70, 0x71, 0x72]}]},
- {img: [0x02, 0x01, 0x06, 0x21, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08, 0x01,
- 0x06, 0x21, 0x4f, 0x44, 0x00, 0x02, 0x00, 0x08],
- iidf: [
- [/* Data offset */
- 0xff, 0xff,
- /* Header */
- 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
- /* Image body */
- 0x40, 0x50,
- /* Clut offset */
- 0xaa, 0xbb, 0xcc,
- /* Clut entries */
- 0x01, 0x03, 0x05,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65],
- [/* Data offset */
- 0xff, 0xff,
- /* Header */
- 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
- /* Image body */
- 0x4f, 0x5f,
- /* Clut offset */
- 0xaa, 0xbb, 0xcc,
- /* Clut entries */
- 0x11, 0x13, 0x15,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]],
- expected: [
- {width: 0x01,
- height: 0x06,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- bitsPerImgPoint: 0x02,
- numOfClutEntries: 0x04,
- body: [0x40, 0x50],
- clut: [0x01, 0x03, 0x05,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]},
- {width: 0x01,
- height: 0x06,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- bitsPerImgPoint: 0x02,
- numOfClutEntries: 0x04,
- body: [0x4f, 0x5f],
- clut: [0x11, 0x13, 0x15,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]}]}];
-
- function do_test(img, iidf, expected) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let instanceIndex = 0;
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf[instanceIndex].length * 2);
-
- // Write data
- for (let i = 0; i < iidf[instanceIndex].length; i++) {
- helper.writeHexOctet(iidf[instanceIndex][i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
-
- instanceIndex++;
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function(icons) {
- equal(icons.length, expected.length);
- for (let i = 0; i < icons.length; i++) {
- let icon = icons[i];
- let exp = expected[i];
- equal(icon.width, exp.width);
- equal(icon.height, exp.height);
- equal(icon.codingScheme, exp.codingScheme);
-
- equal(icon.body.length, exp.body.length);
- for (let j = 0; j < icon.body.length; j++) {
- equal(icon.body[j], exp.body[j]);
- }
-
- equal(icon.clut.length, exp.clut.length);
- for (let j = 0; j < icon.clut.length; j++) {
- equal(icon.clut[j], exp.clut[j]);
- }
- }
- };
-
- record.readIMG(0, onsuccess);
- }
-
- for (let i = 0; i< test_data.length; i++) {
- do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
- }
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with
- * ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY
- */
-add_test(function test_reading_img_color() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- {img: [0x01, 0x05, 0x05, 0x22, 0x4f, 0x11, 0x00, 0x00, 0x00, 0x13],
- iidf: [
- [/* Header */
- 0x05, 0x05, 0x03, 0x08, 0x00, 0x13,
- /* Image body */
- 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0,
- 0xb0, 0xc0, 0xd0,
- /* Clut entries */
- 0x00, 0x01, 0x02,
- 0x10, 0x11, 0x12,
- 0x20, 0x21, 0x22,
- 0x30, 0x31, 0x32,
- 0x40, 0x41, 0x42,
- 0x50, 0x51, 0x52,
- 0x60, 0x61, 0x62,
- 0x70, 0x71, 0x72]],
- expected: [
- {width: 0x05,
- height: 0x05,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- bitsPerImgPoint: 0x03,
- numOfClutEntries: 0x08,
- body: [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,
- 0xa0, 0xb0, 0xc0, 0xd0],
- clut: [0x00, 0x01, 0x02,
- 0x10, 0x11, 0x12,
- 0x20, 0x21, 0x22,
- 0x30, 0x31, 0x32,
- 0x40, 0x41, 0x42,
- 0x50, 0x51, 0x52,
- 0x60, 0x61, 0x62,
- 0x70, 0x71, 0x72]}]},
- {img: [0x02, 0x01, 0x06, 0x22, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08, 0x01,
- 0x06, 0x22, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08],
- iidf: [
- [/* Data offset */
- 0xff, 0xff,
- /* Header */
- 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
- /* Image body */
- 0x40, 0x50,
- /* Clut offset */
- 0x0a, 0x0b, 0x0c,
- /* Clut entries */
- 0x01, 0x03, 0x05,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65],
- [/* Data offset */
- 0xff, 0xff,
- /* Header */
- 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
- /* Image body */
- 0x4f, 0x5f,
- /* Clut offset */
- 0x0a, 0x0b, 0x0c,
- /* Clut entries */
- 0x11, 0x13, 0x15,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]],
- expected: [
- {width: 0x01,
- height: 0x06,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- bitsPerImgPoint: 0x02,
- numOfClutEntries: 0x04,
- body: [0x40, 0x50],
- clut: [0x01, 0x03, 0x05,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]},
- {width: 0x01,
- height: 0x06,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- bitsPerImgPoint: 0x02,
- numOfClutEntries: 0x04,
- body: [0x4f, 0x5f],
- clut: [0x11, 0x13, 0x15,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]}]}];
-
- function do_test(img, iidf, expected) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let instanceIndex = 0;
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf[instanceIndex].length * 2);
-
- // Write data
- for (let i = 0; i < iidf[instanceIndex].length; i++) {
- helper.writeHexOctet(iidf[instanceIndex][i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
-
- instanceIndex++;
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function(icons) {
- equal(icons.length, expected.length);
- for (let i = 0; i < icons.length; i++) {
- let icon = icons[i];
- let exp = expected[i];
- equal(icon.width, exp.width);
- equal(icon.height, exp.height);
- equal(icon.codingScheme, exp.codingScheme);
-
- equal(icon.body.length, exp.body.length);
- for (let j = 0; j < icon.body.length; j++) {
- equal(icon.body[j], exp.body[j]);
- }
-
- equal(icon.clut.length, exp.clut.length);
- for (let j = 0; j < icon.clut.length; j++) {
- equal(icon.clut[j], exp.clut[j]);
- }
- }
- };
-
- record.readIMG(0, onsuccess);
- }
-
- for (let i = 0; i< test_data.length; i++) {
- do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
- }
- run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.readCphsInfo
- */
-add_test(function test_read_cphs_info() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let pduHelper = context.GsmPDUHelper;
- let recordHelper = context.SimRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let cphsPDU = new Uint8Array(3);
-
- io.loadTransparentEF = function(options) {
- if (cphsPDU) {
- // Write data size
- buf.writeInt32(cphsPDU.length * 2);
-
- // Write CPHS INFO
- for (let i = 0; i < cphsPDU.length; i++) {
- pduHelper.writeHexOctet(cphsPDU[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(cphsPDU.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- } else {
- do_print("cphsPDU[] is not set.");
- }
- };
-
- function do_test(cphsInfo, cphsSt) {
- let onsuccess = false;
- let onerror = false;
-
- delete RIL.iccInfoPrivate.cphsSt;
- cphsPDU.set(cphsInfo);
- recordHelper.readCphsInfo(() => { onsuccess = true; },
- () => { onerror = true; });
-
- ok((cphsSt) ? onsuccess : onerror);
- ok(!((cphsSt) ? onerror : onsuccess));
- if (cphsSt) {
- equal(RIL.iccInfoPrivate.cphsSt.length, cphsSt.length);
- for (let i = 0; i < cphsSt.length; i++) {
- equal(RIL.iccInfoPrivate.cphsSt[i], cphsSt[i]);
- }
- } else {
- equal(RIL.iccInfoPrivate.cphsSt, cphsSt);
- }
- }
-
- do_test([
- 0x01, // Phase 1
- 0xFF, // All available & activated
- 0x03 // All available & activated
- ],
- [
- 0x3F, // All services except ONSF(bit 8-7) are available and activated.
- 0x00 // INFO_NUM shall not be available & activated.
- ]);
-
- do_test([
- 0x02, // Phase 2
- 0xFF, // All available & activated
- 0x03 // All available & activated
- ],
- [
- 0xF3, // All services except ONSF are available and activated.
- 0x03 // INFO_NUM shall not be available & activated.
- ]);
-
- do_test([
- 0x03, // Phase 3
- 0xFF, // All available & activated
- 0x03 // All available & activated
- ],
- undefined); // RIL.iccInfoPrivate.cphsSt shall be remained as 'undefined'.
-
- run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.readMBDN/SimRecordHelper.readCphsMBN
- */
-add_test(function test_read_voicemail_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let pduHelper = context.GsmPDUHelper;
- let recordHelper = context.SimRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let postedMessage;
-
- worker.postMessage = function(message) {
- postedMessage = message;
- };
-
- io.loadLinearFixedEF = function(options) {
- let mbnData = [
- 0x56, 0x6F, 0x69, 0x63, 0x65, 0x6D, 0x61, 0x69,
- 0x6C, 0xFF, // Alpha Identifier: Voicemail
- 0x03, // Length of BCD number: 3
- 0x80, // TOA: Unknown
- 0x11, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, // Dialing Number: 111
- 0xFF, // Capability/Configuration Record Identifier
- 0xFF // Extension Record Identifier
- ];
-
- // Write data size
- buf.writeInt32(mbnData.length * 2);
-
- // Write MBN
- for (let i = 0; i < mbnData.length; i++) {
- pduHelper.writeHexOctet(mbnData[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(mbnData.length * 2);
-
- options.recordSize = mbnData.length;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function do_test(funcName, msgCount) {
- postedMessage = null;
- delete RIL.iccInfoPrivate.mbdn;
- recordHelper[funcName]();
-
- equal("iccmbdn", postedMessage.rilMessageType);
- equal("Voicemail", postedMessage.alphaId);
- equal("111", postedMessage.number);
- }
-
- do_test("readMBDN");
- do_test("readCphsMBN");
-
- run_next_test();
-});
-
-/**
- * Verify the recovery from SimRecordHelper.readCphsMBN() if MBDN is not valid
- * or is empty after SimRecordHelper.readMBDN().
- */
-add_test(function test_read_mbdn_recovered_from_cphs_mbn() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let pduHelper = context.GsmPDUHelper;
- let recordHelper = context.SimRecordHelper;
- let iccUtilsHelper = context.ICCUtilsHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- io.loadLinearFixedEF = function(options) {
- let mbnData = [
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
- ];
-
- // Write data size
- buf.writeInt32(mbnData.length * 2);
-
- // Write MBN
- for (let i = 0; i < mbnData.length; i++) {
- pduHelper.writeHexOctet(mbnData[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(mbnData.length * 2);
-
- options.recordSize = mbnData.length;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- iccUtilsHelper.isCphsServiceAvailable = function(geckoService) {
- return geckoService == "MBN";
- };
-
- let isRecovered = false;
- recordHelper.readCphsMBN = function(onComplete) {
- isRecovered = true;
- };
-
- recordHelper.readMBDN();
-
- equal(RIL.iccInfoPrivate.mbdn, undefined);
- ok(isRecovered);
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_PNN with different coding scheme.
- */
-add_test(function test_pnn_with_different_coding_scheme() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [{
- // Cell Broadcast data coding scheme - "Test1"
- pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03],
- expectedResult: "Test1"
- },{
- // UCS2 with 0x80 - "Test1"
- pnn: [0x43, 0x0C, 0x90, 0x80, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31],
- expectedResult: "Test1"
- },{
- // UCS2 with 0x81 - "Mozilla\u694a"
- pnn: [0x43, 0x0E, 0x90, 0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff],
- expectedResult: "Mozilla\u694a"
- },{
- // UCS2 with 0x82 - "Mozilla\u694a"
- pnn: [0x43, 0x0F, 0x90, 0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff],
- expectedResult: "Mozilla\u694a"
- }];
-
- function do_test_pnn(pnn, expectedResult) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size.
- buf.writeInt32(pnn.length * 2);
-
- // Write data.
- for (let i = 0; i < pnn.length; i++) {
- pduHelper.writeHexOctet(pnn[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(pnn.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readPNN();
-
- equal(ril.iccInfoPrivate.PNN[0].fullName, expectedResult);
- // Reset PNN info for next test
- ril.iccInfoPrivate.PNN = null;
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- for (let i = 0; i < test_data.length; i++) {
- do_test_pnn(test_data[i].pnn, test_data[i].expectedResult);
- }
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_PNN with different content.
- */
-add_test(function test_pnn_with_different_content() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [{
- // [0]: {"fullName":"Test1","shortName":"Test1"}
- pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03,
- 0x45, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03],
- expectedResult: {"fullName": "Test1","shortName": "Test1"}
- },{
- // [1]: {"fullName":"Test2"}
- pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x2E, 0x03],
- expectedResult: {"fullName": "Test2"}
- },{
- // [2]: undefined
- pnn: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
- },{
- // [3]: {"fullName": "Test4"}
- pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x4E, 0x03],
- expectedResult: {"fullName": "Test4"}
- },{
- // [4]: undefined
- pnn: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
- }];
-
- function do_test_pnn() {
- ril.iccIO = function fakeIccIO(options) {
- let index = options.p1 - 1;
- let pnn = test_data[index].pnn;
-
- // Write data size.
- buf.writeInt32(pnn.length * 2);
-
- // Write data.
- for (let i = 0; i < pnn.length; i++) {
- pduHelper.writeHexOctet(pnn[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(pnn.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- options.p1 = 1;
- options.totalRecords = test_data.length;
-
- ril.iccIO(options);
- };
-
- record.readPNN();
-
- equal(test_data.length, ril.iccInfoPrivate.PNN.length);
- for (let i = 0; i < test_data.length; i++) {
- if (test_data[i].expectedResult) {
- equal(test_data[i].expectedResult.fullName,
- ril.iccInfoPrivate.PNN[i].fullName);
- equal(test_data[i].expectedResult.shortName,
- ril.iccInfoPrivate.PNN[i].shortName);
- } else {
- equal(test_data[i].expectedResult, ril.iccInfoPrivate.PNN[i]);
- }
- }
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- do_test_pnn();
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_ruim.js b/dom/system/gonk/tests/test_ril_worker_ruim.js
deleted file mode 100644
index 0ddc10f29..000000000
--- a/dom/system/gonk/tests/test_ril_worker_ruim.js
+++ /dev/null
@@ -1,328 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify RUIM Service.
- */
-add_test(function test_is_ruim_service_available() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- context.RIL._isCdma = true;
- context.RIL.appType = CARD_APPTYPE_RUIM;
-
- function test_table(cst, geckoService, enabled) {
- context.RIL.iccInfoPrivate.cst = cst;
- equal(context.ICCUtilsHelper.isICCServiceAvailable(geckoService),
- enabled);
- }
-
- test_table([0x0, 0x0, 0x0, 0x0, 0x03], "SPN", true);
- test_table([0x0, 0x0, 0x0, 0x03, 0x0], "SPN", false);
- test_table([0x0, 0x0C, 0x0, 0x0, 0x0], "ENHANCED_PHONEBOOK", true);
- test_table([0x0, 0x0, 0x0, 0x0, 0x0], "ENHANCED_PHONEBOOK", false);
-
- run_next_test();
-});
-
-/**
- * Verify EF_PATH for RUIM file.
- */
-add_test(function test_ruim_file_path_id() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ICCFileHelper = context.ICCFileHelper;
-
- RIL.appType = CARD_APPTYPE_RUIM;
- equal(ICCFileHelper.getEFPath(ICC_EF_CSIM_CST),
- EF_PATH_MF_SIM + EF_PATH_DF_CDMA);
-
- run_next_test();
-});
-
-add_test(function test_fetch_ruim_recodes() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ruimHelper = context.RuimRecordHelper;
-
- function testFetchRuimRecordes(expectCalled) {
- let ifCalled = [];
-
- ruimHelper.getIMSI_M = function() {
- ifCalled.push("getIMSI_M");
- };
-
- ruimHelper.readCST = function() {
- ifCalled.push("readCST");
- };
-
- ruimHelper.readCDMAHome = function() {
- ifCalled.push("readCDMAHome");
- };
-
- RIL.getCdmaSubscription = function() {
- ifCalled.push("getCdmaSubscription");
- };
-
- ruimHelper.fetchRuimRecords();
-
- for (let i = 0; i < expectCalled.length; i++ ) {
- if (ifCalled[i] != expectCalled[i]) {
- do_print(expectCalled[i] + " is not called.");
- ok(false);
- }
- }
- }
-
- let expectCalled = ["getIMSI_M", "readCST", "readCDMAHome",
- "getCdmaSubscription"];
- testFetchRuimRecordes(expectCalled);
-
- run_next_test();
-});
-
-/**
- * Verify RuimRecordHelper.decodeIMSIValue
- */
-add_test(function test_decode_imsi_value() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
-
- function testDecodeImsiValue(encoded, length, expect) {
- let decoded = context.RuimRecordHelper.decodeIMSIValue(encoded, length);
-
- equal(expect, decoded);
- }
-
- testDecodeImsiValue( 99, 2, "00");
- testDecodeImsiValue( 90, 2, "01");
- testDecodeImsiValue( 19, 2, "20");
- testDecodeImsiValue( 23, 2, "34");
- testDecodeImsiValue(999, 3, "000");
- testDecodeImsiValue(990, 3, "001");
- testDecodeImsiValue(909, 3, "010");
- testDecodeImsiValue( 99, 3, "100");
- testDecodeImsiValue(901, 3, "012");
- testDecodeImsiValue( 19, 3, "120");
- testDecodeImsiValue( 91, 3, "102");
- testDecodeImsiValue(199, 3, "200");
- testDecodeImsiValue(123, 3, "234");
- testDecodeImsiValue(578, 3, "689");
-
- run_next_test();
-});
-
-/**
- * Verify RuimRecordHelper.getIMSI_M
- */
-add_test(function test_get_imsi_m() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function testDecodeImsi(encodedImsi, expectedImsi) {
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(encodedImsi.length * 2);
-
- // Write imsi
- for (let i = 0; i < encodedImsi.length; i++) {
- helper.writeHexOctet(encodedImsi[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(encodedImsi.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- context.RuimRecordHelper.getIMSI_M();
- let imsi = context.RIL.iccInfoPrivate.imsi;
-
- equal(expectedImsi, imsi)
- }
-
- let imsi_1 = "466050081062861";
- testDecodeImsi([0x0, 0xe5, 0x03, 0xee, 0xca, 0x17, 0x5e, 0x80, 0x63, 0x01], imsi_1);
-
- let imsi_2 = "460038351175976";
- testDecodeImsi([0x0, 0xd4, 0x02, 0x61, 0x97, 0x01, 0x5c, 0x80, 0x67, 0x01], imsi_2);
-
- run_next_test();
-});
-
-/**
- * Verify RuimRecordHelper.readCDMAHome
- */
-add_test(function test_read_cdmahome() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let cdmaHome = [0xc1, 0x34, 0xff, 0xff, 0x00];
-
- // Write data size
- buf.writeInt32(cdmaHome.length * 2);
-
- // Write cdma home file.
- for (let i = 0; i < cdmaHome.length; i++) {
- helper.writeHexOctet(cdmaHome[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(cdmaHome.length * 2);
-
- // We just have 1 test record.
-
- options.totalRecords = 1;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function testCdmaHome(expectedSystemIds, expectedNetworkIds) {
- context.RuimRecordHelper.readCDMAHome();
- let cdmaHome = context.RIL.cdmaHome;
- for (let i = 0; i < expectedSystemIds.length; i++) {
- equal(cdmaHome.systemId[i], expectedSystemIds[i]);
- equal(cdmaHome.networkId[i], expectedNetworkIds[i]);
- }
- equal(cdmaHome.systemId.length, expectedSystemIds.length);
- equal(cdmaHome.networkId.length, expectedNetworkIds.length);
- }
-
- testCdmaHome([13505], [65535]);
-
- run_next_test();
-});
-
-/**
- * Verify reading CDMA EF_SPN
- */
-add_test(function test_read_cdmaspn() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function testReadSpn(file, expectedSpn, expectedDisplayCondition) {
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(file.length * 2);
-
- // Write file.
- for (let i = 0; i < file.length; i++) {
- helper.writeHexOctet(file[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(file.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- context.RuimRecordHelper.readSPN();
- equal(context.RIL.iccInfo.spn, expectedSpn);
- equal(context.RIL.iccInfoPrivate.spnDisplayCondition,
- expectedDisplayCondition);
- }
-
- testReadSpn([0x01, 0x04, 0x06, 0x4e, 0x9e, 0x59, 0x2a, 0x96,
- 0xfb, 0x4f, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff],
- String.fromCharCode(0x4e9e) +
- String.fromCharCode(0x592a) +
- String.fromCharCode(0x96fb) +
- String.fromCharCode(0x4fe1),
- 0x1);
-
- // Test when there's no tailing 0xff in spn string.
- testReadSpn([0x01, 0x04, 0x06, 0x4e, 0x9e, 0x59, 0x2a, 0x96,
- 0xfb, 0x4f, 0xe1],
- String.fromCharCode(0x4e9e) +
- String.fromCharCode(0x592a) +
- String.fromCharCode(0x96fb) +
- String.fromCharCode(0x4fe1),
- 0x1);
-
- run_next_test();
-});
-
-/**
- * Verify display condition for CDMA.
- */
-add_test(function test_cdma_spn_display_condition() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ICCUtilsHelper = context.ICCUtilsHelper;
-
- // Set cdma.
- RIL._isCdma = true;
-
- // Test updateDisplayCondition runs before any of SIM file is ready.
- equal(ICCUtilsHelper.updateDisplayCondition(), true);
- equal(RIL.iccInfo.isDisplayNetworkNameRequired, true);
- equal(RIL.iccInfo.isDisplaySpnRequired, false);
-
- // Test with value.
- function testDisplayCondition(ruimDisplayCondition,
- homeSystemIds, homeNetworkIds,
- currentSystemId, currentNetworkId,
- expectUpdateDisplayCondition,
- expectIsDisplaySPNRequired) {
- RIL.iccInfoPrivate.spnDisplayCondition = ruimDisplayCondition;
- RIL.cdmaHome = {
- systemId: homeSystemIds,
- networkId: homeNetworkIds
- };
- RIL.voiceRegistrationState.cell = {
- cdmaSystemId: currentSystemId,
- cdmaNetworkId: currentNetworkId
- };
-
- equal(ICCUtilsHelper.updateDisplayCondition(), expectUpdateDisplayCondition);
- equal(RIL.iccInfo.isDisplayNetworkNameRequired, false);
- equal(RIL.iccInfo.isDisplaySpnRequired, expectIsDisplaySPNRequired);
- };
-
- // SPN is not required when ruimDisplayCondition is false.
- testDisplayCondition(0x0, [123], [345], 123, 345, true, false);
-
- // System id and network id are all match.
- testDisplayCondition(0x1, [123], [345], 123, 345, true, true);
-
- // Network is 65535, we should only need to match system id.
- testDisplayCondition(0x1, [123], [65535], 123, 345, false, true);
-
- // Not match.
- testDisplayCondition(0x1, [123], [456], 123, 345, true, false);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms.js b/dom/system/gonk/tests/test_ril_worker_sms.js
deleted file mode 100644
index 7c1b972a7..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms.js
+++ /dev/null
@@ -1,273 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gSmsSegmentHelper", function() {
- let ns = {};
- Cu.import("resource://gre/modules/SmsSegmentHelper.jsm", ns);
- return ns.SmsSegmentHelper;
-});
-
-const ESCAPE = "\uffff";
-const RESCTL = "\ufffe";
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify receiving SMS-DELIVERY messages
- */
-
-function hexToNibble(nibble) {
- nibble &= 0x0f;
- if (nibble < 10) {
- nibble += 48; // ASCII '0'
- } else {
- nibble += 55; // ASCII 'A'
- }
- return nibble;
-}
-
-function pduToParcelData(pdu) {
- let dataLength = 4 + pdu.length * 4 + 4;
- let data = new Uint8Array(dataLength);
- let offset = 0;
-
- // String length
- data[offset++] = pdu.length & 0xFF;
- data[offset++] = (pdu.length >> 8) & 0xFF;
- data[offset++] = (pdu.length >> 16) & 0xFF;
- data[offset++] = (pdu.length >> 24) & 0xFF;
-
- // PDU data
- for (let i = 0; i < pdu.length; i++) {
- let hi = (pdu[i] >>> 4) & 0x0F;
- let lo = pdu[i] & 0x0F;
-
- data[offset++] = hexToNibble(hi);
- data[offset++] = 0;
- data[offset++] = hexToNibble(lo);
- data[offset++] = 0;
- }
-
- // String delimitor
- data[offset++] = 0;
- data[offset++] = 0;
- data[offset++] = 0;
- data[offset++] = 0;
-
- return data;
-}
-
-function compose7bitPdu(lst, sst, data, septets) {
- if ((lst == 0) && (sst == 0)) {
- return [0x00, // SMSC
- PDU_MTI_SMS_DELIVER, // firstOctet
- 1, 0x00, 0, // senderAddress
- 0x00, // protocolIdentifier
- PDU_DCS_MSG_CODING_7BITS_ALPHABET, // dataCodingScheme
- 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
- septets] // userDataLength
- .concat(data);
- }
-
- return [0x00, // SMSC
- PDU_MTI_SMS_DELIVER | PDU_UDHI, // firstOctet
- 1, 0x00, 0, // senderAddress
- 0x00, // protocolIdentifier
- PDU_DCS_MSG_CODING_7BITS_ALPHABET, // dataCodingScheme
- 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
- 8 + septets, // userDataLength
- 6, // user data header length
- PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT, 1, lst, // PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT
- PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT, 1, sst] // PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT
- .concat(data);
-}
-
-function composeUcs2Pdu(rawBytes) {
- return [0x00, // SMSC
- PDU_MTI_SMS_DELIVER, // firstOctet
- 1, 0x00, 0, // senderAddress
- 0x00, // protocolIdentifier
- PDU_DCS_MSG_CODING_16BITS_ALPHABET, // dataCodingScheme
- 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
- rawBytes.length] // userDataLength
- .concat(rawBytes);
-}
-
-function newSmsParcel(pdu) {
- return newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_SMS,
- pduToParcelData(pdu));
-}
-
-function removeSpecialChar(str, needle) {
- for (let i = 0; i < needle.length; i++) {
- let pos;
- while ((pos = str.indexOf(needle[i])) >= 0) {
- str = str.substring(0, pos) + str.substring(pos + 1);
- }
- }
- return str;
-}
-
-function newWriteHexOctetAsUint8Worker() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- context.GsmPDUHelper.writeHexOctet = function(value) {
- context.Buf.writeUint8(value);
- };
-
- return worker;
-}
-
-function add_test_receiving_sms(expected, pdu) {
- add_test(function test_receiving_sms() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- do_print("fullBody: " + message.fullBody);
- equal(expected, message.fullBody)
- }
- });
-
- do_print("expect: " + expected);
- do_print("pdu: " + pdu);
- worker.onRILMessage(0, newSmsParcel(pdu));
-
- run_next_test();
- });
-}
-
-var test_receiving_7bit_alphabets__worker;
-function test_receiving_7bit_alphabets(lst, sst) {
- if (!test_receiving_7bit_alphabets__worker) {
- test_receiving_7bit_alphabets__worker = newWriteHexOctetAsUint8Worker();
- }
- let worker = test_receiving_7bit_alphabets__worker;
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = context.Buf;
-
- function get7bitRawBytes(expected) {
- buf.outgoingIndex = 0;
- helper.writeStringAsSeptets(expected, 0, lst, sst);
-
- let subArray = buf.outgoingBytes.subarray(0, buf.outgoingIndex);
- return Array.slice(subArray);
- }
-
- let langTable = PDU_NL_LOCKING_SHIFT_TABLES[lst];
- let langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[sst];
-
- let text = removeSpecialChar(langTable + langShiftTable, ESCAPE + RESCTL);
- for (let i = 0; i < text.length;) {
- let len = Math.min(70, text.length - i);
- let expected = text.substring(i, i + len);
- let septets =
- gSmsSegmentHelper.countGsm7BitSeptets(expected, langTable, langShiftTable);
- let rawBytes = get7bitRawBytes(expected);
- let pdu = compose7bitPdu(lst, sst, rawBytes, septets);
- add_test_receiving_sms(expected, pdu);
-
- i += len;
- }
-}
-
-function test_receiving_ucs2_alphabets(text) {
- let worker = test_receiving_7bit_alphabets__worker;
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
-
- function getUCS2RawBytes(expected) {
- buf.outgoingIndex = 0;
- context.GsmPDUHelper.writeUCS2String(expected);
-
- let subArray = buf.outgoingBytes.subarray(0, buf.outgoingIndex);
- return Array.slice(subArray);
- }
-
- for (let i = 0; i < text.length;) {
- let len = Math.min(70, text.length - i);
- let expected = text.substring(i, i + len);
- let rawBytes = getUCS2RawBytes(expected);
- let pdu = composeUcs2Pdu(rawBytes);
- add_test_receiving_sms(expected, pdu);
-
- i += len;
- }
-}
-
-var ucs2str = "";
-for (let lst = 0; lst < PDU_NL_LOCKING_SHIFT_TABLES.length; lst++) {
- ucs2str += PDU_NL_LOCKING_SHIFT_TABLES[lst];
- for (let sst = 0; sst < PDU_NL_SINGLE_SHIFT_TABLES.length; sst++) {
- test_receiving_7bit_alphabets(lst, sst);
-
- if (lst == 0) {
- ucs2str += PDU_NL_SINGLE_SHIFT_TABLES[sst];
- }
- }
-}
-test_receiving_ucs2_alphabets(ucs2str);
-
-// Bug 820220: B2G SMS: wrong order and truncated content in multi-part messages
-add_test(function test_sendSMS_UCS2_without_langIndex_langShiftIndex_defined() {
- let worker = newWriteHexOctetAsUint8Worker();
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.sendParcel = function() {
- // Each sendParcel() call represents one outgoing segment of a multipart
- // SMS message. Here, we have the first segment send, so it's "Hello "
- // only.
- //
- // 4(parcel size) + 4(request type) + 4(token)
- // + 4(two messages) + 4(null SMSC) + 4(message string length)
- // + 1(first octet) + 1(message reference)
- // + 2(DA len, TOA) + 4(addr)
- // + 1(pid) + 1(dcs)
- // + 1(UDL) + 6(UDHL, type, len, ref, max, seq)
- // + 12(2 * strlen("Hello "))
- // + 4(two delimitors) = 57
- //
- // If we have additional 6(type, len, langIndex, type len, langShiftIndex)
- // octets here, then bug 809553 is not fixed.
- equal(this.outgoingIndex, 57);
-
- run_next_test();
- };
-
- context.RIL.sendSMS({
- number: "1",
- segmentMaxSeq: 2,
- fullBody: "Hello World!",
- dcs: PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- segmentRef16Bit: false,
- userDataHeaderLength: 5,
- requestStatusReport: true,
- segments: [
- {
- body: "Hello ",
- encodedBodyLength: 12,
- }, {
- body: "World!",
- encodedBodyLength: 12,
- }
- ],
- });
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_cdma.js b/dom/system/gonk/tests/test_ril_worker_sms_cdma.js
deleted file mode 100644
index 85d0b6e0c..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_cdma.js
+++ /dev/null
@@ -1,298 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/*
- * Helper function to covert a HEX string to a byte array.
- *
- * @param hexString
- * A hexadecimal string of which the length is even.
- */
-function hexStringToBytes(hexString) {
- let bytes = [];
-
- let length = hexString.length;
-
- for (let i = 0; i < length; i += 2) {
- bytes.push(Number.parseInt(hexString.substr(i, 2), 16));
- }
-
- return bytes;
-}
-
-/*
- * Helper function to covert a byte array to a HEX string.
- *
- * @param bytes
- * Could be a regular byte array or Uint8Array.
- */
-function bytesToHexString(bytes) {
- let hexString = "";
- let hex;
-
- for (let i = 0; i < bytes.length; i++) {
- hex = bytes[i].toString(16).toUpperCase();
- if (hex.length === 1) {
- hexString += "0";
- }
- hexString += hex;
- }
-
- return hexString;
-}
-
-/*
- * Helper function to ecode Opaque UserData
- *
- * @param msg_type
- * PDU_CDMA_MSG_TYPE_SUBMIT or PDU_CDMA_MSG_TYPE_DELIVER
- * @param data
- * The byte array of opaque data to be encoded.
- */
-function encodeOpaqueUserData(bitBufferHelper, options) {
- let bearerDataBuffer = [];
- bitBufferHelper.startWrite(bearerDataBuffer);
-
- // Msg-Id
- bitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_MSG_ID, 8);
- bitBufferHelper.writeBits(3, 8);
- bitBufferHelper.writeBits(options.msg_type, 4); // MSG_TYPE
- bitBufferHelper.writeBits(1, 16); // MSG_ID
- bitBufferHelper.flushWithPadding(); // HEADER_IND (1) + RESERVED (3)
-
- // User Data
- bitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_BODY, 8);
- let dataLength = options.data.length;
- bitBufferHelper.writeBits(2 + dataLength, 8); // 2 bytes for MSG_ENCODING, NUM_FIELDS
- bitBufferHelper.writeBits(PDU_CDMA_MSG_CODING_OCTET, 5); //MSG_ENCODING
- // MSG_TYPE is omitted if MSG_ENCODING is CODING_OCTET
- bitBufferHelper.writeBits(dataLength, 8); // NUM_FIELDS
- for (let i = 0; i < dataLength; i++) { // CHARi
- bitBufferHelper.writeBits(options.data[i], 8);
- }
- bitBufferHelper.flushWithPadding(); // RESERVED (3 filling bits)
-
- return bearerDataBuffer;
-}
-
-function newSmsParcel(cdmaPduHelper, pdu) {
- return newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_CDMA_NEW_SMS,
- pduToParcelData(cdmaPduHelper, pdu));
-}
-
-/*
- * Helper function to encode PDU into Parcel.
- * See ril_cdma_sms.h for the structure definition of RIL_CDMA_SMS_Message
- *
- * @param teleservice
- * The Teleservice-Id of this PDU.
- * See PDU_CDMA_MSG_TELESERIVCIE_ID_XXX in ril_const.js.
- * @param address
- * The Orginating or Destinating address.
- * @param bearerData
- * The byte array of the encoded bearer data.
- */
-function pduToParcelData(cdmaPduHelper, pdu) {
-
- let addrInfo = cdmaPduHelper.encodeAddr(pdu.address);
- // Teleservice, isServicePresent, ServiceCategory,
- // addrInfo {digitMode, numberMode, numberType, numberPlan, address.length, address}
- // Sub Address
- // bearerData length, bearerData.
- let dataLength = 4 + 4 + 4
- + (5 + addrInfo.address.length) * 4
- + 3 * 4
- + 4 + pdu.bearerData.length * 4;
-
- let data = new Uint8Array(dataLength);
- let offset = 0;
-
- function writeInt(value) {
- data[offset++] = value & 0xFF;
- data[offset++] = (value >> 8) & 0xFF;
- data[offset++] = (value >> 16) & 0xFF;
- data[offset++] = (value >> 24) & 0xFF;
- }
-
- function writeByte(value) {
- data[offset++] = value & 0xFF;
- data[offset++] = 0;
- data[offset++] = 0;
- data[offset++] = 0;
- }
-
- // Teleservice
- writeInt(pdu.teleservice);
-
- // isServicePresent
- writeByte(0);
-
- // ServiceCategory
- writeInt(PDU_CDMA_MSG_CATEGORY_UNSPEC);
-
- // AddrInfo
- writeByte(addrInfo.digitMode);
- writeByte(addrInfo.numberMode);
- writeByte(addrInfo.numberType);
- writeByte(addrInfo.numberPlan);
- let addressLength = addrInfo.address.length;
- writeByte(addressLength);
- for (let i = 0; i < addressLength; i++) {
- writeByte(addrInfo.address[i]);
- }
-
- // Subaddress
- writeByte(0);
- writeByte(0);
- writeByte(0);
-
- // Bearer Data Length
- dataLength = pdu.bearerData.length;
- writeByte(dataLength);
-
- // Bearer Data
- for (let i = 0; i < dataLength; i++) {
- writeByte(pdu.bearerData[i]);
- }
-
- return data;
-}
-
-/**
- * Verify CDMA SMS Delivery ACK Message.
- */
-add_test(function test_processCdmaSmsStatusReport() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- function test_StatusReport(errorClass, msgStatus) {
- let msgId = 0;
- let sentSmsMap = context.RIL._pendingSentSmsMap;
-
- sentSmsMap[msgId] = {};
-
- let message = {
- SMSC: "",
- mti: 0,
- udhi: 0,
- sender: "0987654321",
- recipient: null,
- pid: PDU_PID_DEFAULT,
- epid: PDU_PID_DEFAULT,
- dcs: 0,
- mwi: null,
- replace: false,
- header: null,
- body: "Status: Sent, Dest: 0987654321",
- data: null,
- timestamp: new Date().valueOf(),
- language: null,
- status: null,
- scts: null,
- dt: null,
- encoding: PDU_CDMA_MSG_CODING_7BITS_ASCII,
- messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- messageType: PDU_CDMA_MSG_TYPE_P2P,
- serviceCategory: 0,
- subMsgType: PDU_CDMA_MSG_TYPE_DELIVER_ACK,
- msgId: msgId,
- errorClass: errorClass,
- msgStatus: msgStatus
- };
-
- context.RIL._processCdmaSmsStatusReport(message);
-
- let postedMessage = workerHelper.postedMessage;
-
- // Check if pending token is removed.
- ok((errorClass === 2) ? !!sentSmsMap[msgId] : !sentSmsMap[msgId]);
-
- // Check the response message accordingly.
- if (errorClass === -1) {
- // Check if the report is treated as normal incoming SMS
- equal("sms-received", postedMessage.rilMessageType);
- } else if (errorClass === 2) {
- // Do nothing.
- } else {
- // Check Delivery Status
- if (errorClass === 0) {
- equal(postedMessage.deliveryStatus, GECKO_SMS_DELIVERY_STATUS_SUCCESS);
- } else {
- equal(postedMessage.deliveryStatus, GECKO_SMS_DELIVERY_STATUS_ERROR);
- }
- }
- }
-
- test_StatusReport(-1, -1); // Message Status Sub-parameter is absent.
- test_StatusReport(0, 0); // 00|000000: no error|Message accepted
- test_StatusReport(2, 4); // 10|000100: temporary condition|Network congestion
- test_StatusReport(3, 5); // 11|000101: permanent condition|Network error
-
- run_next_test();
-});
-
-/**
- * Verify WAP Push over CDMA SMS Message.
- */
-add_test(function test_processCdmaSmsWapPush() {
- let workerHelper = newInterceptWorker(),
- worker = workerHelper.worker,
- context = worker.ContextPool._contexts[0],
- bitBufferHelper = context.BitBufferHelper,
- cdmaPduHelper = context.CdmaPDUHelper;
-
- function test_CdmaSmsWapPdu(wdpData, reversed) {
- let orig_address = "0987654321",
- hexString,
- fullDataHexString = "";
-
- for (let i = 0; i < wdpData.length; i++) {
- let dataIndex = (reversed) ? (wdpData.length - i - 1) : i;
- hexString = "00"; // MSG_TYPE
- hexString += bytesToHexString([wdpData.length]); // TOTAL_SEG
- hexString += bytesToHexString([dataIndex]); // SEG_NUM (zero-based)
- if ((dataIndex === 0)) {
- hexString += "23F00B84"; // SOURCE_PORT, DEST_PORT for 1st segment
- }
- hexString += wdpData[dataIndex]; // WDP DATA
-
- do_print("hexString: " + hexString);
-
- fullDataHexString += wdpData[i];
-
- let pdu = {
- teleservice: PDU_CDMA_MSG_TELESERIVCIE_ID_WAP,
- address: orig_address,
- bearerData: encodeOpaqueUserData(bitBufferHelper,
- { msg_type: PDU_CDMA_MSG_TYPE_DELIVER,
- data: hexStringToBytes(hexString) })
- };
-
- worker.onRILMessage(0, newSmsParcel(cdmaPduHelper, pdu));
- }
-
- let postedMessage = workerHelper.postedMessage;
-
- do_print("fullDataHexString: " + fullDataHexString);
-
- equal("sms-received", postedMessage.rilMessageType);
- equal(PDU_CDMA_MSG_TELESERIVCIE_ID_WAP, postedMessage.teleservice);
- equal(orig_address, postedMessage.sender);
- equal(0x23F0, postedMessage.header.originatorPort);
- equal(0x0B84, postedMessage.header.destinationPort);
- equal(fullDataHexString, bytesToHexString(postedMessage.data));
- }
-
- // Verify Single WAP PDU
- test_CdmaSmsWapPdu(["000102030405060708090A0B0C0D0E0F"]);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_cdmapduhelper.js b/dom/system/gonk/tests/test_ril_worker_sms_cdmapduhelper.js
deleted file mode 100644
index 276728f2f..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_cdmapduhelper.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify CdmaPDUHelper#encodeUserDataReplyOption.
- */
-add_test(function test_CdmaPDUHelper_encodeUserDataReplyOption() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- let testDataBuffer = [];
- context.BitBufferHelper.startWrite(testDataBuffer);
-
- let helper = context.CdmaPDUHelper;
- helper.encodeUserDataReplyOption({requestStatusReport: true});
-
- let expectedDataBuffer = [PDU_CDMA_MSG_USERDATA_REPLY_OPTION, 0x01, 0x40];
-
- equal(testDataBuffer.length, expectedDataBuffer.length);
-
- for (let i = 0; i < expectedDataBuffer.length; i++) {
- equal(testDataBuffer[i], expectedDataBuffer[i]);
- }
-
- run_next_test();
-});
-
-/**
- * Verify CdmaPDUHelper#cdma_decodeUserDataMsgStatus.
- */
-add_test(function test_CdmaPDUHelper_decodeUserDataMsgStatus() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- let helper = context.CdmaPDUHelper;
- function test_MsgStatus(octet) {
- let testDataBuffer = [octet];
- context.BitBufferHelper.startRead(testDataBuffer);
- let result = helper.decodeUserDataMsgStatus();
-
- equal(result.errorClass, octet >>> 6);
- equal(result.msgStatus, octet & 0x3F);
- }
-
- // 00|000000: no error|Message accepted
- test_MsgStatus(0x00);
-
- // 10|000100: temporary condition|Network congestion
- test_MsgStatus(0x84);
-
- // 11|000101: permanent condition|Network error
- test_MsgStatus(0xC5);
-
- run_next_test();
-});
-
-/**
- * Verify CdmaPDUHelper#decodeCdmaPDUMsg.
- * - encoding by shift-jis
- */
-add_test(function test_CdmaPDUHelper_decodeCdmaPDUMsg_Shift_jis() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- let helper = context.CdmaPDUHelper;
- function test_decodePDUMsg(testDataBuffer, expected, encoding, msgType, msgBodySize) {
- context.BitBufferHelper.startRead(testDataBuffer);
- let result = helper.decodeCdmaPDUMsg(encoding, msgType, msgBodySize);
- equal(result, expected);
- }
-
- // Shift-JIS has 1 byte and 2 byte code for one character and has some types of characters:
- // Hiragana, Kanji, Katakana(fullwidth, halfwidth)...
- // This test is a combination of 1 byte and 2 byte code and types of characters.
-
- // test case 1
- let testDataBuffer1 = [0x82, 0x58, 0x33, 0x41, 0x61, 0x33, 0x82, 0x60,
- 0x82, 0x81, 0x33, 0xB1, 0xAF, 0x33, 0x83, 0x41,
- 0x83, 0x96, 0x33, 0x82, 0xA0, 0x33, 0x93, 0xFA,
- 0x33, 0x3A, 0x3C, 0x33, 0x81, 0x80, 0x81, 0x8E,
- 0x33, 0x31, 0x82, 0x51, 0x41, 0x61, 0x82, 0x51,
- 0x82, 0x60, 0x82, 0x81, 0x82, 0x51, 0xB1, 0xAF,
- 0x82, 0x51, 0x83, 0x41, 0x83, 0x96, 0x82, 0x51,
- 0x82, 0xA0, 0x82, 0x51, 0x93, 0xFA, 0x82, 0x51,
- 0x3A, 0x3C, 0x82, 0x51, 0x81, 0x80, 0x81, 0x8E,
- 0x82, 0x51];
-
- test_decodePDUMsg(
- testDataBuffer1,
- "\uFF19\u0033\u0041\u0061\u0033\uFF21\uFF41\u0033\uFF71\uFF6F\u0033\u30A2\u30F6\u0033\u3042\u0033\u65E5\u0033\u003A\u003C\u0033\u00F7\u2103\u0033\u0031\uFF12\u0041\u0061\uFF12\uFF21\uFF41\uFF12\uFF71\uFF6F\uFF12\u30A2\u30F6\uFF12\u3042\uFF12\u65E5\uFF12\u003A\u003C\uFF12\u00F7\u2103\uFF12",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer1.length
- );
-
- // test case 2
- let testDataBuffer2 = [0x31, 0x51, 0x63, 0x82, 0x58, 0x51, 0x63, 0x82,
- 0x60, 0x82, 0x81, 0x51, 0x63, 0xB1, 0xAF, 0x51,
- 0x63, 0x83, 0x41, 0x83, 0x96, 0x51, 0x63, 0x82,
- 0xA0, 0x51, 0x63, 0x93, 0xFA, 0x51, 0x63, 0x3A,
- 0x3C, 0x51, 0x63, 0x81, 0x80, 0x81, 0x8E, 0x51,
- 0x63, 0x31, 0x82, 0x70, 0x82, 0x85, 0x82, 0x58,
- 0x82, 0x70, 0x82, 0x85, 0x41, 0x61, 0x82, 0x70,
- 0x82, 0x85, 0xB1, 0xAF, 0x82, 0x70, 0x82, 0x85,
- 0x83, 0x41, 0x83, 0x96, 0x82, 0x70, 0x82, 0x85,
- 0x82, 0xA0, 0x82, 0x70, 0x82, 0x85, 0x93, 0xFA,
- 0x82, 0x70, 0x82, 0x85, 0x3A, 0x3C, 0x82, 0x70,
- 0x82, 0x85, 0x81, 0x80, 0x81, 0x8E, 0x82, 0x70,
- 0x82, 0x85];
-
- test_decodePDUMsg(
- testDataBuffer2,
- "\u0031\u0051\u0063\uFF19\u0051\u0063\uFF21\uFF41\u0051\u0063\uFF71\uFF6F\u0051\u0063\u30A2\u30F6\u0051\u0063\u3042\u0051\u0063\u65E5\u0051\u0063\u003A\u003C\u0051\u0063\u00F7\u2103\u0051\u0063\u0031\uFF31\uFF45\uFF19\uFF31\uFF45\u0041\u0061\uFF31\uFF45\uFF71\uFF6F\uFF31\uFF45\u30A2\u30F6\uFF31\uFF45\u3042\uFF31\uFF45\u65E5\uFF31\uFF45\u003A\u003C\uFF31\uFF45\u00F7\u2103\uFF31\uFF45",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer2.length
- );
-
- // test case 3
- let testDataBuffer3 = [0x31, 0xC2, 0xDF, 0x82, 0x58, 0xC2, 0xDF, 0x41,
- 0x61, 0xC2, 0xDF, 0x82, 0x60, 0x82, 0x81, 0xC2,
- 0xDF, 0x83, 0x41, 0x83, 0x96, 0xC2, 0xDF, 0x82,
- 0xA0, 0xC2, 0xDF, 0x93, 0xFA, 0xC2, 0xDF, 0x3A,
- 0x3C, 0xC2, 0xDF, 0x81, 0x80, 0x81, 0x8E, 0xC2,
- 0xDF, 0x31, 0x83, 0x51, 0x83, 0x87, 0x82, 0x58,
- 0x83, 0x51, 0x83, 0x87, 0x41, 0x61, 0x83, 0x51,
- 0x83, 0x87, 0x82, 0x60, 0x82, 0x81, 0x83, 0x51,
- 0x83, 0x87, 0xB1, 0xAF, 0x83, 0x51, 0x83, 0x87,
- 0x82, 0xA0, 0x83, 0x51, 0x83, 0x87, 0x93, 0xFA,
- 0x83, 0x51, 0x83, 0x87, 0x3A, 0x3C, 0x83, 0x51,
- 0x83, 0x87, 0x81, 0x80, 0x81, 0x8E, 0x83, 0x51,
- 0x83, 0x87];
-
- test_decodePDUMsg(
- testDataBuffer3,
- "\u0031\uFF82\uFF9F\uFF19\uFF82\uFF9F\u0041\u0061\uFF82\uFF9F\uFF21\uFF41\uFF82\uFF9F\u30A2\u30F6\uFF82\uFF9F\u3042\uFF82\uFF9F\u65E5\uFF82\uFF9F\u003A\u003C\uFF82\uFF9F\u00F7\u2103\uFF82\uFF9F\u0031\u30B2\u30E7\uFF19\u30B2\u30E7\u0041\u0061\u30B2\u30E7\uFF21\uFF41\u30B2\u30E7\uFF71\uFF6F\u30B2\u30E7\u3042\u30B2\u30E7\u65E5\u30B2\u30E7\u003A\u003C\u30B2\u30E7\u00F7\u2103\u30B2\u30E7",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer3.length
- );
-
- // test case 4
- let testDataBuffer4 = [0x31, 0x82, 0xB0, 0x82, 0x58, 0x82, 0xB0, 0x41,
- 0x61, 0x82, 0xB0, 0x82, 0x60, 0x82, 0x81, 0x82,
- 0xB0, 0xB1, 0xAF, 0x82, 0xB0, 0x83, 0x41, 0x83,
- 0x96, 0x82, 0xB0, 0x93, 0xFA, 0x82, 0xB0, 0x3A,
- 0x3C, 0x82, 0xB0, 0x81, 0x80, 0x81, 0x8E, 0x82,
- 0xB0, 0x31, 0x88, 0xA4, 0x82, 0x58, 0x88, 0xA4,
- 0x41, 0x61, 0x88, 0xA4, 0x82, 0x60, 0x82, 0x81,
- 0x88, 0xA4, 0xB1, 0xAF, 0x88, 0xA4, 0x83, 0x41,
- 0x83, 0x96, 0x88, 0xA4, 0x82, 0xA0, 0x88, 0xA4,
- 0x3A, 0x3C, 0x88, 0xA4, 0x81, 0x80, 0x81, 0x8E,
- 0x88, 0xA4];
-
- test_decodePDUMsg(
- testDataBuffer4,
- "\u0031\u3052\uFF19\u3052\u0041\u0061\u3052\uFF21\uFF41\u3052\uFF71\uFF6F\u3052\u30A2\u30F6\u3052\u65E5\u3052\u003A\u003C\u3052\u00F7\u2103\u3052\u0031\u611B\uFF19\u611B\u0041\u0061\u611B\uFF21\uFF41\u611B\uFF71\uFF6F\u611B\u30A2\u30F6\u611B\u3042\u611B\u003A\u003C\u611B\u00F7\u2103\u611B",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer4.length
- );
-
- // test case 5
- let testDataBuffer5 = [0x31, 0x40, 0x82, 0x58, 0x40, 0x41, 0x61, 0x40,
- 0x82, 0x60, 0x82, 0x81, 0x40, 0xB1, 0xAF, 0x40,
- 0x83, 0x41, 0x83, 0x96, 0x40, 0x82, 0xA0, 0x40,
- 0x93, 0xFA, 0x40, 0x81, 0x80, 0x81, 0x8E, 0x40,
- 0x31, 0x81, 0x9B, 0x82, 0x58, 0x81, 0x9B, 0x41,
- 0x61, 0x81, 0x9B, 0x82, 0x60, 0x82, 0x81, 0x81,
- 0x9B, 0xB1, 0xAF, 0x81, 0x9B, 0x83, 0x41, 0x83,
- 0x96, 0x81, 0x9B, 0x82, 0xA0, 0x81, 0x9B, 0x93,
- 0xFA, 0x81, 0x9B, 0x3A, 0x3C, 0x81, 0x9B];
-
- test_decodePDUMsg(
- testDataBuffer5,
- "\u0031\u0040\uFF19\u0040\u0041\u0061\u0040\uFF21\uFF41\u0040\uFF71\uFF6F\u0040\u30A2\u30F6\u0040\u3042\u0040\u65E5\u0040\u00F7\u2103\u0040\u0031\u25CB\uFF19\u25CB\u0041\u0061\u25CB\uFF21\uFF41\u25CB\uFF71\uFF6F\u25CB\u30A2\u30F6\u25CB\u3042\u25CB\u65E5\u25CB\u003A\u003C\u25CB",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer5.length
- );
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_gsmpduhelper.js b/dom/system/gonk/tests/test_ril_worker_sms_gsmpduhelper.js
deleted file mode 100644
index f52c64cf8..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_gsmpduhelper.js
+++ /dev/null
@@ -1,282 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify GsmPDUHelper#readDataCodingScheme.
- */
-add_test(function test_GsmPDUHelper_readDataCodingScheme() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- function test_dcs(dcs, encoding, messageClass, mwi) {
- helper.readHexOctet = function() {
- return dcs;
- }
-
- let msg = {};
- helper.readDataCodingScheme(msg);
-
- equal(msg.dcs, dcs);
- equal(msg.encoding, encoding);
- equal(msg.messageClass, messageClass);
- equal(msg.mwi == null, mwi == null);
- if (mwi != null) {
- equal(msg.mwi.active, mwi.active);
- equal(msg.mwi.discard, mwi.discard);
- equal(msg.mwi.msgCount, mwi.msgCount);
- }
- }
-
- // Group 00xx
- // Bit 3 and 2 indicate the character set being used.
- test_dcs(0x00, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x04, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x08, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x0C, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- // Bit 4, if set to 0, indicates that bits 1 to 0 are reserved and have no
- // message class meaning.
- test_dcs(0x01, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x02, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x03, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- // Bit 4, if set to 1, indicates that bits 1 to 0 have a message class meaning.
- test_dcs(0x10, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
- test_dcs(0x11, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
- test_dcs(0x12, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
- test_dcs(0x13, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
-
- // Group 01xx
- test_dcs(0x50, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
-
- // Group 1000..1011: reserved
- test_dcs(0x8F, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x9F, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0xAF, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0xBF, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
-
- // Group 1100: Message Waiting Indication Group: Discard Message
- // Bit 3 indicates Indication Sense:
- test_dcs(0xC0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: false, discard: true, msgCount: 0});
- test_dcs(0xC8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: true, msgCount: -1});
- // Bit 2 is reserved, and set to 0:
- test_dcs(0xCC, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: true, msgCount: -1});
-
- // Group 1101: Message Waiting Indication Group: Store Message
- // Bit 3 indicates Indication Sense:
- test_dcs(0xD0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: false, discard: false, msgCount: 0});
- test_dcs(0xD8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: false, msgCount: -1});
- // Bit 2 is reserved, and set to 0:
- test_dcs(0xDC, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: false, msgCount: -1});
-
- // Group 1110: Message Waiting Indication Group: Store Message, UCS2
- // Bit 3 indicates Indication Sense:
- test_dcs(0xE0, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: false, discard: false, msgCount: 0});
- test_dcs(0xE8, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: false, msgCount: -1});
- // Bit 2 is reserved, and set to 0:
- test_dcs(0xEC, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: false, msgCount: -1});
-
- // Group 1111
- test_dcs(0xF0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
- test_dcs(0xF1, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
- test_dcs(0xF2, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
- test_dcs(0xF3, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
- test_dcs(0xF4, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
- test_dcs(0xF5, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
- test_dcs(0xF6, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
- test_dcs(0xF7, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
- // Bit 3 is reserved and should be set to 0, but if it doesn't we should
- // ignore it.
- test_dcs(0xF8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
-
- run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper#writeStringAsSeptets() padding bits handling.
- */
-add_test(function test_GsmPDUHelper_writeStringAsSeptets() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- helper.resetOctetWritten = function() {
- helper.octetsWritten = 0;
- };
- helper.writeHexOctet = function() {
- helper.octetsWritten++;
- };
-
- let base = "AAAAAAAA"; // Base string of 8 characters long
- for (let len = 0; len < 8; len++) {
- let str = base.substring(0, len);
-
- for (let paddingBits = 0; paddingBits < 8; paddingBits++) {
- do_print("Verifying GsmPDUHelper.writeStringAsSeptets("
- + str + ", " + paddingBits + ", <default>, <default>)");
- helper.resetOctetWritten();
- helper.writeStringAsSeptets(str, paddingBits, PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- equal(Math.ceil(((len * 7) + paddingBits) / 8),
- helper.octetsWritten);
- }
- }
-
- run_next_test();
-});
-
-/**
- * Verify that encoding with Spanish locking shift table generates the same
- * septets as with GSM default alphabet table.
- *
- * Bug 1138841 - Incorrect Spanish national language locking shift table
- * definition.
- */
-add_test(function test_GsmPDUHelper_writeStringAsSeptets_spanish_fallback() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = [];
- helper.writeHexOctet = function(octet) {
- buf.push(octet);
- }
-
- // Simple message string which is covered by GSM default alphabet.
- let msg = "The quick brown fox jumps over the lazy dog";
-
- // Encoded with GSM default alphabet.
- helper.writeStringAsSeptets(msg, 0 /* paddingBits */,
- PDU_NL_IDENTIFIER_DEFAULT, PDU_NL_IDENTIFIER_DEFAULT);
- let octetsWithDefaultTable = buf;
- buf = [];
-
- // Encoded with Spanish locking shift table.
- helper.writeStringAsSeptets(msg, 0 /* paddingBits */,
- PDU_NL_IDENTIFIER_SPANISH, PDU_NL_IDENTIFIER_SPANISH);
-
- // The length and content should be equal to what encoded with GSM default
- // alphabet.
- equal(octetsWithDefaultTable.length, buf.length);
- for (let i = 0; i < buf.length; i++) {
- equal(octetsWithDefaultTable[i], buf[i]);
- }
-
- run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper#readAddress
- */
-add_test(function test_GsmPDUHelper_readAddress() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- function test_address(addrHex, addrString) {
- let uint16Array = [];
- let ix = 0;
- for (let i = 0; i < addrHex.length; ++i) {
- uint16Array[i] = addrHex[i].charCodeAt();
- }
-
- context.Buf.readUint16 = function(){
- if(ix >= uint16Array.length) {
- do_throw("out of range in uint16Array");
- }
- return uint16Array[ix++];
- }
- let length = helper.readHexOctet();
- let parsedAddr = helper.readAddress(length);
- equal(parsedAddr, addrString);
- }
-
- // For AlphaNumeric
- test_address("04D01100", "_@");
- test_address("04D01000", "\u0394@");
-
- // Direct prepand
- test_address("0B914151245584F6", "+14154255486");
- test_address("0E914151245584B633", "+14154255486#33");
-
- // PDU_TOA_NATIONAL
- test_address("0BA14151245584F6", "14154255486");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_nl_tables.js b/dom/system/gonk/tests/test_ril_worker_sms_nl_tables.js
deleted file mode 100644
index 32bc5dc2a..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_nl_tables.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-const ESCAPE = "\uffff";
-const RESCTL = "\ufffe";
-const LF = "\n";
-const CR = "\r";
-const SP = " ";
-const FF = "\u000c";
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify validity of the national language tables
- */
-add_test(function test_nl_locking_shift_tables_validity() {
- for (let lst = 0; lst < PDU_NL_LOCKING_SHIFT_TABLES.length; lst++) {
- do_print("Verifying PDU_NL_LOCKING_SHIFT_TABLES[" + lst + "]");
-
- let table = PDU_NL_LOCKING_SHIFT_TABLES[lst];
-
- // Make sure table length is 128, or it will break table lookup algorithm.
- equal(table.length, 128);
-
- // Make sure special values are preserved.
- equal(table[PDU_NL_EXTENDED_ESCAPE], ESCAPE);
- equal(table[PDU_NL_LINE_FEED], LF);
- equal(table[PDU_NL_CARRIAGE_RETURN], CR);
- equal(table[PDU_NL_SPACE], SP);
- }
-
- run_next_test();
-});
-
-add_test(function test_nl_single_shift_tables_validity() {
- for (let sst = 0; sst < PDU_NL_SINGLE_SHIFT_TABLES.length; sst++) {
- do_print("Verifying PDU_NL_SINGLE_SHIFT_TABLES[" + sst + "]");
-
- let table = PDU_NL_SINGLE_SHIFT_TABLES[sst];
-
- // Make sure table length is 128, or it will break table lookup algorithm.
- equal(table.length, 128);
-
- // Make sure special values are preserved.
- equal(table[PDU_NL_EXTENDED_ESCAPE], ESCAPE);
- equal(table[PDU_NL_PAGE_BREAK], FF);
- equal(table[PDU_NL_RESERVED_CONTROL], RESCTL);
- }
-
- run_next_test();
-});
-
-add_test(function test_gsm_sms_strict_7bit_charmap_validity() {
- let defaultTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- let defaultShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- for (let from in GSM_SMS_STRICT_7BIT_CHARMAP) {
- let to = GSM_SMS_STRICT_7BIT_CHARMAP[from];
- do_print("Verifying GSM_SMS_STRICT_7BIT_CHARMAP[\"\\u0x"
- + from.charCodeAt(0).toString(16) + "\"] => \"\\u"
- + to.charCodeAt(0).toString(16) + "\"");
-
- // Make sure "from" is not in default table
- equal(defaultTable.indexOf(from), -1);
- equal(defaultShiftTable.indexOf(from), -1);
- // Make sure "to" is in default table
- if ((defaultTable.indexOf(to) < 0)
- && (defaultShiftTable.indexOf(to) < 0)) {
- equal(false, true);
- }
- }
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_segment_info.js b/dom/system/gonk/tests/test_ril_worker_sms_segment_info.js
deleted file mode 100644
index 2b29ac60e..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_segment_info.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gSmsSegmentHelper", function() {
- let ns = {};
- Cu.import("resource://gre/modules/SmsSegmentHelper.jsm", ns);
- return ns.SmsSegmentHelper;
-});
-
-const ESCAPE = "\uffff";
-const RESCTL = "\ufffe";
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify SmsSegmentHelper#countGsm7BitSeptets() and
- * GsmPDUHelper#writeStringAsSeptets() algorithm match each other.
- */
-add_test(function test_SmsSegmentHelper__countGsm7BitSeptets() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- helper.resetOctetWritten = function() {
- helper.octetsWritten = 0;
- };
- helper.writeHexOctet = function() {
- helper.octetsWritten++;
- };
-
- function do_check_calc(str, expectedCalcLen, lst, sst, strict7BitEncoding, strToWrite) {
- equal(expectedCalcLen,
- gSmsSegmentHelper
- .countGsm7BitSeptets(str,
- PDU_NL_LOCKING_SHIFT_TABLES[lst],
- PDU_NL_SINGLE_SHIFT_TABLES[sst],
- strict7BitEncoding));
-
- helper.resetOctetWritten();
- strToWrite = strToWrite || str;
- helper.writeStringAsSeptets(strToWrite, 0, lst, sst);
- equal(Math.ceil(expectedCalcLen * 7 / 8), helper.octetsWritten);
- }
-
- // Test calculation encoded message length using both locking/single shift tables.
- for (let lst = 0; lst < PDU_NL_LOCKING_SHIFT_TABLES.length; lst++) {
- let langTable = PDU_NL_LOCKING_SHIFT_TABLES[lst];
-
- let str = langTable.substring(0, PDU_NL_EXTENDED_ESCAPE)
- + langTable.substring(PDU_NL_EXTENDED_ESCAPE + 1);
-
- for (let sst = 0; sst < PDU_NL_SINGLE_SHIFT_TABLES.length; sst++) {
- let langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[sst];
-
- // <escape>, <resctrl> should be ignored.
- do_check_calc(ESCAPE + RESCTL, 0, lst, sst);
-
- // Characters defined in locking shift table should be encoded directly.
- do_check_calc(str, str.length, lst, sst);
-
- let [str1, str2] = ["", ""];
- for (let i = 0; i < langShiftTable.length; i++) {
- if ((i == PDU_NL_EXTENDED_ESCAPE) || (i == PDU_NL_RESERVED_CONTROL)) {
- continue;
- }
-
- let c = langShiftTable[i];
- if (langTable.indexOf(c) >= 0) {
- str1 += c;
- } else {
- str2 += c;
- }
- }
-
- // Characters found in both locking/single shift tables should be
- // directly encoded.
- do_check_calc(str1, str1.length, lst, sst);
-
- // Characters found only in single shift tables should be encoded as
- // <escape><code>, therefore doubles its original length.
- do_check_calc(str2, str2.length * 2, lst, sst);
- }
- }
-
- // Bug 790192: support strict GSM SMS 7-Bit encoding
- let str = "", strToWrite = "", gsmLen = 0;
- for (let c in GSM_SMS_STRICT_7BIT_CHARMAP) {
- str += c;
- strToWrite += GSM_SMS_STRICT_7BIT_CHARMAP[c];
- if (PDU_NL_LOCKING_SHIFT_TABLES.indexOf(GSM_SMS_STRICT_7BIT_CHARMAP[c])) {
- gsmLen += 1;
- } else {
- gsmLen += 2;
- }
- }
- do_check_calc(str, gsmLen,
- PDU_NL_IDENTIFIER_DEFAULT, PDU_NL_IDENTIFIER_DEFAULT,
- true, strToWrite);
-
- run_next_test();
-});
-
diff --git a/dom/system/gonk/tests/test_ril_worker_smsc_address.js b/dom/system/gonk/tests/test_ril_worker_smsc_address.js
deleted file mode 100644
index c8c283b7c..000000000
--- a/dom/system/gonk/tests/test_ril_worker_smsc_address.js
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-const SMSC_ATT = '+13123149810';
-const SMSC_ATT_TYPO = '+++1312@@@314$$$9,8,1,0';
-const SMSC_ATT_TEXT = '"+13123149810",145';
-const SMSC_ATT_TEXT_INCORRECT_TOA = '"+13123149810",129';
-const SMSC_ATT_PDU = '07913121139418F0';
-const SMSC_O2 = '+447802000332';
-const SMSC_O2_TEXT = '"+447802000332",145';
-const SMSC_O2_PDU = '0791448720003023';
-const SMSC_EMPTY = '';
-const SMSC_TON_UNKNOWN = '0407485455'
-const SMSC_TON_UNKNOWN_TEXT = '"0407485455",129';
-const SMSC_TON_UNKNOWN_TEXT_NO_TOA = '"0407485455"';
-const SMSC_TON_UNKNOWN_TEXT_INVALID_TOA = '"0407485455",abc';
-const SMSC_TON_UNKNOWN_PDU = '06814070844555';
-const SMSC_EMPTY_PDU = 'FFFFFFFFFFFFFFFFFFFFFFFF';
-const SMSC_EMPTY_TEXT = '';
-
-function run_test() {
- run_next_test();
-}
-
-function setSmsc(context, smsc, ton, npi, expected) {
- context.Buf.postRILMessage = function() {
- equal(this.readString(), expected);
- };
-
- context.RIL.setSmscAddress({
- smscAddress: smsc,
- typeOfNumber: ton,
- numberPlanIdentification: npi
- });
-}
-
-function getSmsc(worker, context, raw, smsc, ton, npi) {
- worker.postMessage = function(message) {
- equal(message.smscAddress, smsc);
- equal(message.typeOfNumber, ton);
- equal(message.numberPlanIdentification, npi);
- }
-
- context.Buf.writeString(raw);
- context.RIL[REQUEST_GET_SMSC_ADDRESS](0, { rilMessageType: "getSmscAddress"});
-}
-
-add_test(function test_setSmscAddress() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let parcelTypes = [];
- context.Buf.newParcel = (type, options) => parcelTypes.push(type);
-
- // Test text mode.
- worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "text";
-
- setSmsc(context, SMSC_ATT, 1, 1, SMSC_ATT_TEXT);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_O2, 1, 1, SMSC_O2_TEXT);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_ATT_TYPO, 1, 1, SMSC_ATT_TEXT);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_TON_UNKNOWN, 0, 1, SMSC_TON_UNKNOWN_TEXT);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- // Test pdu mode.
- worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "pdu";
-
- setSmsc(context, SMSC_ATT, 1, 1, SMSC_ATT_PDU);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_O2, 1, 1, SMSC_O2_PDU);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_ATT_TYPO, 1, 1, SMSC_ATT_PDU);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_TON_UNKNOWN, 0, 1, SMSC_TON_UNKNOWN_PDU);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- run_next_test();
-});
-
-add_test(function test_getSmscAddress() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
-
- // Test text mode.
- worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "text";
- getSmsc(worker, context, SMSC_ATT_TEXT, SMSC_ATT, 1, 1);
- getSmsc(worker, context, SMSC_ATT_TEXT_INCORRECT_TOA, SMSC_ATT, 1, 1);
- getSmsc(worker, context, SMSC_O2_TEXT, SMSC_O2, 1, 1);
- getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT, SMSC_TON_UNKNOWN, 0, 1);
- getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT_NO_TOA, SMSC_TON_UNKNOWN, 0, 1);
- getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT_INVALID_TOA, SMSC_TON_UNKNOWN,
- 0, 1);
- getSmsc(worker, context, SMSC_EMPTY_TEXT, SMSC_EMPTY, 0, 1);
-
- // Test pdu mode.
- worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "pdu";
- getSmsc(worker, context, SMSC_ATT_PDU, SMSC_ATT, 1, 1);
- getSmsc(worker, context, SMSC_O2_PDU, SMSC_O2, 1, 1);
- getSmsc(worker, context, SMSC_TON_UNKNOWN_PDU, SMSC_TON_UNKNOWN, 0, 1);
- getSmsc(worker, context, SMSC_EMPTY_PDU, SMSC_EMPTY, 0, 1);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_ssn.js b/dom/system/gonk/tests/test_ril_worker_ssn.js
deleted file mode 100644
index ea0a2a599..000000000
--- a/dom/system/gonk/tests/test_ril_worker_ssn.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_notification() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- function Call(callIndex, number) {
- this.callIndex = callIndex;
- this.number = number;
- }
-
- Call.prototype = {
- // Should use CALL_STATE_ACTIVE.
- // Any new outgoing call (state = dialing or alerting) will be drop if there
- // is no pending outgoing call created before.
- state: CALL_STATE_ACTIVE,
- //callIndex: 0,
- toa: 0,
- isMpty: false,
- isMT: false,
- als: 0,
- isVoice: true,
- isVoicePrivacy: false,
- //number: null,
- numberPresentation: 0,
- name: null,
- namePresentation: 0,
- uusInfo: null
- };
-
- let oneCall = {
- 0: new Call(0, '00000')
- };
-
- let twoCalls = {
- 0: new Call(0, '00000'),
- 1: new Call(1, '11111')
- };
-
- function testNotification(calls, code, number, resultNotification) {
-
- let testInfo = {calls: calls, code: code, number: number,
- resultNotification: resultNotification};
- do_print('Test case info: ' + JSON.stringify(testInfo));
-
- // Set current calls.
- context.RIL.sendChromeMessage({
- rilMessageType: "currentCalls",
- calls: calls
- });
-
- let notificationInfo = {
- notificationType: 1, // MT
- code: code,
- index: 0,
- type: 0,
- number: number
- };
-
- context.RIL._processSuppSvcNotification(notificationInfo);
-
- let postedMessage = workerHelper.postedMessage;
- equal(postedMessage.rilMessageType, 'suppSvcNotification');
- equal(postedMessage.number, number);
- equal(postedMessage.notification, resultNotification);
-
- // Clear all existed calls.
- context.RIL.sendChromeMessage({
- rilMessageType: "currentCalls",
- calls: {}
- });
- }
-
- testNotification(oneCall, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, null,
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- testNotification(oneCall, SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED, null,
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, null,
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED, null,
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, '00000',
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, '11111',
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, '22222',
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_stk.js b/dom/system/gonk/tests/test_ril_worker_stk.js
deleted file mode 100644
index 49b914e89..000000000
--- a/dom/system/gonk/tests/test_ril_worker_stk.js
+++ /dev/null
@@ -1,1698 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Helper function.
- */
-function newUint8SupportOutgoingIndexWorker() {
- let worker = newWorker();
- let index = 4; // index for read
- let buf = [0, 0, 0, 0]; // Preserved parcel size
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.writeUint8 = function(value) {
- if (context.Buf.outgoingIndex >= buf.length) {
- buf.push(value);
- } else {
- buf[context.Buf.outgoingIndex] = value;
- }
-
- context.Buf.outgoingIndex++;
- };
-
- context.Buf.readUint8 = function() {
- return buf[index++];
- };
-
- context.Buf.seekIncoming = function(offset) {
- index += offset;
- };
-
- worker.debug = do_print;
-
- return worker;
-}
-
-// Test RIL requests related to STK.
-/**
- * Verify if RIL.sendStkTerminalProfile be called.
- */
-add_test(function test_if_send_stk_terminal_profile() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let profileSend = false;
- context.RIL.sendStkTerminalProfile = function(data) {
- profileSend = true;
- };
-
- let iccStatus = {
- gsmUmtsSubscriptionAppIndex: 0,
- apps: [{
- app_state: CARD_APPSTATE_READY,
- app_type: CARD_APPTYPE_USIM
- }],
- };
- worker.RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = false;
-
- context.RIL._processICCStatus(iccStatus);
-
- equal(profileSend, false);
-
- run_next_test();
-});
-
-/**
- * Verify RIL.sendStkTerminalProfile
- */
-add_test(function test_send_stk_terminal_profile() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let buf = context.Buf;
-
- ril.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
-
- buf.seekIncoming(8);
- let profile = buf.readString();
- for (let i = 0; i < STK_SUPPORTED_TERMINAL_PROFILE.length; i++) {
- equal(parseInt(profile.substring(2 * i, 2 * i + 2), 16),
- STK_SUPPORTED_TERMINAL_PROFILE[i]);
- }
-
- run_next_test();
-});
-
-/**
- * Verify STK terminal response
- */
-add_test(function test_stk_terminal_response() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 44 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // TEXT LENGTH(10))
- equal(this.readInt32(), 44);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_PROVIDE_LOCAL_INFO);
- equal(pduHelper.readHexOctet(), STK_LOCAL_INFO_NNA);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_OK);
-
- // Text
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 8);
- equal(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_7BIT_PACKED);
- equal(pduHelper.readSeptetsToString(7, 0, PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT), "Mozilla");
-
- run_next_test();
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_PROVIDE_LOCAL_INFO,
- commandQualifier: STK_LOCAL_INFO_NNA,
- options: {
- isPacked: true
- }
- },
- input: "Mozilla",
- resultCode: STK_RESULT_OK
- };
- context.RIL.sendStkTerminalResponse(response);
-});
-
-/**
- * Verify STK terminal response : GET INPUT with empty string.
- *
- * @See |TERMINAL RESPONSE: GET INPUT 1.9.1A| of 27.22.4.3.1 GET INPUT (normal)
- * in TS 102 384.
- */
-add_test(function test_stk_terminal_response_get_input_empty_string() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 30 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // TEXT LENGTH(3))
- equal(this.readInt32(), 30);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_GET_INPUT);
- equal(pduHelper.readHexOctet(), 0x00);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_OK);
-
- // Text
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_8BIT);
-
- run_next_test();
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_GET_INPUT,
- commandQualifier: 0x00,
- options: {
- minLength: 0,
- maxLength: 1,
- defaultText: "<SEND>"
- }
- },
- input: "",
- resultCode: STK_RESULT_OK
- };
- context.RIL.sendStkTerminalResponse(response);
-});
-
-/**
- * Verify STK terminal response : GET INPUT with 160 unpacked characters.
- *
- * @See |TERMINAL RESPONSE: GET INPUT 1.8.1| of 27.22.4.3.1 GET INPUT (normal)
- * in TS 102 384.
- */
-add_test(function test_stk_terminal_response_get_input_160_unpacked_characters() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
- let iccPduHelper = context.ICCPDUHelper;
- let TEST_TEXT_STRING = "***1111111111###" +
- "***2222222222###" +
- "***3333333333###" +
- "***4444444444###" +
- "***5555555555###" +
- "***6666666666###" +
- "***7777777777###" +
- "***8888888888###" +
- "***9999999999###" +
- "***0000000000###";
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 352 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // TEXT LENGTH(164))
- equal(this.readInt32(), 352);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_GET_INPUT);
- equal(pduHelper.readHexOctet(), 0x00);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_OK);
-
- // Text
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- // C-TLV Length Encoding: 161 = 0x81 0xA1
- equal(pduHelper.readHexOctet(), 0x81);
- equal(pduHelper.readHexOctet(), 0xA1);
- equal(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_8BIT);
- equal(iccPduHelper.read8BitUnpackedToString(160), TEST_TEXT_STRING);
-
- run_next_test();
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_GET_INPUT,
- commandQualifier: 0x00,
- options: {
- minLength: 160,
- maxLength: 160,
- text: TEST_TEXT_STRING
- }
- },
- input: TEST_TEXT_STRING,
- resultCode: STK_RESULT_OK
- };
- context.RIL.sendStkTerminalResponse(response);
-});
-
-/**
- * Verify STK terminal response : GET_INKEY - NO_RESPONSE_FROM_USER with
- * duration provided.
- *
- * @See |27.22.4.2.8 GET INKEY (Variable Time out)| in TS 102 384.
- */
-add_test(function test_stk_terminal_response_get_inkey_no_response_from_user() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 32 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // DURATION(4))
- equal(this.readInt32(), 32);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_GET_INKEY);
- equal(pduHelper.readHexOctet(), 0x00);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_NO_RESPONSE_FROM_USER);
-
- // Duration, Type-Length-Value(Time unit, Time interval)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DURATION);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_TIME_UNIT_SECOND);
- equal(pduHelper.readHexOctet(), 10);
-
- run_next_test();
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_GET_INKEY,
- commandQualifier: 0x00,
- options: {
- duration: {
- timeUnit: STK_TIME_UNIT_SECOND,
- timeInterval: 10
- },
- text: 'Enter "+"'
- }
- },
- resultCode: STK_RESULT_NO_RESPONSE_FROM_USER
- };
- context.RIL.sendStkTerminalResponse(response);
-});
-
-/**
- * Verify STK terminal response : GET_INKEY - YES/NO request
- */
-add_test(function test_stk_terminal_response_get_inkey() {
- function do_test(isYesNo) {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 32 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // TEXT LENGTH(4))
- equal(this.readInt32(), 32);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_GET_INKEY);
- equal(pduHelper.readHexOctet(), 0x04);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_OK);
-
- // Yes/No response
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_8BIT);
- equal(pduHelper.readHexOctet(), isYesNo ? 0x01 : 0x00);
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_GET_INKEY,
- commandQualifier: 0x04,
- options: {
- isYesNoRequested: true
- }
- },
- isYesNo: isYesNo,
- resultCode: STK_RESULT_OK
- };
-
- context.RIL.sendStkTerminalResponse(response);
- };
-
- // Test "Yes" response
- do_test(true);
- // Test "No" response
- do_test(false);
-
- run_next_test();
-});
-
-/**
- * Verify STK terminal response with additional information.
- */
-add_test(function test_stk_terminal_response_with_additional_info() {
- function do_test(aInfo) {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Length 26 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(4))
- equal(this.readInt32(), 26);
-
- // Command Details, Type-Length-Value(commandNumber, typeOfCommand, commandQualifier)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_DISPLAY_TEXT);
- equal(pduHelper.readHexOctet(), 0x01);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result, Type-Length-Value(General result, Additional information on result)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
- equal(pduHelper.readHexOctet(), aInfo);
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_DISPLAY_TEXT,
- commandQualifier: 0x01,
- options: {
- isHighPriority: true
- }
- },
- resultCode: STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS,
- additionalInformation: aInfo
- };
-
- context.RIL.sendStkTerminalResponse(response);
- };
-
- do_test(0x01); // 'Screen is busy'
-
- run_next_test();
-});
-
-// Test ComprehensionTlvHelper
-
-/**
- * Verify ComprehensionTlvHelper.writeLocationInfoTlv
- */
-add_test(function test_write_location_info_tlv() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let tlvHelper = context.ComprehensionTlvHelper;
-
- // Test with 2-digit mnc, and gsmCellId obtained from UMTS network.
- let loc = {
- mcc: "466",
- mnc: "92",
- gsmLocationAreaCode : 10291,
- gsmCellId: 19072823
- };
- tlvHelper.writeLocationInfoTlv(loc);
-
- let tag = pduHelper.readHexOctet();
- equal(tag, COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
-
- let length = pduHelper.readHexOctet();
- equal(length, 9);
-
- let mcc_mnc = pduHelper.readSwappedNibbleBcdString(3);
- equal(mcc_mnc, "46692");
-
- let lac = (pduHelper.readHexOctet() << 8) | pduHelper.readHexOctet();
- equal(lac, 10291);
-
- let cellId = (pduHelper.readHexOctet() << 24) |
- (pduHelper.readHexOctet() << 16) |
- (pduHelper.readHexOctet() << 8) |
- (pduHelper.readHexOctet());
- equal(cellId, 19072823);
-
- // Test with 1-digit mnc, and gsmCellId obtained from GSM network.
- loc = {
- mcc: "466",
- mnc: "02",
- gsmLocationAreaCode : 10291,
- gsmCellId: 65534
- };
- tlvHelper.writeLocationInfoTlv(loc);
-
- tag = pduHelper.readHexOctet();
- equal(tag, COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
-
- length = pduHelper.readHexOctet();
- equal(length, 7);
-
- mcc_mnc = pduHelper.readSwappedNibbleBcdString(3);
- equal(mcc_mnc, "46602");
-
- lac = (pduHelper.readHexOctet() << 8) | pduHelper.readHexOctet();
- equal(lac, 10291);
-
- cellId = (pduHelper.readHexOctet() << 8) | (pduHelper.readHexOctet());
- equal(cellId, 65534);
-
- // Test with 3-digit mnc, and gsmCellId obtained from GSM network.
- loc = {
- mcc: "466",
- mnc: "222",
- gsmLocationAreaCode : 10291,
- gsmCellId: 65534
- };
- tlvHelper.writeLocationInfoTlv(loc);
-
- tag = pduHelper.readHexOctet();
- equal(tag, COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
-
- length = pduHelper.readHexOctet();
- equal(length, 7);
-
- mcc_mnc = pduHelper.readSwappedNibbleBcdString(3);
- equal(mcc_mnc, "466222");
-
- lac = (pduHelper.readHexOctet() << 8) | pduHelper.readHexOctet();
- equal(lac, 10291);
-
- cellId = (pduHelper.readHexOctet() << 8) | (pduHelper.readHexOctet());
- equal(cellId, 65534);
-
- run_next_test();
-});
-
-/**
- * Verify ComprehensionTlvHelper.writeErrorNumber
- */
-add_test(function test_write_disconnecting_cause() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let tlvHelper = context.ComprehensionTlvHelper;
-
- tlvHelper.writeCauseTlv(RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BUSY]);
- let tag = pduHelper.readHexOctet();
- equal(tag, COMPREHENSIONTLV_TAG_CAUSE | COMPREHENSIONTLV_FLAG_CR);
- let len = pduHelper.readHexOctet();
- equal(len, 2); // We have one cause.
- let standard = pduHelper.readHexOctet();
- equal(standard, 0x60);
- let cause = pduHelper.readHexOctet();
- equal(cause, 0x80 | CALL_FAIL_BUSY);
-
- run_next_test();
-});
-
-/**
- * Verify ComprehensionTlvHelper.getSizeOfLengthOctets
- */
-add_test(function test_get_size_of_length_octets() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let tlvHelper = context.ComprehensionTlvHelper;
-
- let length = 0x70;
- equal(tlvHelper.getSizeOfLengthOctets(length), 1);
-
- length = 0x80;
- equal(tlvHelper.getSizeOfLengthOctets(length), 2);
-
- length = 0x180;
- equal(tlvHelper.getSizeOfLengthOctets(length), 3);
-
- length = 0x18000;
- equal(tlvHelper.getSizeOfLengthOctets(length), 4);
-
- run_next_test();
-});
-
-/**
- * Verify ComprehensionTlvHelper.writeLength
- */
-add_test(function test_write_length() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let tlvHelper = context.ComprehensionTlvHelper;
-
- let length = 0x70;
- tlvHelper.writeLength(length);
- equal(pduHelper.readHexOctet(), length);
-
- length = 0x80;
- tlvHelper.writeLength(length);
- equal(pduHelper.readHexOctet(), 0x81);
- equal(pduHelper.readHexOctet(), length);
-
- length = 0x180;
- tlvHelper.writeLength(length);
- equal(pduHelper.readHexOctet(), 0x82);
- equal(pduHelper.readHexOctet(), (length >> 8) & 0xff);
- equal(pduHelper.readHexOctet(), length & 0xff);
-
- length = 0x18000;
- tlvHelper.writeLength(length);
- equal(pduHelper.readHexOctet(), 0x83);
- equal(pduHelper.readHexOctet(), (length >> 16) & 0xff);
- equal(pduHelper.readHexOctet(), (length >> 8) & 0xff);
- equal(pduHelper.readHexOctet(), length & 0xff);
-
- run_next_test();
-});
-
-// Test Proactive commands.
-
-function test_stk_proactive_command(aOptions) {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
- let stkFactory = context.StkCommandParamsFactory;
-
- let testPdu = aOptions.pdu;
- let testTypeOfCommand = aOptions.typeOfCommand;
- let testIcons = aOptions.icons;
- let testFunc = aOptions.testFunc;
-
- if (testIcons) {
- let ril = context.RIL;
- ril.iccInfoPrivate.sst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x30]; //IMG: 39
- ril.appType = CARD_APPTYPE_SIM;
-
- // skip asynchornous process in IconLoader.loadIcons().
- let iconLoader = context.IconLoader;
- iconLoader.loadIcons = (recordNumbers, onsuccess, onerror) => {
- onsuccess(testIcons);
- };
- }
-
- for(let i = 0 ; i < testPdu.length; i++) {
- pduHelper.writeHexOctet(testPdu[i]);
- }
-
- let berTlv = berHelper.decode(testPdu.length);
- let ctlvs = berTlv.value;
- let ctlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
- let cmdDetails = ctlv.value;
- equal(cmdDetails.typeOfCommand, testTypeOfCommand);
-
- stkFactory.createParam(cmdDetails, ctlvs, (aResult) => {
- cmdDetails.options = aResult;
- testFunc(context, cmdDetails, ctlvs);
- });
-}
-
-/**
- * Verify Proactive command helper : searchForSelectedTags
- */
-add_test(function test_stk_proactive_command_search_for_selected_tags() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
-
- let tag_test = [
- 0xD0,
- 0x3E,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x31,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x32,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x33,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x34,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x35,
- 0x85, 0x00];
-
- for (let i = 0; i < tag_test.length; i++) {
- pduHelper.writeHexOctet(tag_test[i]);
- }
-
- let berTlv = berHelper.decode(tag_test.length);
- let selectedCtlvs =
- stkHelper.searchForSelectedTags(berTlv.value, [COMPREHENSIONTLV_TAG_ALPHA_ID]);
- let tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 1");
-
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 2");
-
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 3");
-
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 4");
-
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 5");
-
- // emulate that the alpha identifier is provided and is a null data object,
- // which is converted to an empty string in ICCPDUHelper.
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- strictEqual(tlv.value.identifier, "");
-
- // emulate that the alpha identifier is not provided
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- strictEqual(tlv, undefined);
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Refresh
- */
-add_test(function test_stk_proactive_command_refresh() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x10,
- 0x81, 0x03, 0x01, 0x01, 0x01,
- 0x82, 0x02, 0x81, 0x82,
- 0x92, 0x05, 0x01, 0x3F, 0x00, 0x2F, 0xE2
- ],
- typeOfCommand: STK_CMD_REFRESH,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let stkHelper = context.StkProactiveCmdHelper;
- let ctlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_FILE_LIST, ctlvs);
- equal(ctlv.value.fileList, "3F002FE2");
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Play Tone
- */
-add_test(function test_stk_proactive_command_play_tone() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x1F,
- 0x81, 0x03, 0x01, 0x20, 0x00,
- 0x82, 0x02, 0x81, 0x03,
- 0x85, 0x09, 0x44, 0x69, 0x61, 0x6C, 0x20, 0x54, 0x6F, 0x6E, 0x65,
- 0x8E, 0x01, 0x01,
- 0x84, 0x02, 0x01, 0x05,
- 0x9E, 0x02, 0x00, 0x01
- ],
- typeOfCommand: STK_CMD_PLAY_TONE,
- icons: [1],
- testFunc: (context, cmdDetails, ctlvs) => {
- let playTone = cmdDetails.options;
-
- equal(playTone.text, "Dial Tone");
- equal(playTone.tone, STK_TONE_TYPE_DIAL_TONE);
- equal(playTone.duration.timeUnit, STK_TIME_UNIT_SECOND);
- equal(playTone.duration.timeInterval, 5);
- equal(playTone.iconSelfExplanatory, true);
- equal(playTone.icons, 1);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Poll Interval
- */
-add_test(function test_stk_proactive_command_poll_interval() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0D,
- 0x81, 0x03, 0x01, 0x03, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x84, 0x02, 0x01, 0x14
- ],
- typeOfCommand: STK_CMD_POLL_INTERVAL,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let interval = cmdDetails.options;
-
- equal(interval.timeUnit, STK_TIME_UNIT_SECOND);
- equal(interval.timeInterval, 0x14);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command: Display Text
- */
-add_test(function test_stk_proactive_command_display_text() {
- test_stk_proactive_command({
- pdu: [
- 0xd0,
- 0x2c,
- 0x81, 0x03, 0x01, 0x21, 0x80,
- 0x82, 0x02, 0x81, 0x02,
- 0x0d, 0x1d, 0x00, 0xd3, 0x30, 0x9b, 0xfc, 0x06, 0xc9, 0x5c, 0x30, 0x1a,
- 0xa8, 0xe8, 0x02, 0x59, 0xc3, 0xec, 0x34, 0xb9, 0xac, 0x07, 0xc9, 0x60,
- 0x2f, 0x58, 0xed, 0x15, 0x9b, 0xb9, 0x40,
- 0x9e, 0x02, 0x00, 0x01
- ],
- typeOfCommand: STK_CMD_DISPLAY_TEXT,
- icons: [1],
- testFunc: (context, cmdDetails, ctlvs) => {
- let textMsg = cmdDetails.options;
-
- equal(textMsg.text, "Saldo 2.04 E. Validez 20/05/13. ");
- equal(textMsg.iconSelfExplanatory, true);
- equal(textMsg.icons, 1);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command: Set Up Event List.
- */
-add_test(function test_stk_proactive_command_event_list() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0F,
- 0x81, 0x03, 0x01, 0x05, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x99, 0x04, 0x00, 0x01, 0x02, 0x03
- ],
- typeOfCommand: STK_CMD_SET_UP_EVENT_LIST,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let event = cmdDetails.options;
-
- equal(Array.isArray(event.eventList), true);
-
- for (let i = 0; i < event.eventList.length; i++) {
- equal(event.eventList[i], i);
- }
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Get Input
- */
-add_test(function test_stk_proactive_command_get_input() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x22,
- 0x81, 0x03, 0x01, 0x23, 0x8F,
- 0x82, 0x02, 0x81, 0x82,
- 0x8D, 0x05, 0x04, 0x54, 0x65, 0x78, 0x74,
- 0x91, 0x02, 0x01, 0x10,
- 0x17, 0x08, 0x04, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74,
- 0x9E, 0x02, 0x00, 0x01
- ],
- typeOfCommand: STK_CMD_GET_INPUT,
- icons: [1],
- testFunc: (context, cmdDetails, ctlvs) => {
- let input = cmdDetails.options;
-
- equal(input.text, "Text");
- equal(input.isAlphabet, true);
- equal(input.isUCS2, true);
- equal(input.hideInput, true);
- equal(input.isPacked, true);
- equal(input.isHelpAvailable, true);
- equal(input.minLength, 0x01);
- equal(input.maxLength, 0x10);
- equal(input.defaultText, "Default");
- equal(input.iconSelfExplanatory, true);
- equal(input.icons, 1);
- }
- });
-
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x11,
- 0x81, 0x03, 0x01, 0x23, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x8D, 0x00,
- 0x91, 0x02, 0x01, 0x10,
- 0x17, 0x00
- ],
- typeOfCommand: STK_CMD_GET_INPUT,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let input = cmdDetails.options;
-
- equal(input.text, null);
- equal(input.minLength, 0x01);
- equal(input.maxLength, 0x10);
- equal(input.defaultText, null);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : More Time
- */
-add_test(function test_stk_proactive_command_more_time() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
-
- let more_time_1 = [
- 0xD0,
- 0x09,
- 0x81, 0x03, 0x01, 0x02, 0x00,
- 0x82, 0x02, 0x81, 0x82];
-
- for(let i = 0 ; i < more_time_1.length; i++) {
- pduHelper.writeHexOctet(more_time_1[i]);
- }
-
- let berTlv = berHelper.decode(more_time_1.length);
- let ctlvs = berTlv.value;
- let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
- equal(tlv.value.commandNumber, 0x01);
- equal(tlv.value.typeOfCommand, STK_CMD_MORE_TIME);
- equal(tlv.value.commandQualifier, 0x00);
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Select Item
- */
-add_test(function test_stk_proactive_command_select_item() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x3D,
- 0x81, 0x03, 0x01, 0x24, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
- 0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
- 0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
- 0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x10, 0x15, 0x20,
- 0x90, 0x01, 0x01,
- 0x9E, 0x02, 0x00, 0x01,
- 0x9F, 0x04, 0x00, 0x01, 0x02, 0x03
- ],
- typeOfCommand: STK_CMD_SELECT_ITEM,
- icons: [1, 1, 2, 3],
- testFunc: (context, cmdDetails, ctlvs) => {
- let menu = cmdDetails.options;
-
- equal(menu.title, "Title");
- equal(menu.iconSelfExplanatory, true);
- equal(menu.icons, 1);
- equal(menu.items[0].identifier, 1);
- equal(menu.items[0].text, "item 1");
- equal(menu.items[0].iconSelfExplanatory, true);
- equal(menu.items[0].icons, 1);
- equal(menu.items[1].identifier, 2);
- equal(menu.items[1].text, "item 2");
- equal(menu.items[1].iconSelfExplanatory, true);
- equal(menu.items[1].icons, 2);
- equal(menu.items[2].identifier, 3);
- equal(menu.items[2].text, "item 3");
- equal(menu.items[2].iconSelfExplanatory, true);
- equal(menu.items[2].icons, 3);
- equal(menu.nextActionList[0], STK_CMD_SET_UP_CALL);
- equal(menu.nextActionList[1], STK_CMD_LAUNCH_BROWSER);
- equal(menu.nextActionList[2], STK_CMD_PLAY_TONE);
- equal(menu.defaultItem, 0x00);
- }
- });
-
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x33,
- 0x81, 0x03, 0x01, 0x24, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
- 0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
- 0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
- 0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x00, 0x15, 0x81,
- 0x90, 0x01, 0x03
- ],
- typeOfCommand: STK_CMD_SELECT_ITEM,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let menu = cmdDetails.options;
-
- equal(menu.title, "Title");
- equal(menu.items[0].identifier, 1);
- equal(menu.items[0].text, "item 1");
- equal(menu.items[1].identifier, 2);
- equal(menu.items[1].text, "item 2");
- equal(menu.items[2].identifier, 3);
- equal(menu.items[2].text, "item 3");
- equal(menu.nextActionList[0], STK_NEXT_ACTION_NULL);
- equal(menu.nextActionList[1], STK_CMD_LAUNCH_BROWSER);
- equal(menu.nextActionList[2], STK_NEXT_ACTION_END_PROACTIVE_SESSION);
- equal(menu.defaultItem, 0x02);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Set Up Menu
- */
-add_test(function test_stk_proactive_command_set_up_menu() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x3A,
- 0x81, 0x03, 0x01, 0x25, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
- 0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
- 0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
- 0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x10, 0x15, 0x20,
- 0x9E, 0x02, 0x00, 0x01,
- 0x9F, 0x04, 0x00, 0x01, 0x02, 0x03
- ],
- typeOfCommand: STK_CMD_SET_UP_MENU,
- icons: [1, 1, 2, 3],
- testFunc: (context, cmdDetails, ctlvs) => {
- let menu = cmdDetails.options;
-
- equal(menu.title, "Title");
- equal(menu.iconSelfExplanatory, true);
- equal(menu.icons, 1);
- equal(menu.items[0].identifier, 1);
- equal(menu.items[0].text, "item 1");
- equal(menu.items[0].iconSelfExplanatory, true);
- equal(menu.items[0].icons, 1);
- equal(menu.items[1].identifier, 2);
- equal(menu.items[1].text, "item 2");
- equal(menu.items[1].iconSelfExplanatory, true);
- equal(menu.items[1].icons, 2);
- equal(menu.items[2].identifier, 3);
- equal(menu.items[2].text, "item 3");
- equal(menu.items[2].iconSelfExplanatory, true);
- equal(menu.items[2].icons, 3);
- equal(menu.nextActionList[0], STK_CMD_SET_UP_CALL);
- equal(menu.nextActionList[1], STK_CMD_LAUNCH_BROWSER);
- equal(menu.nextActionList[2], STK_CMD_PLAY_TONE);
- }
- });
-
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x30,
- 0x81, 0x03, 0x01, 0x25, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
- 0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
- 0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
- 0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x81, 0x00, 0x00
- ],
- typeOfCommand: STK_CMD_SET_UP_MENU,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let menu = cmdDetails.options;
-
- equal(menu.title, "Title");
- equal(menu.items[0].identifier, 1);
- equal(menu.items[0].text, "item 1");
- equal(menu.items[1].identifier, 2);
- equal(menu.items[1].text, "item 2");
- equal(menu.items[2].identifier, 3);
- equal(menu.items[2].text, "item 3");
- equal(menu.nextActionList[0], STK_NEXT_ACTION_END_PROACTIVE_SESSION);
- equal(menu.nextActionList[1], STK_NEXT_ACTION_NULL);
- equal(menu.nextActionList[2], STK_NEXT_ACTION_NULL);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Set Up Call
- */
-add_test(function test_stk_proactive_command_set_up_call() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x31,
- 0x81, 0x03, 0x01, 0x10, 0x04,
- 0x82, 0x02, 0x81, 0x82,
- 0x05, 0x0A, 0x44, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74,
- 0x86, 0x09, 0x81, 0x10, 0x32, 0x04, 0x21, 0x43, 0x65, 0x1C, 0x2C,
- 0x05, 0x07, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
- 0x9E, 0x02, 0x00, 0x01,
- 0x9E, 0x02, 0x01, 0x02
- ],
- typeOfCommand: STK_CMD_SET_UP_CALL,
- icons: [1, 2],
- testFunc: (context, cmdDetails, ctlvs) => {
- let setupCall = cmdDetails.options;
-
- equal(setupCall.address, "012340123456,1,2");
- equal(setupCall.confirmMessage.text, "Disconnect");
- equal(setupCall.confirmMessage.iconSelfExplanatory, true);
- equal(setupCall.confirmMessage.icons, 1);
- equal(setupCall.callMessage.text, "Message");
- equal(setupCall.callMessage.iconSelfExplanatory, false);
- equal(setupCall.callMessage.icons, 2);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Timer Management
- */
-add_test(function test_stk_proactive_command_timer_management() {
- // Timer Management - Start
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x11,
- 0x81, 0x03, 0x01, 0x27, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0xA4, 0x01, 0x01,
- 0xA5, 0x03, 0x10, 0x20, 0x30
- ],
- typeOfCommand: STK_CMD_TIMER_MANAGEMENT,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- equal(cmdDetails.commandQualifier, STK_TIMER_START);
-
- let timer = cmdDetails.options;
-
- equal(timer.timerId, 0x01);
- equal(timer.timerValue, (0x01 * 60 * 60) + (0x02 * 60) + 0x03);
- }
- });
-
- // Timer Management - Deactivate
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0C,
- 0x81, 0x03, 0x01, 0x27, 0x01,
- 0x82, 0x02, 0x81, 0x82,
- 0xA4, 0x01, 0x01
- ],
- typeOfCommand: STK_CMD_TIMER_MANAGEMENT,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- equal(cmdDetails.commandQualifier, STK_TIMER_DEACTIVATE);
-
- let timer = cmdDetails.options;
-
- equal(timer.timerId, 0x01);
- ok(timer.timerValue === undefined);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Provide Local Information
- */
-add_test(function test_stk_proactive_command_provide_local_information() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
- let stkCmdHelper = context.StkCommandParamsFactory;
-
- // Verify IMEI
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x09,
- 0x81, 0x03, 0x01, 0x26, 0x01,
- 0x82, 0x02, 0x81, 0x82
- ],
- typeOfCommand: STK_CMD_PROVIDE_LOCAL_INFO,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- equal(cmdDetails.commandQualifier, STK_LOCAL_INFO_IMEI);
-
- let provideLocalInfo = cmdDetails.options;
- equal(provideLocalInfo.localInfoType, STK_LOCAL_INFO_IMEI);
- }
- });
-
- // Verify Date and Time Zone
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x09,
- 0x81, 0x03, 0x01, 0x26, 0x03,
- 0x82, 0x02, 0x81, 0x82
- ],
- typeOfCommand: STK_CMD_PROVIDE_LOCAL_INFO,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- equal(cmdDetails.commandQualifier, STK_LOCAL_INFO_DATE_TIME_ZONE);
-
- let provideLocalInfo = cmdDetails.options;
- equal(provideLocalInfo.localInfoType, STK_LOCAL_INFO_DATE_TIME_ZONE);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive command : BIP Messages
- */
-add_test(function test_stk_proactive_command_open_channel() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
- let stkCmdHelper = context.StkCommandParamsFactory;
-
- // Open Channel
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0F,
- 0x81, 0x03, 0x01, 0x40, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x04, 0x4F, 0x70, 0x65, 0x6E //alpha id: "Open"
- ],
- typeOfCommand: STK_CMD_OPEN_CHANNEL,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let bipMsg = cmdDetails.options;
-
- equal(bipMsg.text, "Open");
- }
- });
-
- // Close Channel
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x10,
- 0x81, 0x03, 0x01, 0x41, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x43, 0x6C, 0x6F, 0x73, 0x65 //alpha id: "Close"
- ],
- typeOfCommand: STK_CMD_CLOSE_CHANNEL,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let bipMsg = cmdDetails.options;
-
- equal(bipMsg.text, "Close");
- }
- });
-
- // Receive Data
- test_stk_proactive_command({
- pdu: [
- 0XD0,
- 0X12,
- 0x81, 0x03, 0x01, 0x42, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x07, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65 //alpha id: "Receive"
- ],
- typeOfCommand: STK_CMD_RECEIVE_DATA,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let bipMsg = cmdDetails.options;
-
- equal(bipMsg.text, "Receive");
- }
- });
-
- // Send Data
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0F,
- 0x81, 0x03, 0x01, 0x43, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x04, 0x53, 0x65, 0x6E, 0x64 //alpha id: "Send"
- ],
- typeOfCommand: STK_CMD_SEND_DATA,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let bipMsg = cmdDetails.options;
-
- equal(bipMsg.text, "Send");
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Event Download Command : Location Status
- */
-add_test(function test_stk_event_download_location_status() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 42 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) +
- // TLV_EVENT_LIST_SIZE(3) +
- // TLV_LOCATION_STATUS_SIZE(3) +
- // TLV_LOCATION_INFO_GSM_SIZE(9))
- equal(this.readInt32(), 42);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 19 = TLV_DEVICE_ID_SIZE(4) +
- // TLV_EVENT_LIST_SIZE(3) +
- // TLV_LOCATION_STATUS_SIZE(3) +
- // TLV_LOCATION_INFO_GSM_SIZE(9)
- equal(pduHelper.readHexOctet(), 19);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_LOCATION_STATUS);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Location Status, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_LOCATION_STATUS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_SERVICE_STATE_NORMAL);
-
- // Location Info, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 7);
-
- equal(pduHelper.readHexOctet(), 0x21); // MCC + MNC
- equal(pduHelper.readHexOctet(), 0x63);
- equal(pduHelper.readHexOctet(), 0x54);
- equal(pduHelper.readHexOctet(), 0); // LAC
- equal(pduHelper.readHexOctet(), 0);
- equal(pduHelper.readHexOctet(), 0); // Cell ID
- equal(pduHelper.readHexOctet(), 0);
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_LOCATION_STATUS,
- locationStatus: STK_SERVICE_STATE_NORMAL,
- locationInfo: {
- mcc: "123",
- mnc: "456",
- gsmLocationAreaCode: 0,
- gsmCellId: 0
- }
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
-
-// Test Event Download commands.
-
-/**
- * Verify Event Download Command : Language Selection
- */
-add_test(function test_stk_event_download_language_selection() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 26 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) +
- // TLV_EVENT_LIST_SIZE(3) +
- // TLV_LANGUAGE(4))
- equal(this.readInt32(), 26);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 19 = TLV_DEVICE_ID_SIZE(4) +
- // TLV_EVENT_LIST_SIZE(3) +
- // TLV_LANGUAGE(4)
- equal(pduHelper.readHexOctet(), 11);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_LANGUAGE_SELECTION);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Language, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_LANGUAGE);
- equal(pduHelper.readHexOctet(), 2);
- equal(iccHelper.read8BitUnpackedToString(2), "zh");
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_LANGUAGE_SELECTION,
- language: "zh"
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
-
-/**
- * Verify Event Download Command : User Activity
- */
-add_test(function test_stk_event_download_user_activity() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 18 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3))
- equal(this.readInt32(), 18);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 7 = TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3)
- equal(pduHelper.readHexOctet(), 7);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_USER_ACTIVITY);
-
- // Device Identities, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_USER_ACTIVITY
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
-
-/**
- * Verify Event Download Command : Idle Screen Available
- */
-add_test(function test_stk_event_download_idle_screen_available() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 18 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3))
- equal(this.readInt32(), 18);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 7 = TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3)
- equal(pduHelper.readHexOctet(), 7);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE);
-
- // Device Identities, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_DISPLAY);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
-
-/**
- * Verify Event Downloaded Command :Browser Termination
- */
-add_test(function test_stk_event_download_browser_termination() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 24 = 2 * ( 2+TLV_DEVICE_ID(4)+TLV_EVENT_LIST_SIZE(3)
- // +TLV_BROWSER_TERMINATION_CAUSE(3) )
- equal(this.readInt32(), 24);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 10 = TLV_DEVICE_ID(4)+TLV_EVENT_LIST_SIZE(3)
- // ++TLV_BROWSER_TERMINATION_CAUSE(3)
- equal(pduHelper.readHexOctet(), 10);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_BROWSER_TERMINATION);
-
- // Device Identities, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Browser Termination Case, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_BROWSER_TERMINATION_CAUSE |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_BROWSER_TERMINATION_CAUSE_USER);
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_BROWSER_TERMINATION,
- terminationCause: STK_BROWSER_TERMINATION_CAUSE_USER
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_voiceprivacy.js b/dom/system/gonk/tests/test_ril_worker_voiceprivacy.js
deleted file mode 100644
index 21829da22..000000000
--- a/dom/system/gonk/tests/test_ril_worker_voiceprivacy.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_setVoicePrivacyMode_success() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setVoicePrivacyMode = function fakeSetVoicePrivacyMode(options) {
- context.RIL[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE](0, {});
- };
-
- context.RIL.setVoicePrivacyMode({
- enabled: true
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
-
- run_next_test();
-});
-
-add_test(function test_setVoicePrivacyMode_generic_failure() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setVoicePrivacyMode = function fakeSetVoicePrivacyMode(options) {
- context.RIL[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE](0, {
- errorMsg: GECKO_ERROR_GENERIC_FAILURE
- });
- };
-
- context.RIL.setVoicePrivacyMode({
- enabled: true
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
-
- run_next_test();
-});
-
-add_test(function test_queryVoicePrivacyMode_success_enabled_true() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32List = function fakeReadUint32List() {
- return [1];
- };
-
- context.RIL.queryVoicePrivacyMode = function fakeQueryVoicePrivacyMode(options) {
- context.RIL[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE](1, {});
- };
-
- context.RIL.queryVoicePrivacyMode();
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- ok(postedMessage.enabled);
- run_next_test();
-});
-
-add_test(function test_queryVoicePrivacyMode_success_enabled_false() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32List = function fakeReadUint32List() {
- return [0];
- };
-
- context.RIL.queryVoicePrivacyMode = function fakeQueryVoicePrivacyMode(options) {
- context.RIL[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE](1, {});
- };
-
- context.RIL.queryVoicePrivacyMode();
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- ok(!postedMessage.enabled);
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/xpcshell.ini b/dom/system/gonk/tests/xpcshell.ini
deleted file mode 100644
index 1e8b798a3..000000000
--- a/dom/system/gonk/tests/xpcshell.ini
+++ /dev/null
@@ -1,43 +0,0 @@
-[DEFAULT]
-head = header_helpers.js
-tail =
-
-[test_ril_worker_buf.js]
-[test_ril_worker_icc_CardLock.js]
-[test_ril_worker_icc_CardState.js]
-[test_ril_worker_icc_BerTlvHelper.js]
-[test_ril_worker_icc_GsmPDUHelper.js]
-[test_ril_worker_icc_ICCContactHelper.js]
-[test_ril_worker_icc_ICCIOHelper.js]
-[test_ril_worker_icc_ICCPDUHelper.js]
-[test_ril_worker_icc_ICCRecordHelper.js]
-[test_ril_worker_icc_IconLoader.js]
-[test_ril_worker_icc_ICCUtilsHelper.js]
-[test_ril_worker_icc_SimRecordHelper.js]
-[test_ril_worker_sms.js]
-# Bug 916067 - B2G RIL: test_ril_worker_sms.js takes too long to finish
-skip-if = true
-[test_ril_worker_sms_cdma.js]
-[test_ril_worker_sms_cdmapduhelper.js]
-[test_ril_worker_sms_nl_tables.js]
-[test_ril_worker_sms_gsmpduhelper.js]
-[test_ril_worker_sms_segment_info.js]
-[test_ril_worker_smsc_address.js]
-[test_ril_worker_cf.js]
-[test_ril_worker_cellbroadcast_config.js]
-[test_ril_worker_cellbroadcast_gsm.js]
-[test_ril_worker_cellbroadcast_umts.js]
-[test_ril_worker_ruim.js]
-[test_ril_worker_cw.js]
-[test_ril_worker_clir.js]
-[test_ril_worker_clip.js]
-[test_ril_worker_ssn.js]
-[test_ril_worker_voiceprivacy.js]
-[test_ril_worker_ecm.js]
-[test_ril_worker_stk.js]
-requesttimeoutfactor = 4
-[test_ril_worker_barring_password.js]
-[test_ril_worker_cdma_info_rec.js]
-[test_ril_system_messenger.js]
-# header_helpers.js is not needed for test_ril_system_messenger.js
-head =
diff --git a/dom/system/gonk/worker_buf.js b/dom/system/gonk/worker_buf.js
deleted file mode 100644
index 7064eeac5..000000000
--- a/dom/system/gonk/worker_buf.js
+++ /dev/null
@@ -1,623 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-/**
- * This object contains helpers buffering incoming data & deconstructing it
- * into parcels as well as buffering outgoing data & constructing parcels.
- * For that it maintains two buffers and corresponding uint8 views, indexes.
- *
- * The incoming buffer is a circular buffer where we store incoming data.
- * As soon as a complete parcel is received, it is processed right away, so
- * the buffer only needs to be large enough to hold one parcel.
- *
- * The outgoing buffer is to prepare outgoing parcels. The index is reset
- * every time a parcel is sent.
- */
-
-var Buf = {
- INT32_MAX: 2147483647,
- UINT8_SIZE: 1,
- UINT16_SIZE: 2,
- UINT32_SIZE: 4,
- PARCEL_SIZE_SIZE: 4,
- PDU_HEX_OCTET_SIZE: 4,
-
- incomingBufferLength: 1024,
- incomingBuffer: null,
- incomingBytes: null,
- incomingWriteIndex: 0,
- incomingReadIndex: 0,
- readIncoming: 0,
- readAvailable: 0,
- currentParcelSize: 0,
-
- outgoingBufferLength: 1024,
- outgoingBuffer: null,
- outgoingBytes: null,
- outgoingIndex: 0,
- outgoingBufferCalSizeQueue: null,
-
- _init: function() {
- this.incomingBuffer = new ArrayBuffer(this.incomingBufferLength);
- this.outgoingBuffer = new ArrayBuffer(this.outgoingBufferLength);
-
- this.incomingBytes = new Uint8Array(this.incomingBuffer);
- this.outgoingBytes = new Uint8Array(this.outgoingBuffer);
-
- // Track where incoming data is read from and written to.
- this.incomingWriteIndex = 0;
- this.incomingReadIndex = 0;
-
- // Leave room for the parcel size for outgoing parcels.
- this.outgoingIndex = this.PARCEL_SIZE_SIZE;
-
- // How many bytes we've read for this parcel so far.
- this.readIncoming = 0;
-
- // How many bytes available as parcel data.
- this.readAvailable = 0;
-
- // Size of the incoming parcel. If this is zero, we're expecting a new
- // parcel.
- this.currentParcelSize = 0;
-
- // Queue for storing outgoing override points
- this.outgoingBufferCalSizeQueue = [];
- },
-
- /**
- * Mark current outgoingIndex as start point for calculation length of data
- * written to outgoingBuffer.
- * Mark can be nested for here uses queue to remember marks.
- *
- * @param writeFunction
- * Function to write data length into outgoingBuffer, this function is
- * also used to allocate buffer for data length.
- * Raw data size(in Uint8) is provided as parameter calling writeFunction.
- * If raw data size is not in proper unit for writing, user can adjust
- * the length value in writeFunction before writing.
- **/
- startCalOutgoingSize: function(writeFunction) {
- let sizeInfo = {index: this.outgoingIndex,
- write: writeFunction};
-
- // Allocate buffer for data lemgtj.
- writeFunction.call(0);
-
- // Get size of data length buffer for it is not counted into data size.
- sizeInfo.size = this.outgoingIndex - sizeInfo.index;
-
- // Enqueue size calculation information.
- this.outgoingBufferCalSizeQueue.push(sizeInfo);
- },
-
- /**
- * Calculate data length since last mark, and write it into mark position.
- **/
- stopCalOutgoingSize: function() {
- let sizeInfo = this.outgoingBufferCalSizeQueue.pop();
-
- // Remember current outgoingIndex.
- let currentOutgoingIndex = this.outgoingIndex;
- // Calculate data length, in uint8.
- let writeSize = this.outgoingIndex - sizeInfo.index - sizeInfo.size;
-
- // Write data length to mark, use same function for allocating buffer to make
- // sure there is no buffer overloading.
- this.outgoingIndex = sizeInfo.index;
- sizeInfo.write(writeSize);
-
- // Restore outgoingIndex.
- this.outgoingIndex = currentOutgoingIndex;
- },
-
- /**
- * Grow the incoming buffer.
- *
- * @param min_size
- * Minimum new size. The actual new size will be the the smallest
- * power of 2 that's larger than this number.
- */
- growIncomingBuffer: function(min_size) {
- if (DEBUG) {
- debug("Current buffer of " + this.incomingBufferLength +
- " can't handle incoming " + min_size + " bytes.");
- }
- let oldBytes = this.incomingBytes;
- this.incomingBufferLength =
- 2 << Math.floor(Math.log(min_size)/Math.log(2));
- if (DEBUG) debug("New incoming buffer size: " + this.incomingBufferLength);
- this.incomingBuffer = new ArrayBuffer(this.incomingBufferLength);
- this.incomingBytes = new Uint8Array(this.incomingBuffer);
- if (this.incomingReadIndex <= this.incomingWriteIndex) {
- // Read and write index are in natural order, so we can just copy
- // the old buffer over to the bigger one without having to worry
- // about the indexes.
- this.incomingBytes.set(oldBytes, 0);
- } else {
- // The write index has wrapped around but the read index hasn't yet.
- // Write whatever the read index has left to read until it would
- // circle around to the beginning of the new buffer, and the rest
- // behind that.
- let head = oldBytes.subarray(this.incomingReadIndex);
- let tail = oldBytes.subarray(0, this.incomingReadIndex);
- this.incomingBytes.set(head, 0);
- this.incomingBytes.set(tail, head.length);
- this.incomingReadIndex = 0;
- this.incomingWriteIndex += head.length;
- }
- if (DEBUG) {
- debug("New incoming buffer size is " + this.incomingBufferLength);
- }
- },
-
- /**
- * Grow the outgoing buffer.
- *
- * @param min_size
- * Minimum new size. The actual new size will be the the smallest
- * power of 2 that's larger than this number.
- */
- growOutgoingBuffer: function(min_size) {
- if (DEBUG) {
- debug("Current buffer of " + this.outgoingBufferLength +
- " is too small.");
- }
- let oldBytes = this.outgoingBytes;
- this.outgoingBufferLength =
- 2 << Math.floor(Math.log(min_size)/Math.log(2));
- this.outgoingBuffer = new ArrayBuffer(this.outgoingBufferLength);
- this.outgoingBytes = new Uint8Array(this.outgoingBuffer);
- this.outgoingBytes.set(oldBytes, 0);
- if (DEBUG) {
- debug("New outgoing buffer size is " + this.outgoingBufferLength);
- }
- },
-
- /**
- * Functions for reading data from the incoming buffer.
- *
- * These are all little endian, apart from readParcelSize();
- */
-
- /**
- * Ensure position specified is readable.
- *
- * @param index
- * Data position in incoming parcel, valid from 0 to
- * currentParcelSize.
- */
- ensureIncomingAvailable: function(index) {
- if (index >= this.currentParcelSize) {
- throw new Error("Trying to read data beyond the parcel end!");
- } else if (index < 0) {
- throw new Error("Trying to read data before the parcel begin!");
- }
- },
-
- /**
- * Seek in current incoming parcel.
- *
- * @param offset
- * Seek offset in relative to current position.
- */
- seekIncoming: function(offset) {
- // Translate to 0..currentParcelSize
- let cur = this.currentParcelSize - this.readAvailable;
-
- let newIndex = cur + offset;
- this.ensureIncomingAvailable(newIndex);
-
- // ... incomingReadIndex -->|
- // 0 new cur currentParcelSize
- // |================|=======|====================|
- // |<-- cur -->|<- readAvailable ->|
- // |<-- newIndex -->|<-- new readAvailable -->|
- this.readAvailable = this.currentParcelSize - newIndex;
-
- // Translate back:
- if (this.incomingReadIndex < cur) {
- // The incomingReadIndex is wrapped.
- newIndex += this.incomingBufferLength;
- }
- newIndex += (this.incomingReadIndex - cur);
- newIndex %= this.incomingBufferLength;
- this.incomingReadIndex = newIndex;
- },
-
- readUint8Unchecked: function() {
- let value = this.incomingBytes[this.incomingReadIndex];
- this.incomingReadIndex = (this.incomingReadIndex + 1) %
- this.incomingBufferLength;
- return value;
- },
-
- readUint8: function() {
- // Translate to 0..currentParcelSize
- let cur = this.currentParcelSize - this.readAvailable;
- this.ensureIncomingAvailable(cur);
-
- this.readAvailable--;
- return this.readUint8Unchecked();
- },
-
- readUint8Array: function(length) {
- // Translate to 0..currentParcelSize
- let last = this.currentParcelSize - this.readAvailable;
- last += (length - 1);
- this.ensureIncomingAvailable(last);
-
- let array = new Uint8Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = this.readUint8Unchecked();
- }
-
- this.readAvailable -= length;
- return array;
- },
-
- readUint16: function() {
- return this.readUint8() | this.readUint8() << 8;
- },
-
- readInt32: function() {
- return this.readUint8() | this.readUint8() << 8 |
- this.readUint8() << 16 | this.readUint8() << 24;
- },
-
- readInt64: function() {
- // Avoid using bitwise operators as the operands of all bitwise operators
- // are converted to signed 32-bit integers.
- return this.readUint8() +
- this.readUint8() * Math.pow(2, 8) +
- this.readUint8() * Math.pow(2, 16) +
- this.readUint8() * Math.pow(2, 24) +
- this.readUint8() * Math.pow(2, 32) +
- this.readUint8() * Math.pow(2, 40) +
- this.readUint8() * Math.pow(2, 48) +
- this.readUint8() * Math.pow(2, 56);
- },
-
- readInt32List: function() {
- let length = this.readInt32();
- let ints = [];
- for (let i = 0; i < length; i++) {
- ints.push(this.readInt32());
- }
- return ints;
- },
-
- readString: function() {
- let string_len = this.readInt32();
- if (string_len < 0 || string_len >= this.INT32_MAX) {
- return null;
- }
- let s = "";
- for (let i = 0; i < string_len; i++) {
- s += String.fromCharCode(this.readUint16());
- }
- // Strings are \0\0 delimited, but that isn't part of the length. And
- // if the string length is even, the delimiter is two characters wide.
- // It's insane, I know.
- this.readStringDelimiter(string_len);
- return s;
- },
-
- readStringList: function() {
- let num_strings = this.readInt32();
- let strings = [];
- for (let i = 0; i < num_strings; i++) {
- strings.push(this.readString());
- }
- return strings;
- },
-
- readStringDelimiter: function(length) {
- let delimiter = this.readUint16();
- if (!(length & 1)) {
- delimiter |= this.readUint16();
- }
- if (DEBUG) {
- if (delimiter !== 0) {
- debug("Something's wrong, found string delimiter: " + delimiter);
- }
- }
- },
-
- readParcelSize: function() {
- return this.readUint8Unchecked() << 24 |
- this.readUint8Unchecked() << 16 |
- this.readUint8Unchecked() << 8 |
- this.readUint8Unchecked();
- },
-
- /**
- * Functions for writing data to the outgoing buffer.
- */
-
- /**
- * Ensure position specified is writable.
- *
- * @param index
- * Data position in outgoing parcel, valid from 0 to
- * outgoingBufferLength.
- */
- ensureOutgoingAvailable: function(index) {
- if (index >= this.outgoingBufferLength) {
- this.growOutgoingBuffer(index + 1);
- }
- },
-
- writeUint8: function(value) {
- this.ensureOutgoingAvailable(this.outgoingIndex);
-
- this.outgoingBytes[this.outgoingIndex] = value;
- this.outgoingIndex++;
- },
-
- writeUint16: function(value) {
- this.writeUint8(value & 0xff);
- this.writeUint8((value >> 8) & 0xff);
- },
-
- writeInt32: function(value) {
- this.writeUint8(value & 0xff);
- this.writeUint8((value >> 8) & 0xff);
- this.writeUint8((value >> 16) & 0xff);
- this.writeUint8((value >> 24) & 0xff);
- },
-
- writeString: function(value) {
- if (value == null) {
- this.writeInt32(-1);
- return;
- }
- this.writeInt32(value.length);
- for (let i = 0; i < value.length; i++) {
- this.writeUint16(value.charCodeAt(i));
- }
- // Strings are \0\0 delimited, but that isn't part of the length. And
- // if the string length is even, the delimiter is two characters wide.
- // It's insane, I know.
- this.writeStringDelimiter(value.length);
- },
-
- writeStringList: function(strings) {
- this.writeInt32(strings.length);
- for (let i = 0; i < strings.length; i++) {
- this.writeString(strings[i]);
- }
- },
-
- writeStringDelimiter: function(length) {
- this.writeUint16(0);
- if (!(length & 1)) {
- this.writeUint16(0);
- }
- },
-
- writeParcelSize: function(value) {
- /**
- * Parcel size will always be the first thing in the parcel byte
- * array, but the last thing written. Store the current index off
- * to a temporary to be reset after we write the size.
- */
- let currentIndex = this.outgoingIndex;
- this.outgoingIndex = 0;
- this.writeUint8((value >> 24) & 0xff);
- this.writeUint8((value >> 16) & 0xff);
- this.writeUint8((value >> 8) & 0xff);
- this.writeUint8(value & 0xff);
- this.outgoingIndex = currentIndex;
- },
-
- copyIncomingToOutgoing: function(length) {
- if (!length || (length < 0)) {
- return;
- }
-
- let translatedReadIndexEnd =
- this.currentParcelSize - this.readAvailable + length - 1;
- this.ensureIncomingAvailable(translatedReadIndexEnd);
-
- let translatedWriteIndexEnd = this.outgoingIndex + length - 1;
- this.ensureOutgoingAvailable(translatedWriteIndexEnd);
-
- let newIncomingReadIndex = this.incomingReadIndex + length;
- if (newIncomingReadIndex < this.incomingBufferLength) {
- // Reading won't cause wrapping, go ahead with builtin copy.
- this.outgoingBytes
- .set(this.incomingBytes.subarray(this.incomingReadIndex,
- newIncomingReadIndex),
- this.outgoingIndex);
- } else {
- // Not so lucky.
- newIncomingReadIndex %= this.incomingBufferLength;
- this.outgoingBytes
- .set(this.incomingBytes.subarray(this.incomingReadIndex,
- this.incomingBufferLength),
- this.outgoingIndex);
- if (newIncomingReadIndex) {
- let firstPartLength = this.incomingBufferLength - this.incomingReadIndex;
- this.outgoingBytes.set(this.incomingBytes.subarray(0, newIncomingReadIndex),
- this.outgoingIndex + firstPartLength);
- }
- }
-
- this.incomingReadIndex = newIncomingReadIndex;
- this.readAvailable -= length;
- this.outgoingIndex += length;
- },
-
- /**
- * Parcel management
- */
-
- /**
- * Write incoming data to the circular buffer.
- *
- * @param incoming
- * Uint8Array containing the incoming data.
- */
- writeToIncoming: function(incoming) {
- // We don't have to worry about the head catching the tail since
- // we process any backlog in parcels immediately, before writing
- // new data to the buffer. So the only edge case we need to handle
- // is when the incoming data is larger than the buffer size.
- let minMustAvailableSize = incoming.length + this.readIncoming;
- if (minMustAvailableSize > this.incomingBufferLength) {
- this.growIncomingBuffer(minMustAvailableSize);
- }
-
- // We can let the typed arrays do the copying if the incoming data won't
- // wrap around the edges of the circular buffer.
- let remaining = this.incomingBufferLength - this.incomingWriteIndex;
- if (remaining >= incoming.length) {
- this.incomingBytes.set(incoming, this.incomingWriteIndex);
- } else {
- // The incoming data would wrap around it.
- let head = incoming.subarray(0, remaining);
- let tail = incoming.subarray(remaining);
- this.incomingBytes.set(head, this.incomingWriteIndex);
- this.incomingBytes.set(tail, 0);
- }
- this.incomingWriteIndex = (this.incomingWriteIndex + incoming.length) %
- this.incomingBufferLength;
- },
-
- /**
- * Process incoming data.
- *
- * @param incoming
- * Uint8Array containing the incoming data.
- */
- processIncoming: function(incoming) {
- if (DEBUG) {
- debug("Received " + incoming.length + " bytes.");
- debug("Already read " + this.readIncoming);
- }
-
- this.writeToIncoming(incoming);
- this.readIncoming += incoming.length;
- while (true) {
- if (!this.currentParcelSize) {
- // We're expecting a new parcel.
- if (this.readIncoming < this.PARCEL_SIZE_SIZE) {
- // We don't know how big the next parcel is going to be, need more
- // data.
- if (DEBUG) debug("Next parcel size unknown, going to sleep.");
- return;
- }
- this.currentParcelSize = this.readParcelSize();
- if (DEBUG) {
- debug("New incoming parcel of size " + this.currentParcelSize);
- }
- // The size itself is not included in the size.
- this.readIncoming -= this.PARCEL_SIZE_SIZE;
- }
-
- if (this.readIncoming < this.currentParcelSize) {
- // We haven't read enough yet in order to be able to process a parcel.
- if (DEBUG) debug("Read " + this.readIncoming + ", but parcel size is "
- + this.currentParcelSize + ". Going to sleep.");
- return;
- }
-
- // Alright, we have enough data to process at least one whole parcel.
- // Let's do that.
- let expectedAfterIndex = (this.incomingReadIndex + this.currentParcelSize)
- % this.incomingBufferLength;
-
- if (DEBUG) {
- let parcel;
- if (expectedAfterIndex < this.incomingReadIndex) {
- let head = this.incomingBytes.subarray(this.incomingReadIndex);
- let tail = this.incomingBytes.subarray(0, expectedAfterIndex);
- parcel = Array.slice(head).concat(Array.slice(tail));
- } else {
- parcel = Array.slice(this.incomingBytes.subarray(
- this.incomingReadIndex, expectedAfterIndex));
- }
- debug("Parcel (size " + this.currentParcelSize + "): " + parcel);
- }
-
- if (DEBUG) debug("We have at least one complete parcel.");
- try {
- this.readAvailable = this.currentParcelSize;
- this.processParcel();
- } catch (ex) {
- if (DEBUG) debug("Parcel handling threw " + ex + "\n" + ex.stack);
- }
-
- // Ensure that the whole parcel was consumed.
- if (this.incomingReadIndex != expectedAfterIndex) {
- if (DEBUG) {
- debug("Parcel handler didn't consume whole parcel, " +
- Math.abs(expectedAfterIndex - this.incomingReadIndex) +
- " bytes left over");
- }
- this.incomingReadIndex = expectedAfterIndex;
- }
- this.readIncoming -= this.currentParcelSize;
- this.readAvailable = 0;
- this.currentParcelSize = 0;
- }
- },
-
- /**
- * Communicate with the IPC thread.
- */
- sendParcel: function() {
- // Compute the size of the parcel and write it to the front of the parcel
- // where we left room for it. Note that he parcel size does not include
- // the size itself.
- let parcelSize = this.outgoingIndex - this.PARCEL_SIZE_SIZE;
- this.writeParcelSize(parcelSize);
-
- // This assumes that postRILMessage will make a copy of the ArrayBufferView
- // right away!
- let parcel = this.outgoingBytes.subarray(0, this.outgoingIndex);
- if (DEBUG) debug("Outgoing parcel: " + Array.slice(parcel));
- this.onSendParcel(parcel);
- this.outgoingIndex = this.PARCEL_SIZE_SIZE;
- },
-
- getCurrentParcelSize: function() {
- return this.currentParcelSize;
- },
-
- getReadAvailable: function() {
- return this.readAvailable;
- }
-
- /**
- * Process one parcel.
- *
- * |processParcel| is an implementation provided incoming parcel processing
- * function invoked when we have received a complete parcel. Implementation
- * may call multiple read functions to extract data from the incoming buffer.
- */
- //processParcel: function() {
- // let something = this.readInt32();
- // ...
- //},
-
- /**
- * Write raw data out to underlying channel.
- *
- * |onSendParcel| is an implementation provided stream output function
- * invoked when we're really going to write something out. We assume the
- * data are completely copied to some output buffer in this call and may
- * be destroyed when it's done.
- *
- * @param parcel
- * An array of numeric octet data.
- */
- //onSendParcel: function(parcel) {
- // ...
- //}
-};
-
-module.exports = { Buf: Buf };
diff --git a/dom/system/moz.build b/dom/system/moz.build
index 3cff531b5..fc8cf533b 100644
--- a/dom/system/moz.build
+++ b/dom/system/moz.build
@@ -12,8 +12,6 @@ elif toolkit == 'cocoa':
DIRS += ['mac']
elif toolkit == 'android':
DIRS += ['android']
-elif toolkit == 'gonk':
- DIRS += ['gonk']
elif toolkit in ('gtk2', 'gtk3'):
DIRS += ['linux']
diff --git a/dom/tests/mochitest/bugs/test_resize_move_windows.html b/dom/tests/mochitest/bugs/test_resize_move_windows.html
index 0762e9231..f84b4fde8 100644
--- a/dom/tests/mochitest/bugs/test_resize_move_windows.html
+++ b/dom/tests/mochitest/bugs/test_resize_move_windows.html
@@ -312,7 +312,10 @@ function checkChangeIsEnabled(aWindow, aNext)
.then(aNext);
}
-SpecialPowers.pushPrefEnv({"set": [["dom.disable_window_move_resize", false]]}, function() {
+SpecialPowers.pushPrefEnv({
+ "set": [["dom.disable_window_move_resize", false],
+ ["security.data_uri.block_toplevel_data_uri_navigations", false],]},
+ function() {
SimpleTest.waitForFocus(function() {
if (screen.width <= 200 || screen.height <= 200) {
todo(false, "The screen needs to be bigger than 200px*200px to run this test.");
diff --git a/dom/tests/mochitest/fetch/test_fetch_cors.js b/dom/tests/mochitest/fetch/test_fetch_cors.js
index ac83d050d..f375ce73f 100644
--- a/dom/tests/mochitest/fetch/test_fetch_cors.js
+++ b/dom/tests/mochitest/fetch/test_fetch_cors.js
@@ -64,9 +64,9 @@ function testSameOriginCredentials() {
withCred: "same-origin",
},
{
- // Default mode is "omit".
+ // Default mode is "same-origin".
pass: 1,
- noCookie: 1,
+ cookie: cookieStr,
},
{
pass: 1,
diff --git a/dom/tests/mochitest/fetch/test_headers_common.js b/dom/tests/mochitest/fetch/test_headers_common.js
index fe792b25b..8b17b6b12 100644
--- a/dom/tests/mochitest/fetch/test_headers_common.js
+++ b/dom/tests/mochitest/fetch/test_headers_common.js
@@ -213,12 +213,12 @@ function TestHeadersIterator() {
var value_iter = headers.values();
var entries_iter = headers.entries();
- arrayEquals(iterate(key_iter), ["foo", "foo", "foo2"], "Correct key iterator");
- arrayEquals(iterate(value_iter), ["bar", ehsanInflated, "baz2"], "Correct value iterator");
- arrayEquals(iterate(entries_iter), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+ arrayEquals(iterate(key_iter), ["foo", "foo2"], "Correct key iterator");
+ arrayEquals(iterate(value_iter), ["bar, " + ehsanInflated, "baz2"], "Correct value iterator");
+ arrayEquals(iterate(entries_iter), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
- arrayEquals(iterateForOf(headers), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
- arrayEquals(iterateForOf(new Headers(headers)), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+ arrayEquals(iterateForOf(headers), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+ arrayEquals(iterateForOf(new Headers(headers)), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
}
function runTest() {
diff --git a/dom/tests/mochitest/fetch/test_request.js b/dom/tests/mochitest/fetch/test_request.js
index badad61b9..405767b50 100644
--- a/dom/tests/mochitest/fetch/test_request.js
+++ b/dom/tests/mochitest/fetch/test_request.js
@@ -6,7 +6,7 @@ function testDefaultCtor() {
is(req.context, "fetch", "Default context is fetch.");
is(req.referrer, "about:client", "Default referrer is `client` which serializes to about:client.");
is(req.mode, "cors", "Request mode for string input is cors");
- is(req.credentials, "omit", "Default Request credentials is omit");
+ is(req.credentials, "same-origin", "Default Request credentials is same-origin");
is(req.cache, "default", "Default Request cache is default");
var req = new Request(req);
@@ -16,7 +16,7 @@ function testDefaultCtor() {
is(req.context, "fetch", "Default context is fetch.");
is(req.referrer, "about:client", "Default referrer is `client` which serializes to about:client.");
is(req.mode, "cors", "Request mode string input is cors");
- is(req.credentials, "omit", "Default Request credentials is omit");
+ is(req.credentials, "same-origin", "Default Request credentials is same-origin");
is(req.cache, "default", "Default Request cache is default");
}
@@ -152,12 +152,9 @@ function testHeaderGuard() {
}
function testMode() {
- try {
- var req = new Request("http://example.com", {mode: "navigate"});
- ok(false, "Creating a Request with navigate RequestMode should throw a TypeError");
- } catch(e) {
- is(e.name, "TypeError", "Creating a Request with navigate RequestMode should throw a TypeError");
- }
+ var req = new Request("http://example.com", {mode: "navigate"});
+ ok(true, "Creating a Request with navigate RequestMode should not throw.");
+ is(req.mode, "same-origin", "Request mode becomes same-origin");
}
function testMethod() {
diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html
index acbc12e07..98f3ffed0 100644
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -63,7 +63,7 @@ var ecmaGlobals =
"Int32Array",
"Int8Array",
"InternalError",
- {name: "Intl", android: false},
+ "Intl",
"Iterator",
"JSON",
"Map",
@@ -751,9 +751,11 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceNavigation",
// IMPORTANT: Do not change this list without review from a DOM peer!
- {name: "PerformanceObserver", nightly: true},
+ "PerformanceNavigationTiming",
// IMPORTANT: Do not change this list without review from a DOM peer!
- {name: "PerformanceObserverEntryList", nightly: true},
+ "PerformanceObserver"
+// IMPORTANT: Do not change this list without review from a DOM peer!
+ "PerformanceObserverEntryList"
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceResourceTiming",
// IMPORTANT: Do not change this list without review from a DOM peer!
diff --git a/dom/tethering/TetheringManager.js b/dom/tethering/TetheringManager.js
deleted file mode 100644
index 1e3d3a0ea..000000000
--- a/dom/tethering/TetheringManager.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsIMessageSender");
-
-const DEBUG = false;
-
-const TETHERING_TYPE_WIFI = "wifi";
-const TETHERING_TYPE_BLUETOOTH = "bt";
-const TETHERING_TYPE_USB = "usb";
-
-function TetheringManager() {
-}
-
-TetheringManager.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
-
- classDescription: "TetheringManager",
- classID: Components.ID("{bd8a831c-d8ec-4f00-8803-606e50781097}"),
- contractID: "@mozilla.org/dom/tetheringmanager;1",
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver]),
-
- init: function(aWindow) {
- const messages = ["WifiManager:setWifiTethering:Return:OK",
- "WifiManager:setWifiTethering:Return:NO"];
- this.initDOMRequestHelper(aWindow, messages);
- },
-
- // TODO : aMessage format may be different after supporting bt/usb.
- // for now, use wifi format first.
- receiveMessage: function(aMessage) {
- let data = aMessage.data.data;
-
- let resolver = this.takePromiseResolver(data.resolverId);
- if (!resolver) {
- return;
- }
-
- switch (aMessage.name) {
- case "WifiManager:setWifiTethering:Return:OK":
- resolver.resolve(data);
- break;
- case "WifiManager:setWifiTethering:Return:NO":
- resolver.reject(data.reason);
- break;
- }
- },
-
- setTetheringEnabled: function setTetheringEnabled(aEnabled, aType, aConfig) {
- let self = this;
- switch (aType) {
- case TETHERING_TYPE_WIFI:
- return this.createPromiseWithId(function(aResolverId) {
- let data = { resolverId: aResolverId, enabled: aEnabled, config: aConfig };
- cpmm.sendAsyncMessage("WifiManager:setWifiTethering", { data: data});
- });
- case TETHERING_TYPE_BLUETOOTH:
- case TETHERING_TYPE_USB:
- default:
- debug("tethering type(" + aType + ") doesn't support");
- return this.createPromiseWithId(function(aResolverId) {
- self.takePromiseResolver(aResolverId).reject();
- });
- }
- },
-};
-
-this.NSGetFactory =
- XPCOMUtils.generateNSGetFactory([TetheringManager]);
-
-var debug;
-if (DEBUG) {
- debug = function (s) {
- dump("-*- TetheringManager component: " + s + "\n");
- };
-} else {
- debug = function (s) {};
-}
diff --git a/dom/tethering/TetheringManager.manifest b/dom/tethering/TetheringManager.manifest
deleted file mode 100644
index 6ef01c69d..000000000
--- a/dom/tethering/TetheringManager.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-#TetheringManager.js
-component {bd8a831c-d8ec-4f00-8803-606e50781097} TetheringManager.js
-contract @mozilla.org/tetheringmanager;1 {bd8a831c-d8ec-4f00-8803-606e50781097}
-
diff --git a/dom/tethering/moz.build b/dom/tethering/moz.build
deleted file mode 100644
index 4f68aca2d..000000000
--- a/dom/tethering/moz.build
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXTRA_COMPONENTS += [
- 'TetheringManager.js',
- 'TetheringManager.manifest',
-]
-
-FINAL_LIBRARY = 'xul'
diff --git a/dom/tethering/tests/marionette/head.js b/dom/tethering/tests/marionette/head.js
deleted file mode 100644
index c6b6abe26..000000000
--- a/dom/tethering/tests/marionette/head.js
+++ /dev/null
@@ -1,768 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const TYPE_WIFI = "wifi";
-const TYPE_BLUETOOTH = "bt";
-const TYPE_USB = "usb";
-
-/**
- * General tethering setting.
- */
-const TETHERING_SETTING_IP = "192.168.1.1";
-const TETHERING_SETTNG_PREFIX = "24";
-const TETHERING_SETTING_START_IP = "192.168.1.10";
-const TETHERING_SETTING_END_IP = "192.168.1.30";
-const TETHERING_SETTING_DNS1 = "8.8.8.8";
-const TETHERING_SETTING_DNS2 = "8.8.4.4";
-
-const TETHERING_NETWORK_ADDR = "192.168.1.0/24";
-
-/**
- * Wifi tethering setting.
- */
-const TETHERING_SETTING_SSID = "FirefoxHotSpot";
-const TETHERING_SETTING_SECURITY = "open";
-const TETHERING_SETTING_KEY = "1234567890";
-
-const SETTINGS_RIL_DATA_ENABLED = 'ril.data.enabled';
-const SETTINGS_KEY_DATA_APN_SETTINGS = "ril.data.apnSettings";
-
-// Emulate Promise.jsm semantics.
-Promise.defer = function() { return new Deferred(); }
-function Deferred() {
- this.promise = new Promise(function(resolve, reject) {
- this.resolve = resolve;
- this.reject = reject;
- }.bind(this));
- Object.freeze(this);
-}
-
-var gTestSuite = (function() {
- let suite = {};
-
- let tetheringManager;
- let pendingEmulatorShellCount = 0;
-
- /**
- * A wrapper function of "is".
- *
- * Calls the marionette function "is" as well as throws an exception
- * if the givens values are not equal.
- *
- * @param value1
- * Any type of value to compare.
- *
- * @param value2
- * Any type of value to compare.
- *
- * @param message
- * Debug message for this check.
- *
- */
- function isOrThrow(value1, value2, message) {
- is(value1, value2, message);
- if (value1 !== value2) {
- throw message;
- }
- }
-
- /**
- * Send emulator shell command with safe guard.
- *
- * We should only call |finish()| after all emulator command transactions
- * end, so here comes with the pending counter. Resolve when the emulator
- * gives positive response, and reject otherwise.
- *
- * Fulfill params:
- * result -- an array of emulator response lines.
- * Reject params:
- * result -- an array of emulator response lines.
- *
- * @param aCommand
- * A string command to be passed to emulator through its telnet console.
- *
- * @return A deferred promise.
- */
- function runEmulatorShellSafe(aCommand) {
- let deferred = Promise.defer();
-
- ++pendingEmulatorShellCount;
- runEmulatorShell(aCommand, function(aResult) {
- --pendingEmulatorShellCount;
-
- ok(true, "Emulator shell response: " + JSON.stringify(aResult));
- if (Array.isArray(aResult)) {
- deferred.resolve(aResult);
- } else {
- deferred.reject(aResult);
- }
- });
-
- return deferred.promise;
- }
-
- /**
- * Wait for timeout.
- *
- * Resolve when the given duration elapsed. Never reject.
- *
- * Fulfill params: (none)
- *
- * @param aTimeoutMs
- * The duration after which the timeout event should occurs.
- *
- * @return A deferred promise.
- */
- function waitForTimeout(aTimeoutMs) {
- let deferred = Promise.defer();
-
- setTimeout(function() {
- deferred.resolve();
- }, aTimeoutMs);
-
- return deferred.promise;
- }
-
- /**
- * Get mozSettings value specified by @aKey.
- *
- * Resolve if that mozSettings value is retrieved successfully, reject
- * otherwise.
- *
- * Fulfill params:
- * The corresponding mozSettings value of the key.
- * Reject params: (none)
- *
- * @param aKey
- * A string.
- *
- * @return A deferred promise.
- */
- function getSettings(aKey) {
- let request = navigator.mozSettings.createLock().get(aKey);
-
- return wrapDomRequestAsPromise(request)
- .then(function resolve(aEvent) {
- ok(true, "getSettings(" + aKey + ") - success");
- return aEvent.target.result[aKey];
- }, function reject(aEvent) {
- ok(false, "getSettings(" + aKey + ") - error");
- throw aEvent.target.error;
- });
- }
-
- /**
- * Set mozSettings values.
- *
- * Resolve if that mozSettings value is set successfully, reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aSettings
- * An object of format |{key1: value1, key2: value2, ...}|.
- * @return A deferred promise.
- */
- function setSettings(aSettings) {
- let lock = window.navigator.mozSettings.createLock();
- let request = lock.set(aSettings);
- let deferred = Promise.defer();
- lock.onsettingstransactionsuccess = function () {
- ok(true, "setSettings(" + JSON.stringify(aSettings) + ")");
- deferred.resolve();
- };
- lock.onsettingstransactionfailure = function (aEvent) {
- ok(false, "setSettings(" + JSON.stringify(aSettings) + ")");
- deferred.reject();
- throw aEvent.target.error;
- };
- return deferred.promise;
- }
-
- /**
- * Set mozSettings value with only one key.
- *
- * Resolve if that mozSettings value is set successfully, reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aKey
- * A string key.
- * @param aValue
- * An object value.
- * @param aAllowError [optional]
- * A boolean value. If set to true, an error response won't be treated
- * as test failure. Default: false.
- *
- * @return A deferred promise.
- */
- function setSettings1(aKey, aValue, aAllowError) {
- let settings = {};
- settings[aKey] = aValue;
- return setSettings(settings, aAllowError);
- }
-
- /**
- * Convenient MozSettings getter for SETTINGS_KEY_DATA_APN_SETTINGS.
- */
- function getDataApnSettings(aAllowError) {
- return getSettings(SETTINGS_KEY_DATA_APN_SETTINGS, aAllowError);
- }
-
- /**
- * Convenient MozSettings setter for SETTINGS_KEY_DATA_APN_SETTINGS.
- */
- function setDataApnSettings(aApnSettings, aAllowError) {
- return setSettings1(SETTINGS_KEY_DATA_APN_SETTINGS, aApnSettings, aAllowError);
- }
-
- /**
- * Set 'ro.tethering.dun_required' system property to 1. Note that this is a
- * 'ro' property, it can only be set once.
- */
- function setTetheringDunRequired() {
- return runEmulatorShellSafe(['setprop', 'ro.tethering.dun_required', '1']);
- }
-
- /**
- * Wrap DOMRequest onsuccess/onerror events to Promise resolve/reject.
- *
- * Fulfill params: A DOMEvent.
- * Reject params: A DOMEvent.
- *
- * @param aRequest
- * A DOMRequest instance.
- *
- * @return A deferred promise.
- */
- function wrapDomRequestAsPromise(aRequest) {
- let deffered = Promise.defer();
-
- ok(aRequest instanceof DOMRequest,
- "aRequest is instanceof" + aRequest.constructor);
-
- aRequest.onsuccess = function(aEvent) {
- deffered.resolve(aEvent);
- };
- aRequest.onerror = function(aEvent) {
- deffered.reject(aEvent);
- };
-
- return deffered.promise;
- }
-
- /**
- * Wait for one named MozMobileConnection event.
- *
- * Resolve if that named event occurs. Never reject.
- *
- * Fulfill params: the DOMEvent passed.
- *
- * @param aEventName
- * A string event name.
- *
- * @return A deferred promise.
- */
- function waitForMobileConnectionEventOnce(aEventName, aServiceId) {
- aServiceId = aServiceId || 0;
-
- let deferred = Promise.defer();
- let mobileconnection = navigator.mozMobileConnections[aServiceId];
-
- mobileconnection.addEventListener(aEventName, function onevent(aEvent) {
- mobileconnection.removeEventListener(aEventName, onevent);
-
- ok(true, "Mobile connection event '" + aEventName + "' got.");
- deferred.resolve(aEvent);
- });
-
- return deferred.promise;
- }
-
- /**
- * Wait for RIL data being connected.
- *
- * This function will check |MozMobileConnection.data.connected| on
- * every 'datachange' event. Resolve when |MozMobileConnection.data.connected|
- * becomes the expected state. Never reject.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aConnected
- * Boolean that indicates the desired data state.
- *
- * @param aServiceId [optional]
- * A numeric DSDS service id. Default: 0.
- *
- * @return A deferred promise.
- */
- function waitForRilDataConnected(aConnected, aServiceId) {
- aServiceId = aServiceId || 0;
-
- return waitForMobileConnectionEventOnce('datachange', aServiceId)
- .then(function () {
- let mobileconnection = navigator.mozMobileConnections[aServiceId];
- if (mobileconnection.data.connected !== aConnected) {
- return waitForRilDataConnected(aConnected, aServiceId);
- }
- });
- }
-
- /**
- * Verify everything about routing when the wifi tethering is either on or off.
- *
- * We use two unix commands to verify the routing: 'netcfg' and 'ip route'.
- * For now the following two things will be checked:
- * 1) The default route interface should be 'rmnet0'.
- * 2) wlan0 is up and its ip is set to a private subnet.
- *
- * We also verify iptables output as netd's NatController will execute
- * $ iptables -t nat -A POSTROUTING -o rmnet0 -j MASQUERADE
- *
- * For tethering through dun, we use 'ip rule' to find the secondary routing
- * table and look for default route on that table.
- *
- * Resolve when the verification is successful and reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: String that indicates the reason of rejection.
- *
- * @return A deferred promise.
- */
- function verifyTetheringRouting(aEnabled, aIsDun) {
- let netcfgResult = {};
- let ipRouteResult = {};
- let ipSecondaryRouteResult = {};
-
- // Execute 'netcfg' and parse to |netcfgResult|, each key of which is the
- // interface name and value is { ip(string) }.
- function exeAndParseNetcfg() {
- return runEmulatorShellSafe(['netcfg'])
- .then(function (aLines) {
- // Sample output:
- //
- // lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
- // eth0 UP 10.0.2.15/24 0x00001043 52:54:00:12:34:56
- // rmnet1 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:58
- // rmnet2 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:59
- // rmnet3 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:5a
- // wlan0 UP 192.168.1.1/24 0x00001043 52:54:00:12:34:5b
- // sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
- // rmnet0 UP 10.0.2.100/24 0x00001043 52:54:00:12:34:57
- //
- aLines.forEach(function (aLine) {
- let tokens = aLine.split(/\s+/);
- if (tokens.length < 5) {
- return;
- }
- let ifname = tokens[0];
- let ip = (tokens[2].split('/'))[0];
- netcfgResult[ifname] = { ip: ip };
- });
- });
- }
-
- // Execute 'ip route' and parse to |ipRouteResult|, each key of which is the
- // interface name and value is { src(string), default(boolean) }.
- function exeAndParseIpRoute() {
- return runEmulatorShellSafe(['ip', 'route'])
- .then(function (aLines) {
- // Sample output:
- //
- // 10.0.2.4 via 10.0.2.2 dev rmnet0
- // 10.0.2.3 via 10.0.2.2 dev rmnet0
- // 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.1
- // 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
- // 10.0.2.0/24 dev rmnet0 proto kernel scope link src 10.0.2.100
- // default via 10.0.2.2 dev rmnet0
- // default via 10.0.2.2 dev eth0 metric 2
- //
-
- // Parse source ip for each interface.
- aLines.forEach(function (aLine) {
- let tokens = aLine.trim().split(/\s+/);
- let srcIndex = tokens.indexOf('src');
- if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
- return;
- }
- let ifname = tokens[2];
- let src = tokens[srcIndex + 1];
- ipRouteResult[ifname] = { src: src, default: false };
- });
-
- // Parse default interfaces.
- aLines.forEach(function (aLine) {
- let tokens = aLine.split(/\s+/);
- if (tokens.length < 2) {
- return;
- }
- if ('default' === tokens[0]) {
- let ifnameIndex = tokens.indexOf('dev');
- if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
- return;
- }
- let ifname = tokens[ifnameIndex + 1];
- if (ipRouteResult[ifname]) {
- ipRouteResult[ifname].default = true;
- }
- return;
- }
- });
-
- });
-
- }
-
- // Find MASQUERADE in POSTROUTING section. 'MASQUERADE' should be found
- // when tethering is enabled. 'MASQUERADE' shouldn't be found when tethering
- // is disabled.
- function verifyIptables() {
- return runEmulatorShellSafe(['iptables', '-t', 'nat', '-L', 'POSTROUTING'])
- .then(function(aLines) {
- // $ iptables -t nat -L POSTROUTING
- //
- // Sample output (tethering on):
- //
- // Chain POSTROUTING (policy ACCEPT)
- // target prot opt source destination
- // MASQUERADE all -- anywhere anywhere
- //
- let found = (function find_MASQUERADE() {
- // Skip first two lines.
- for (let i = 2; i < aLines.length; i++) {
- if (-1 !== aLines[i].indexOf('MASQUERADE')) {
- return true;
- }
- }
- return false;
- })();
-
- if ((aEnabled && !found) || (!aEnabled && found)) {
- throw 'MASQUERADE' + (found ? '' : ' not') + ' found while tethering is ' +
- (aEnabled ? 'enabled' : 'disabled');
- }
- });
- }
-
- // Execute 'ip rule show', there must be one rule for tethering network
- // address to lookup for a secondary routing table, return that table id.
- function verifyIpRule() {
- if (!aIsDun) {
- return;
- }
-
- return runEmulatorShellSafe(['ip', 'rule', 'show'])
- .then(function (aLines) {
- // Sample output:
- //
- // 0: from all lookup local
- // 32765: from 192.168.1.0/24 lookup 60
- // 32766: from all lookup main
- // 32767: from all lookup default
- //
- let tableId = (function findTableId() {
- for (let i = 0; i < aLines.length; i++) {
- let tokens = aLines[i].split(/\s+/);
- if (-1 != tokens.indexOf(TETHERING_NETWORK_ADDR)) {
- let lookupIndex = tokens.indexOf('lookup');
- if (lookupIndex < 0 || lookupIndex + 1 >= tokens.length) {
- return;
- }
- return tokens[lookupIndex + 1];
- }
- }
- return;
- })();
-
- if ((aEnabled && !tableId) || (!aEnabled && tableId)) {
- throw 'Secondary table' + (tableId ? '' : ' not') + ' found while tethering is ' +
- (aEnabled ? 'enabled' : 'disabled');
- }
-
- return tableId;
- });
- }
-
- // Given the table id, use 'ip rule show table <table id>' to find the
- // default route on that secondary routing table.
- function execAndParseSecondaryTable(aTableId) {
- if (!aIsDun || !aEnabled) {
- return;
- }
-
- return runEmulatorShellSafe(['ip', 'route', 'show', 'table', aTableId])
- .then(function (aLines) {
- // We only look for default route in secondary table.
- aLines.forEach(function (aLine) {
- let tokens = aLine.split(/\s+/);
- if (tokens.length < 2) {
- return;
- }
- if ('default' === tokens[0]) {
- let ifnameIndex = tokens.indexOf('dev');
- if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
- return;
- }
- let ifname = tokens[ifnameIndex + 1];
- ipSecondaryRouteResult[ifname] = { default: true };
- return;
- }
- });
- });
- }
-
- function verifyDefaultRouteAndIp(aExpectedWifiTetheringIp) {
- log(JSON.stringify(ipRouteResult));
- log(JSON.stringify(ipSecondaryRouteResult));
- log(JSON.stringify(netcfgResult));
-
- if (aEnabled) {
- isOrThrow(ipRouteResult['rmnet0'].src, netcfgResult['rmnet0'].ip, 'rmnet0.ip');
- isOrThrow(ipRouteResult['rmnet0'].default, true, 'rmnet0.default');
-
- isOrThrow(ipRouteResult['wlan0'].src, netcfgResult['wlan0'].ip, 'wlan0.ip');
- isOrThrow(ipRouteResult['wlan0'].src, aExpectedWifiTetheringIp, 'expected ip');
- isOrThrow(ipRouteResult['wlan0'].default, false, 'wlan0.default');
-
- if (aIsDun) {
- isOrThrow(ipRouteResult['rmnet1'].src, netcfgResult['rmnet1'].ip, 'rmnet1.ip');
- isOrThrow(ipRouteResult['rmnet1'].default, false, 'rmnet1.default');
- // Dun's network default route is set on secondary routing table.
- isOrThrow(ipSecondaryRouteResult['rmnet1'].default, true, 'secondary rmnet1.default');
- }
- }
- }
-
- return verifyIptables()
- .then(verifyIpRule)
- .then(tableId => execAndParseSecondaryTable(tableId))
- .then(exeAndParseNetcfg)
- .then(exeAndParseIpRoute)
- .then(() => verifyDefaultRouteAndIp(TETHERING_SETTING_IP));
- }
-
- /**
- * Request to enable/disable wifi tethering.
- *
- * Enable/disable wifi tethering by using setTetheringEnabled API
- * Resolve when the routing is verified to set up successfully in 20 seconds. The polling
- * period is 1 second.
- *
- * Fulfill params: (none)
- * Reject params: The error message.
- *
- * @param aEnabled
- * Boolean that indicates to enable or disable wifi tethering.
- * @param aIsDun
- * Boolean that indicates whether dun is required.
- *
- * @return A deferred promise.
- */
- function setWifiTetheringEnabled(aEnabled, aIsDun) {
- let RETRY_INTERVAL_MS = 1000;
- let retryCnt = 20;
-
- let config = {
- "ip" : TETHERING_SETTING_IP,
- "prefix" : TETHERING_SETTNG_PREFIX,
- "startIp" : TETHERING_SETTING_START_IP,
- "endIp" : TETHERING_SETTING_END_IP,
- "dns1" : TETHERING_SETTING_DNS1,
- "dns2" : TETHERING_SETTING_DNS2,
- "wifiConfig": {
- "ssid" : TETHERING_SETTING_SSID,
- "security" : TETHERING_SETTING_SECURITY
- }
- };
-
- return tetheringManager.setTetheringEnabled(aEnabled, TYPE_WIFI, config)
- .then(function waitForRoutingVerified() {
- return verifyTetheringRouting(aEnabled, aIsDun)
- .then(null, function onreject(aReason) {
-
- log('verifyTetheringRouting rejected due to ' + aReason +
- ' (' + retryCnt + ')');
-
- if (!retryCnt--) {
- throw aReason;
- }
-
- return waitForTimeout(RETRY_INTERVAL_MS).then(waitForRoutingVerified);
- });
- });
- }
-
- /**
- * Ensure wifi is enabled/disabled.
- *
- * Issue a wifi enable/disable request if wifi is not in the desired state;
- * return a resolved promise otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return a resolved promise or deferred promise.
- */
- function ensureWifiEnabled(aEnabled) {
- let wifiManager = window.navigator.mozWifiManager;
- if (wifiManager.enabled === aEnabled) {
- return Promise.resolve();
- }
- let request = wifiManager.setWifiEnabled(aEnabled);
- return wrapDomRequestAsPromise(request)
- }
-
- /**
- * Ensure tethering manager exists.
- *
- * Check navigator property |mozTetheringManager| to ensure we could access
- * tethering related function.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function ensureTetheringManager() {
- let deferred = Promise.defer();
-
- tetheringManager = window.navigator.mozTetheringManager;
-
- if (tetheringManager instanceof MozTetheringManager) {
- deferred.resolve();
- } else {
- log("navigator.mozTetheringManager is unavailable");
- deferred.reject();
- }
-
- return deferred.promise;
- }
-
- /**
- * Add required permissions for tethering. Never reject.
- *
- * The permissions required for wifi testing are 'wifi-manage' and 'settings-write'.
- * Never reject.
- *
- * Fulfill params: (none)
- *
- * @return A deferred promise.
- */
- function acquirePermission() {
- let deferred = Promise.defer();
-
- let permissions = [{ 'type': 'wifi-manage', 'allow': 1, 'context': window.document },
- { 'type': 'settings-write', 'allow': 1, 'context': window.document },
- { 'type': 'settings-read', 'allow': 1, 'context': window.document },
- { 'type': 'settings-api-write', 'allow': 1, 'context': window.document },
- { 'type': 'settings-api-read', 'allow': 1, 'context': window.document },
- { 'type': 'mobileconnection', 'allow': 1, 'context': window.document }];
-
- SpecialPowers.pushPermissions(permissions, function() {
- deferred.resolve();
- });
-
- return deferred.promise;
- }
-
- /**
- * Common test routine.
- *
- * Start a test with the given test case chain. The test environment will be
- * settled down before the test. After the test, all the affected things will
- * be restored.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aTestCaseChain
- * The test case entry point, which can be a function or a promise.
- *
- * @return A deferred promise.
- */
- suite.startTest = function(aTestCaseChain) {
- function setUp() {
- return ensureTetheringManager()
- .then(acquirePermission);
- }
-
- function tearDown() {
- waitFor(finish, function() {
- return pendingEmulatorShellCount === 0;
- });
- }
-
- return setUp()
- .then(aTestCaseChain)
- .then(function onresolve() {
- tearDown();
- }, function onreject(aReason) {
- ok(false, 'Promise rejects during test' + (aReason ? '(' + aReason + ')' : ''));
- tearDown();
- });
- };
-
- //---------------------------------------------------
- // Public test suite functions
- //---------------------------------------------------
- suite.ensureWifiEnabled = ensureWifiEnabled;
- suite.setWifiTetheringEnabled = setWifiTetheringEnabled;
- suite.getDataApnSettings = getDataApnSettings;
- suite.setDataApnSettings = setDataApnSettings;
- suite.setTetheringDunRequired = setTetheringDunRequired;
-
-
- /**
- * The common test routine for wifi tethering.
- *
- * Set 'ril.data.enabled' to true
- * before testing and restore it afterward. It will also verify 'ril.data.enabled'
- * and 'tethering.wifi.enabled' to be false in the beginning. Note that this routine
- * will NOT change the state of 'tethering.wifi.enabled' so the user should enable
- * than disable on his/her own. This routine will only check if tethering is turned
- * off after testing.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aTestCaseChain
- * The test case entry point, which can be a function or a promise.
- *
- * @return A deferred promise.
- */
- suite.startTetheringTest = function(aTestCaseChain) {
- let oriDataEnabled;
- function verifyInitialState() {
- return getSettings(SETTINGS_RIL_DATA_ENABLED)
- .then(enabled => initTetheringTestEnvironment(enabled));
- }
-
- function initTetheringTestEnvironment(aEnabled) {
- oriDataEnabled = aEnabled;
- if (aEnabled) {
- return Promise.resolve();
- } else {
- return Promise.all([waitForRilDataConnected(true),
- setSettings1(SETTINGS_RIL_DATA_ENABLED, true)]);
- }
- }
-
- function restoreToInitialState() {
- return setSettings1(SETTINGS_RIL_DATA_ENABLED, oriDataEnabled);
- }
-
- return suite.startTest(function() {
- return verifyInitialState()
- .then(aTestCaseChain)
- .then(restoreToInitialState, function onreject(aReason) {
- return restoreToInitialState()
- .then(() => { throw aReason; }); // Re-throw the orignal reject reason.
- });
- });
- };
-
- return suite;
-})();
diff --git a/dom/tethering/tests/marionette/manifest.ini b/dom/tethering/tests/marionette/manifest.ini
deleted file mode 100644
index 89065724f..000000000
--- a/dom/tethering/tests/marionette/manifest.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[DEFAULT]
-run-if = buildapp == 'b2g'
-
-[test_wifi_tethering_enabled.js]
-; The following test must be the last tethering test ran, as it sets the
-; 'ro.tethering.dun_required' property.
-[test_wifi_tethering_dun.js]
diff --git a/dom/tethering/tests/marionette/test_wifi_tethering_dun.js b/dom/tethering/tests/marionette/test_wifi_tethering_dun.js
deleted file mode 100644
index 3d93cf8d3..000000000
--- a/dom/tethering/tests/marionette/test_wifi_tethering_dun.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-gTestSuite.startTest(function() {
- let origApnSettings;
- return gTestSuite.getDataApnSettings()
- .then(value => {
- origApnSettings = value;
- })
- .then(() => {
- // Set dun apn settings.
- let apnSettings = [[ { "carrier": "T-Mobile US",
- "apn": "epc1.tmobile.com",
- "mmsc": "http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types": ["default","supl","mms"] },
- { "carrier": "T-Mobile US",
- "apn": "epc2.tmobile.com",
- "types": ["dun"] } ]];
- return gTestSuite.setDataApnSettings(apnSettings);
- })
- .then(() => gTestSuite.setTetheringDunRequired())
- .then(() => gTestSuite.startTetheringTest(function() {
- return gTestSuite.ensureWifiEnabled(false)
- .then(() => gTestSuite.setWifiTetheringEnabled(true, true))
- .then(() => gTestSuite.setWifiTetheringEnabled(false, true));
- }))
- // Restore apn settings.
- .then(() => {
- if (origApnSettings) {
- return gTestSuite.setDataApnSettings(origApnSettings);
- }
- });
-}); \ No newline at end of file
diff --git a/dom/tethering/tests/marionette/test_wifi_tethering_enabled.js b/dom/tethering/tests/marionette/test_wifi_tethering_enabled.js
deleted file mode 100644
index 936219ec5..000000000
--- a/dom/tethering/tests/marionette/test_wifi_tethering_enabled.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-gTestSuite.startTetheringTest(function() {
- return gTestSuite.ensureWifiEnabled(false)
- .then(() => gTestSuite.setWifiTetheringEnabled(true))
- .then(() => gTestSuite.setWifiTetheringEnabled(false));
-});
diff --git a/dom/url/URL.cpp b/dom/url/URL.cpp
index 1f15e1151..04f5ec137 100644
--- a/dom/url/URL.cpp
+++ b/dom/url/URL.cpp
@@ -17,7 +17,6 @@
#include "nsEscape.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsIIOService.h"
-#include "nsIURIWithQuery.h"
#include "nsIURL.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
@@ -525,21 +524,10 @@ URLMainThread::GetPathname(nsAString& aPathname, ErrorResult& aRv) const
// Do not throw! Not having a valid URI or URL should result in an empty
// string.
- nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(mURI));
- if (url) {
- nsAutoCString file;
- nsresult rv = url->GetFilePath(file);
- if (NS_SUCCEEDED(rv)) {
- CopyUTF8toUTF16(file, aPathname);
- }
-
- return;
- }
-
- nsAutoCString path;
- nsresult rv = mURI->GetPath(path);
+ nsAutoCString file;
+ nsresult rv = mURI->GetFilePath(file);
if (NS_SUCCEEDED(rv)) {
- CopyUTF8toUTF16(path, aPathname);
+ CopyUTF8toUTF16(file, aPathname);
}
}
@@ -548,11 +536,7 @@ URLMainThread::SetPathname(const nsAString& aPathname, ErrorResult& aRv)
{
// Do not throw!
- nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(mURI));
- if (url) {
- url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname));
- return;
- }
+ mURI->SetFilePath(NS_ConvertUTF16toUTF8(aPathname));
}
void
@@ -566,13 +550,9 @@ URLMainThread::GetSearch(nsAString& aSearch, ErrorResult& aRv) const
nsAutoCString search;
nsresult rv;
- nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(mURI));
- if (url) {
- rv = url->GetQuery(search);
- if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
- CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
- }
- return;
+ rv = mURI->GetQuery(search);
+ if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
+ CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
}
}
@@ -603,11 +583,7 @@ URLMainThread::SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv)
{
// Ignore failures to be compatible with NS4.
- nsCOMPtr<nsIURIWithQuery> uriWithQuery(do_QueryInterface(mURI));
- if (uriWithQuery) {
- uriWithQuery->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
- return;
- }
+ mURI->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
}
} // anonymous namespace
@@ -1137,6 +1113,12 @@ public:
return true;
}
+ void
+ Dispatch(ErrorResult& aRv)
+ {
+ WorkerMainThreadRunnable::Dispatch(Terminating, aRv);
+ }
+
private:
nsAString& mValue;
GetterType mType;
@@ -1237,6 +1219,12 @@ public:
return mFailed;
}
+ void
+ Dispatch(ErrorResult& aRv)
+ {
+ WorkerMainThreadRunnable::Dispatch(Terminating, aRv);
+ }
+
private:
const nsString mValue;
SetterType mType;
@@ -1248,7 +1236,7 @@ already_AddRefed<URLWorker>
FinishConstructor(JSContext* aCx, WorkerPrivate* aPrivate,
ConstructorRunnable* aRunnable, ErrorResult& aRv)
{
- aRunnable->Dispatch(aRv);
+ aRunnable->Dispatch(Terminating, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
@@ -1326,7 +1314,7 @@ URLWorker::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
RefPtr<CreateURLRunnable> runnable =
new CreateURLRunnable(workerPrivate, blobImpl, aOptions, aResult);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -1349,7 +1337,7 @@ URLWorker::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aUrl,
RefPtr<RevokeURLRunnable> runnable =
new RevokeURLRunnable(workerPrivate, aUrl);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -1372,7 +1360,7 @@ URLWorker::IsValidURL(const GlobalObject& aGlobal, const nsAString& aUrl,
RefPtr<IsValidURLRunnable> runnable =
new IsValidURLRunnable(workerPrivate, aUrl);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return false;
}
diff --git a/dom/url/tests/test_url.html b/dom/url/tests/test_url.html
index d07a752bb..73e75667d 100644
--- a/dom/url/tests/test_url.html
+++ b/dom/url/tests/test_url.html
@@ -399,6 +399,18 @@
</script>
<script>
+ /** Test for Bug 1275746 **/
+ SimpleTest.doesThrow(() => { var url = new URL("http:"); }, "http: is not a valid URL");
+ SimpleTest.doesThrow(() => { var url = new URL("http:///"); }, "http: is not a valid URL");
+
+ var url = new URL("file:");
+ is(url.href, "file:///", "Parsing file: should work.");
+
+ url = new URL("file:///");
+ is(url.href, "file:///", "Parsing file:/// should work.");
+ </script>
+
+ <script>
var url = new URL("scheme:path/to/file?query#hash");
is(url.href, "scheme:path/to/file?query#hash");
is(url.pathname, "path/to/file");
diff --git a/dom/webidl/CanvasRenderingContext2D.webidl b/dom/webidl/CanvasRenderingContext2D.webidl
index 38a30f9e3..1c5564215 100644
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -27,6 +27,9 @@ dictionary HitRegionOptions {
};
typedef (HTMLImageElement or
+ SVGImageElement) HTMLOrSVGImageElement;
+
+typedef (HTMLOrSVGImageElement or
HTMLCanvasElement or
HTMLVideoElement or
ImageBitmap) CanvasImageSource;
diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl
index f05656e84..0b8c278fe 100644
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -430,6 +430,12 @@ partial interface Document {
void removeAnonymousContent(AnonymousContent aContent);
};
+// http://w3c.github.io/selection-api/#extensions-to-document-interface
+partial interface Document {
+ [Throws]
+ Selection? getSelection();
+};
+
// Extension to give chrome JS the ability to determine whether
// the user has interacted with the document or not.
partial interface Document {
diff --git a/dom/webidl/EventHandler.webidl b/dom/webidl/EventHandler.webidl
index e65a75787..1edc45ac9 100644
--- a/dom/webidl/EventHandler.webidl
+++ b/dom/webidl/EventHandler.webidl
@@ -33,6 +33,7 @@ interface GlobalEventHandlers {
// attribute OnErrorEventHandler onerror;
attribute EventHandler onfocus;
//(Not implemented)attribute EventHandler oncancel;
+ attribute EventHandler onauxclick;
attribute EventHandler oncanplay;
attribute EventHandler oncanplaythrough;
attribute EventHandler onchange;
@@ -128,14 +129,14 @@ interface GlobalEventHandlers {
attribute EventHandler onmozpointerlockerror;
// CSS-Animation and CSS-Transition handlers.
+ attribute EventHandler onanimationcancel;
attribute EventHandler onanimationend;
attribute EventHandler onanimationiteration;
attribute EventHandler onanimationstart;
+ attribute EventHandler ontransitioncancel;
attribute EventHandler ontransitionend;
- // We will ship transitionrun and transitionstart events
- // on Firefox 53. (For detail, see bug 1324985)
-// attribute EventHandler ontransitionrun;
-// attribute EventHandler ontransitionstart;
+ attribute EventHandler ontransitionrun;
+ attribute EventHandler ontransitionstart;
// CSS-Animation and CSS-Transition legacy handlers.
// This handler isn't standard.
diff --git a/dom/webidl/HTMLDocument.webidl b/dom/webidl/HTMLDocument.webidl
index 61b466ff0..42f6d98f7 100644
--- a/dom/webidl/HTMLDocument.webidl
+++ b/dom/webidl/HTMLDocument.webidl
@@ -73,10 +73,6 @@ interface HTMLDocument : Document {
readonly attribute HTMLAllCollection all;
- // https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#selections
- [Throws]
- Selection? getSelection();
-
// @deprecated These are old Netscape 4 methods. Do not use,
// the implementation is no-op.
// XXXbz do we actually need these anymore?
diff --git a/dom/webidl/HTMLInputElement.webidl b/dom/webidl/HTMLInputElement.webidl
index 050d19510..cf3e9a4c7 100644
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -238,6 +238,9 @@ partial interface HTMLInputElement {
dictionary DateTimeValue {
long hour;
long minute;
+ long year;
+ long month;
+ long day;
};
partial interface HTMLInputElement {
@@ -250,6 +253,14 @@ partial interface HTMLInputElement {
[Pref="dom.forms.datetime", ChromeOnly]
void setDateTimePickerState(boolean open);
+ [Pref="dom.forms.datetime", ChromeOnly,
+ BinaryName="getMinimumAsDouble"]
+ double getMinimum();
+
+ [Pref="dom.forms.datetime", ChromeOnly,
+ BinaryName="getMaximumAsDouble"]
+ double getMaximum();
+
[Pref="dom.forms.datetime", Func="IsChromeOrXBL"]
void openDateTimePicker(optional DateTimeValue initialValue);
@@ -258,4 +269,12 @@ partial interface HTMLInputElement {
[Pref="dom.forms.datetime", Func="IsChromeOrXBL"]
void closeDateTimePicker();
+
+ [Pref="dom.forms.datetime", Func="IsChromeOrXBL",
+ BinaryName="getStepAsDouble"]
+ double getStep();
+
+ [Pref="dom.forms.datetime", Func="IsChromeOrXBL",
+ BinaryName="getStepBaseAsDouble"]
+ double getStepBase();
};
diff --git a/dom/webidl/MozApplicationEvent.webidl b/dom/webidl/MozApplicationEvent.webidl
deleted file mode 100644
index e46fdca06..000000000
--- a/dom/webidl/MozApplicationEvent.webidl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-[Constructor(DOMString type, optional MozApplicationEventInit eventInitDict), ChromeOnly]
-interface MozApplicationEvent : Event
-{
- readonly attribute DOMApplication? application;
-};
-
-dictionary MozApplicationEventInit : EventInit
-{
- DOMApplication? application = null;
-};
diff --git a/dom/webidl/MozNetworkStats.webidl b/dom/webidl/MozNetworkStats.webidl
deleted file mode 100644
index dc8635b87..000000000
--- a/dom/webidl/MozNetworkStats.webidl
+++ /dev/null
@@ -1,73 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Provide the detailed options for specifying different kinds of data filtering
- * in getSamples function.
- */
-dictionary NetworkStatsGetOptions
-{
- /**
- * App manifest URL is used to filter network stats by app, while service type
- * is used to filter stats by system service.
- * Note that, these two options cannot be specified at the same time for now;
- * others, an NS_ERROR_NOT_IMPLMENTED exception will be thrown.
- */
- DOMString? appManifestURL = null;
- DOMString serviceType = "";
- /**
- * If it is set as true, only the browsing traffic, which is generated from
- * the mozbrowser iframe element within an app, is returned in result.
- * If it is set as false or not set, the total traffic, which is generated
- * from both the mozapp and mozbrowser iframe elements, is returned.
- */
- boolean browsingTrafficOnly = false;
-};
-
-dictionary NetworkStatsAlarmOptions
-{
- Date startTime;
- Date data;
-};
-
-[JSImplementation="@mozilla.org/networkstats;1",
- ChromeOnly,
- Pref="dom.mozNetworkStats.enabled"]
-interface MozNetworkStats {
- /**
- * App manifest URL of an application for specifying the per-app stats of the
- * specified app.
- */
- readonly attribute DOMString appManifestURL;
-
- /**
- * True if this stats is the browsing traffic of an app (the traffic generated
- * by a mozbrowser iframe element).
- * Otherwise this stats represents the total traffic of an app.
- */
- readonly attribute boolean browsingTrafficOnly;
-
- /**
- * Service type is used to retrieve the corresponding "system-only" stats.
- * E.g., "Tethering", "OTA", etc.
- */
- readonly attribute DOMString serviceType;
-
- /**
- * Network the returned data belongs to.
- */
- readonly attribute MozNetworkStatsInterface network;
-
- /**
- * Stats for a network.
- */
- [Cached, Pure]
- readonly attribute sequence<MozNetworkStatsData> data;
-
- /**
- * Dates
- */
- readonly attribute object start;
- readonly attribute object end;
-};
diff --git a/dom/webidl/MozNetworkStatsAlarm.webidl b/dom/webidl/MozNetworkStatsAlarm.webidl
deleted file mode 100644
index e8bc01998..000000000
--- a/dom/webidl/MozNetworkStatsAlarm.webidl
+++ /dev/null
@@ -1,13 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-[JSImplementation="@mozilla.org/networkstatsalarm;1",
- ChromeOnly,
- Pref="dom.mozNetworkStats.enabled"]
-interface MozNetworkStatsAlarm {
- readonly attribute unsigned long alarmId;
- readonly attribute MozNetworkStatsInterface network;
- readonly attribute long long threshold;
- readonly attribute any data;
-};
diff --git a/dom/webidl/MozNetworkStatsData.webidl b/dom/webidl/MozNetworkStatsData.webidl
deleted file mode 100644
index 60d1e0d36..000000000
--- a/dom/webidl/MozNetworkStatsData.webidl
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-[JSImplementation="@mozilla.org/networkStatsdata;1",
- ChromeOnly,
- Pref="dom.mozNetworkStats.enabled"]
-interface MozNetworkStatsData {
- readonly attribute unsigned long rxBytes; // Received bytes.
- readonly attribute unsigned long txBytes; // Sent bytes.
- readonly attribute Date date; // Date.
-};
diff --git a/dom/webidl/MozNetworkStatsInterface.webidl b/dom/webidl/MozNetworkStatsInterface.webidl
deleted file mode 100644
index 82acfad6b..000000000
--- a/dom/webidl/MozNetworkStatsInterface.webidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-dictionary NetworkInterface {
- long type;
- DOMString id;
-};
-
-/**
- * Represents a data interface for which the manager is recording statistics.
- */
-[Constructor(optional NetworkInterface networkinterface),
- JSImplementation="@mozilla.org/networkstatsinterface;1",
- ChromeOnly,
- Pref="dom.mozNetworkStats.enabled"]
-interface MozNetworkStatsInterface {
- readonly attribute long type;
-
- /**
- * Id value is '0' for wifi or the iccid for mobile (SIM).
- */
- readonly attribute DOMString id;
-
- jsonifier;
-};
diff --git a/dom/webidl/MozNetworkStatsManager.webidl b/dom/webidl/MozNetworkStatsManager.webidl
deleted file mode 100644
index 2c0e374d7..000000000
--- a/dom/webidl/MozNetworkStatsManager.webidl
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-[NavigatorProperty="mozNetworkStats",
- JSImplementation="@mozilla.org/networkStatsManager;1",
- ChromeOnly,
- Pref="dom.mozNetworkStats.enabled"]
-interface MozNetworkStatsManager {
- /**
- * Constants for known interface types.
- */
- const long WIFI = 0;
- const long MOBILE = 1;
-
- /**
- * Find samples between two dates start and end, both included.
- *
- * If options is provided, per-app or per-system service usage will be
- * retrieved; otherwise the target will be overall system usage.
- *
- * If success, the request result will be an MozNetworkStats object.
- */
- DOMRequest getSamples(MozNetworkStatsInterface network,
- Date start,
- Date end,
- optional NetworkStatsGetOptions options);
-
- /**
- * Install an alarm on a network. The network must be in the return of
- * getAvailableNetworks() otherwise an "InvalidNetwork" exception will
- * be raised.
- *
- * When total data usage reaches threshold bytes, a "networkstats-alarm"
- * system message is sent to the application, where the optional parameter
- * |data| must be a cloneable object.
- *
- * If success, the |result| field of the DOMRequest keeps the alarm Id.
- */
- DOMRequest addAlarm(MozNetworkStatsInterface network,
- long long threshold,
- optional NetworkStatsAlarmOptions options);
-
- /**
- * Obtain all alarms for those networks returned by getAvailableNetworks().
- * If a network is provided, only retrieves the alarms for that network.
- * The network must be one of those returned by getAvailebleNetworks() or an
- * "InvalidNetwork" exception will be raised.
- *
- * Each alarm object has the same fields as that in the system message:
- * - alarmId
- * - network
- * - threshold
- * - data
- */
- DOMRequest getAllAlarms(optional MozNetworkStatsInterface network);
-
- /**
- * Remove all network alarms. If an |alarmId| is provided, then only that
- * alarm is removed.
- */
- DOMRequest removeAlarms(optional unsigned long alarmId = 0);
-
- /**
- * Remove all stats related with the provided network from DB.
- */
- DOMRequest clearStats(MozNetworkStatsInterface network);
-
- /**
- * Remove all stats in the database.
- */
- DOMRequest clearAllStats();
-
- /**
- * Return available networks that used to be saved in the database.
- */
- DOMRequest getAvailableNetworks(); // array of MozNetworkStatsInterface.
-
- /**
- * Return available service types that used to be saved in the database.
- */
- DOMRequest getAvailableServiceTypes(); // array of string.
-
- /**
- * Minimum time in milliseconds between samples stored in the database.
- */
- readonly attribute long sampleRate;
-
- /**
- * Time in milliseconds recorded by the API until present time. All samples
- * older than maxStorageAge from now are deleted.
- */
- readonly attribute long long maxStorageAge;
-};
diff --git a/dom/webidl/MozSpeakerManager.webidl b/dom/webidl/MozSpeakerManager.webidl
deleted file mode 100644
index 56ecf866f..000000000
--- a/dom/webidl/MozSpeakerManager.webidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-/*
- * Allow application can control acoustic sound output through speaker.
- * Reference https://wiki.mozilla.org/WebAPI/SpeakerManager
- */
-[Constructor()]
-interface MozSpeakerManager : EventTarget {
- /* query the speaker status */
- readonly attribute boolean speakerforced;
- /* force device device's acoustic sound output through speaker */
- attribute boolean forcespeaker;
- /* this event will be fired when device's speaker forced status change */
- attribute EventHandler onspeakerforcedchange;
-};
diff --git a/dom/webidl/MozWifiCapabilities.webidl b/dom/webidl/MozWifiCapabilities.webidl
deleted file mode 100644
index 3acf5fd55..000000000
--- a/dom/webidl/MozWifiCapabilities.webidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-/*
- * The capabilities of Wifi. These are guaranteed not to change over the
- * lifetime of that particular instance.
- */
-enum WifiSecurityMethod {
- "OPEN",
- "WEP",
- "WPA-PSK",
- "WPA-EAP"
-};
-
-enum WifiWpaMethod {
- "SIM",
- "PEAP",
- "TTLS",
- "TLS"
-};
-
-enum WifiWpaPhase2Method {
- "MSCHAPV2",
- "GTC"
-};
-
-enum WifiWpaCertificate {
- "SERVER",
- "USER"
-};
-
-[JSImplementation="@mozilla.org/mozwificapabilities;1",
- Func="Navigator::HasWifiManagerSupport"]
-interface MozWifiCapabilities {
- [Constant, Cached] readonly attribute sequence<WifiSecurityMethod> security;
- [Constant, Cached] readonly attribute sequence<WifiWpaMethod> eapMethod;
- [Constant, Cached] readonly attribute sequence<WifiWpaPhase2Method> eapPhase2;
- [Constant, Cached] readonly attribute sequence<WifiWpaCertificate> certificate;
-
- jsonifier;
-};
-
diff --git a/dom/webidl/MozWifiConnectionInfoEvent.webidl b/dom/webidl/MozWifiConnectionInfoEvent.webidl
deleted file mode 100644
index cfba1aa3e..000000000
--- a/dom/webidl/MozWifiConnectionInfoEvent.webidl
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-[Constructor(DOMString type, optional MozWifiConnectionInfoEventInit eventInitDict)]
-interface MozWifiConnectionInfoEvent : Event
-{
- /**
- * Network object with an SSID field.
- */
- readonly attribute any network;
-
- /**
- * Strength of the signal to network, in dBm between -55 and -100 dBm.
- */
- readonly attribute short signalStrength;
-
- /**
- * Relative signal strength between 0 and 100.
- */
- readonly attribute short relSignalStrength;
-
- /**
- * Link speed in Mb/s.
- */
- readonly attribute long linkSpeed;
-
- /**
- * IP address in the dotted quad format.
- */
- readonly attribute DOMString? ipAddress;
-};
-
-dictionary MozWifiConnectionInfoEventInit : EventInit
-{
- any network = null;
- short signalStrength = 0;
- short relSignalStrength = 0;
- long linkSpeed = 0;
- DOMString ipAddress = "";
-};
diff --git a/dom/webidl/MozWifiManager.webidl b/dom/webidl/MozWifiManager.webidl
deleted file mode 100644
index dd5aa5932..000000000
--- a/dom/webidl/MozWifiManager.webidl
+++ /dev/null
@@ -1,347 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-enum WifiWPSMethod {
- "pbc",
- "pin",
- "cancel"
-};
-
-enum ConnectionStatus {
- "connecting",
- "authenticating",
- "associated",
- "connected",
- "disconnected",
- "wps-timedout",
- "wps-failed",
- "wps-overlapped",
- "connectingfailed"
-};
-
-dictionary WifiWPSInfo {
- WifiWPSMethod method;
- DOMString? pin;
- DOMString? bssid;
-};
-
-dictionary NetworkProperties {
- DOMString ssid;
- long mode;
- long frequency;
- sequence<DOMString>? security;
- sequence<DOMString>? capabilities;
- boolean known;
- boolean connected;
- boolean hidden;
- DOMString bssid;
- DOMString signalStrength;
- long relSignalStrength;
- DOMString psk;
- DOMString wep;
- DOMString wep_key0;
- DOMString wep_key1;
- DOMString wep_key2;
- DOMString wep_key3;
- long wep_tx_keyidx;
- long priority;
- long scan_ssid;
- DOMString keyManagement;
- DOMString identity;
- DOMString password;
- DOMString auth_alg;
- DOMString phase1;
- DOMString phase2;
- DOMString eap;
- DOMString pin;
- boolean dontConnect;
- DOMString serverCertificate;
- DOMString subjectMatch;
- DOMString userCertificate;
-};
-
-[Constructor(optional NetworkProperties properties),
- JSImplementation="@mozilla.org/mozwifinetwork;1",
- Func="Navigator::HasWifiManagerSupport"]
-interface MozWifiNetwork {
- readonly attribute DOMString ssid;
- readonly attribute long mode;
- readonly attribute long frequency;
- [Constant, Cached] readonly attribute sequence<DOMString>? security;
- [Constant, Cached] readonly attribute sequence<DOMString>? capabilities;
- readonly attribute boolean known;
- readonly attribute boolean connected;
- readonly attribute boolean hidden;
-
- attribute DOMString? bssid;
- attribute DOMString? signalStrength;
- attribute long? relSignalStrength;
- attribute DOMString? psk;
- attribute DOMString? wep;
- attribute DOMString? wep_key0;
- attribute DOMString? wep_key1;
- attribute DOMString? wep_key2;
- attribute DOMString? wep_key3;
- attribute long? wep_tx_keyidx;
- attribute long? priority;
- attribute long? scan_ssid;
- attribute DOMString? keyManagement;
- attribute DOMString? identity;
- attribute DOMString? password;
- attribute DOMString? auth_alg;
- attribute DOMString? phase1;
- attribute DOMString? phase2;
- attribute DOMString? eap;
- attribute DOMString? pin;
- attribute boolean? dontConnect;
- attribute DOMString? serverCertificate;
- attribute DOMString? subjectMatch;
- attribute DOMString? userCertificate;
-};
-
-[JSImplementation="@mozilla.org/mozwificonnection;1",
- ChromeOnly]
-interface MozWifiConnection {
- readonly attribute ConnectionStatus status;
- readonly attribute MozWifiNetwork? network;
-};
-
-[JSImplementation="@mozilla.org/mozwificonnectioninfo;1",
- ChromeOnly]
-interface MozWifiConnectionInfo {
- readonly attribute short signalStrength;
- readonly attribute short relSignalStrength;
- readonly attribute long linkSpeed;
- readonly attribute DOMString? ipAddress;
-};
-
-dictionary IPConfiguration {
- boolean enabled;
- DOMString ipaddr;
- DOMString proxy;
- short maskLength;
- DOMString gateway;
- DOMString dns1;
- DOMString dns2;
-};
-
-[JSImplementation="@mozilla.org/wifimanager;1",
- NavigatorProperty="mozWifiManager",
- Func="Navigator::HasWifiManagerSupport",
- UnsafeInPrerendering]
-interface MozWifiManager : EventTarget {
- /**
- * Turn on/off wifi functionality.
- * @param enable true for enable, false for disable.
- * onsuccess: Wifi enable/disable successfully, including no status change.
- * onerror: Wifi enable/disable failed or prohibited.
- */
- DOMRequest setWifiEnabled(boolean enabled);
-
- /**
- * Returns the list of currently available networks.
- * onsuccess: We have obtained the current list of networks. request.value
- * is an object whose property names are SSIDs and values are
- * network objects.
- * onerror: We were unable to obtain a list of property names.
- */
- DOMRequest getNetworks();
-
- /**
- * Returns the list of networks known to the system that will be
- * automatically connected to if they're in range.
- * onsuccess: request.value is an object whose property names are
- * SSIDs and values are network objects.
- * onerror: We were unable to obtain a list of known networks.
- */
- DOMRequest getKnownNetworks();
-
- /**
- * Takes one of the networks returned from getNetworks and tries to
- * connect to it.
- * @param network A network object with information about the network,
- * such as the SSID, key management desired, etc.
- * onsuccess: We have started attempting to associate with the network.
- * request.value is true.
- * onerror: We were unable to select the network. This most likely means a
- * configuration error.
- */
- DOMRequest associate(MozWifiNetwork network);
-
- /**
- * Given a network, removes it from the list of networks that we'll
- * automatically connect to. In order to re-connect to the network, it is
- * necessary to call associate on it.
- * @param network A network object with the SSID of the network to remove.
- * onsuccess: We have removed this network. If we were previously
- * connected to it, we have started reconnecting to the next
- * network in the list.
- * onerror: We were unable to remove the network.
- */
- DOMRequest forget(MozWifiNetwork network);
-
- /**
- * Wi-Fi Protected Setup functionality.
- * @param detail WPS detail which has 'method' and 'pin' field.
- * The possible method field values are:
- * - pbc: The Push Button Configuration.
- * - pin: The PIN configuration.
- * - cancel: Request to cancel WPS in progress.
- * If method field is 'pin', 'pin' field can exist and has
- * a PIN number.
- * If method field is 'pin', 'bssid' field can exist and has
- * a opposite BSSID.
- * onsuccess: We have successfully started/canceled wps.
- * onerror: We have failed to start/cancel wps.
- */
- DOMRequest wps(optional WifiWPSInfo detail);
-
- /**
- * Turn on/off wifi power saving mode.
- * @param enabled true or false.
- * onsuccess: We have successfully turn on/off wifi power saving mode.
- * onerror: We have failed to turn on/off wifi power saving mode.
- */
- DOMRequest setPowerSavingMode(boolean enabled);
-
- /**
- * Given a network, configure using static IP instead of running DHCP
- * @param network A network object with the SSID of the network to set static ip.
- * @param info info should have following field:
- * - enabled True to enable static IP, false to use DHCP
- * - ipaddr configured static IP address
- * - proxy configured proxy server address
- * - maskLength configured mask length
- * - gateway configured gateway address
- * - dns1 configured first DNS server address
- * - dns2 configured seconf DNS server address
- * onsuccess: We have successfully configure the static ip mode.
- * onerror: We have failed to configure the static ip mode.
- */
- DOMRequest setStaticIpMode(MozWifiNetwork network, optional IPConfiguration info);
-
- /**
- * Given a network, configure http proxy when using wifi.
- * @param network A network object with the SSID of the network to set http proxy.
- * @param info info should have following field:
- * - httpProxyHost ip address of http proxy.
- * - httpProxyPort port of http proxy, set 0 to use default port 8080.
- * set info to null to clear http proxy.
- * onsuccess: We have successfully configure http proxy.
- * onerror: We have failed to configure http proxy.
- */
- DOMRequest setHttpProxy(MozWifiNetwork network, any info);
-
- /**
- * Import a certificate file, only support CA certificate now.
- * @param certBlob A Blob object containing raw data of certificate to be imported.
- * Supported format: binary/base64 encoded DER certificates.
- * (.der/.crt/.cer/.pem)
- * Cause error if importing certificates already imported.
- * @param certPassword Password of certificate.
- * @param certNickname User assigned nickname for imported certificate.
- * Nickname must be unique, it causes error on redundant nickname.
- * onsuccess: We have successfully imported certificate. request.result is an
- * object, containing information of imported CA:
- * {
- * nickname: Nickname of imported CA, String.
- * usage: Supported usage of imported CA, Array of String,
- * includes: "ServerCert".
- * }
- * onerror: We have failed to import certificate.
- */
- DOMRequest importCert(Blob certBlob,
- DOMString certPassword,
- DOMString certNickname);
-
- /**
- * Get list of imported WIFI certificates.
- * onsuccess: We have successfully gotten imported certificate list.
- * request.result is an object using nickname as key, array of usage
- * string as value.
- * request.result[USAGE] = [CA_NICKNAME1, CA_NICKNAME2, ...]
- * USAGE string includes: "ServerCert".
- * onerror: We have failed to list certificate.
- */
- DOMRequest getImportedCerts();
-
- /**
- * Delete an imported certificate.
- * @param certNickname Nickname of imported to be deleted.
- * onsuccess: We have successfully deleted certificate.
- * onerror: We have failed to delete certificate.
- */
- DOMRequest deleteCert(DOMString certNickname);
-
- /**
- * Returns whether or not wifi is currently enabled.
- */
- readonly attribute boolean enabled;
-
- /**
- * Returns the MAC address of the wifi adapter.
- */
- readonly attribute DOMString macAddress;
-
- /**
- * An non-null object containing the following information:
- * - status ("disconnected", "connecting", "associated", "connected")
- * - network
- *
- * Note that the object returned is read only. Any changes required must
- * be done by calling other APIs.
- */
- readonly attribute MozWifiConnection connection;
-
- /**
- * A connectionInformation object with the same information found in an
- * MozWifiConnectionInfoEvent (but without the network).
- * If we are not currently connected to a network, this will be null.
- */
- readonly attribute MozWifiConnectionInfo? connectionInformation;
-
- /**
- * Capabilities of Wifi.
- */
- readonly attribute MozWifiCapabilities? capabilities;
-
- /**
- * State notification listeners. These all take an
- * MozWifiStatusChangeEvent with the new status and a network (which may be
- * null).
- *
- * The possible statuses are:
- * - connecting: Fires when we start the process of connecting to a
- * network.
- * - associated: Fires when we have connected to an access point but do
- * not yet have an IP address.
- * - connected: Fires once we are fully connected to an access point and
- * can access the internet.
- * - disconnected: Fires when we either fail to connect to an access
- * point (transition: associated -> disconnected) or
- * when we were connected to a network but have
- * disconnected for any reason (transition: connected ->
- * disconnected).
- */
- attribute EventHandler onstatuschange;
-
- /**
- * An event listener that is called with information about the signal
- * strength and link speed every 5 seconds.
- */
- attribute EventHandler onconnectioninfoupdate;
-
- /**
- * These two events fire when the wifi system is brought online or taken
- * offline.
- */
- attribute EventHandler onenabled;
- attribute EventHandler ondisabled;
-
- /**
- * An event listener that is called with information about the number
- * of wifi stations connected to wifi hotspot every 5 seconds.
- */
- attribute EventHandler onstationinfoupdate;
-};
diff --git a/dom/webidl/MozWifiP2pManager.webidl b/dom/webidl/MozWifiP2pManager.webidl
deleted file mode 100644
index 58ac1f7be..000000000
--- a/dom/webidl/MozWifiP2pManager.webidl
+++ /dev/null
@@ -1,147 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-enum WPSMethod {
- "pbc",
- "keypad",
- "display"
-};
-
-dictionary WPSInfo {
- WPSMethod method;
- DOMString pin;
-};
-
-[JSImplementation="@mozilla.org/wifip2pgroupowner;1",
- Func="Navigator::HasWifiManagerSupport"]
-interface MozWifiP2pGroupOwner {
- readonly attribute DOMString groupName;
- readonly attribute DOMString macAddress;
- readonly attribute DOMString ipAddress;
- readonly attribute DOMString passphrase;
- readonly attribute DOMString ssid;
- readonly attribute any wpsCapabilities;
- readonly attribute unsigned long freq;
- readonly attribute boolean isLocal;
-};
-
-[JSImplementation="@mozilla.org/wifip2pmanager;1",
- NavigatorProperty="mozWifiP2pManager",
- Func="Navigator::HasWifiManagerSupport"]
-interface MozWifiP2pManager : EventTarget
-{
- /**
- * Enable/Disable wifi direct scan.
- *
- * onsuccess: Succeeded in starting/stopping wifi direct scan.
- * onerror: Failed to start/stop wifi direct scan.
- *
- */
- DOMRequest setScanEnabled(boolean enabled);
-
- /**
- * Connect to a peer with given configuration.
- *
- * @param address The peer MAC address we are going to connect.
- * @param wpsMethod The WPS method we want to use.
- * @param goIntent Number from 0 ~ 15 to indicate how much we want to be
- * the group owner.
- *
- * onsuccess: Succeeded in issueing a 'connect' request. It doesn't mean we
- * have connected to the peer.
- *
- * onerror: Failed to issue a 'connect' request, probably due to an
- * invalid peer address, unsupported wps method or any
- * preliminary error.
- *
- **/
- DOMRequest connect(DOMString address, WPSMethod wpsMethod, optional byte goIntent);
-
- /**
- * Disconnect with a peer.
- *
- * @param address The mac address of the peer.
- *
- * onsuccess: Succeeded to issue a 'disconnect' request. It doesn't mean we
- * have disconnected with the peer.
- *
- * onerror: Failed to issue a 'disconnect' request, probably due to the
- * invalid peer address or any preliminary error.
- *
- */
- DOMRequest disconnect(DOMString address);
-
- /**
- * Get peer list
- *
- * onsuccess: Command success, req.result contains an array of peer objects.
- * onerror: Command failed.
- *
- * Peer object format:
- * .address MAC address of the peer (string)
- * .name the peer's device name (string)
- * .isGroupOwner if the peer is the group owner (boolean)
- * .wpsCapabilities array of the supported |WPSMethod|
- * .connectionStatus one of { "disconnected", "connecting", "connected", "disconnecting" }
- *
- */
- DOMRequest getPeerList();
-
- /**
- * Set pairing confirmation result.
- *
- * @param accepted Boolean to indicate whether we accepted the request or not.
- * @param pin The user input pin number if the wps method is keypad.
- *
- * onsuccess: Command succeeded.
- * onerror: Command failed.
- *
- */
- DOMRequest setPairingConfirmation(boolean accepted, optional DOMString pin);
-
- /**
- * Set device name.
- *
- * @param devieName The new device name we are going to set.
- *
- * onsuccess: Command succeeded.
- * onerror: Command failed.
- *
- */
- DOMRequest setDeviceName(DOMString deviceName);
-
- /**
- * Returns if Wifi Direct is enabled.
- *
- */
- readonly attribute boolean enabled;
-
- /**
- * The current group owner, null if none.
- */
- readonly attribute MozWifiP2pGroupOwner? groupOwner;
-
- /**
- * An event listener that is called whenever the Wifi Direct peer list is
- * updated. Use getPeerList() to get the up-to-date peer list.
- */
- attribute EventHandler onpeerinfoupdate;
-
- /**
- * An event listener that is called whenever Wifi Direct status changed.
- * The address of the changed peer will be stored in event.peerList.
- * See MozWifiP2pStatusChangeEvent.webidl.
- */
- attribute EventHandler onstatuschange;
-
- /**
- * An event listener that is called whenever Wifi Direct is enabled.
- */
- attribute EventHandler onenabled;
-
- /**
- * An event listener that is called whenever Wifi Direct is disabled.
- */
- attribute EventHandler ondisabled;
-};
diff --git a/dom/webidl/MozWifiP2pStatusChangeEvent.webidl b/dom/webidl/MozWifiP2pStatusChangeEvent.webidl
deleted file mode 100644
index be96e2786..000000000
--- a/dom/webidl/MozWifiP2pStatusChangeEvent.webidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-[Constructor(DOMString type, optional MozWifiP2pStatusChangeEventInit eventInitDict),
- Func="Navigator::HasWifiManagerSupport"]
-interface MozWifiP2pStatusChangeEvent : Event
-{
- /**
- * The mac address of the peer whose status has just changed.
- */
- readonly attribute DOMString peerAddress;
-};
-
-dictionary MozWifiP2pStatusChangeEventInit : EventInit
-{
- DOMString peerAddress = "";
-};
diff --git a/dom/webidl/MozWifiStationInfoEvent.webidl b/dom/webidl/MozWifiStationInfoEvent.webidl
deleted file mode 100644
index ff3f5ac6a..000000000
--- a/dom/webidl/MozWifiStationInfoEvent.webidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-[Constructor(DOMString type, optional MozWifiStationInfoEventInit eventInitDict)]
-interface MozWifiStationInfoEvent : Event
-{
- /**
- * The number of wifi stations connected to wifi hotspot.
- */
- readonly attribute short station;
-};
-
-dictionary MozWifiStationInfoEventInit : EventInit
-{
- short station = 0;
-};
diff --git a/dom/webidl/MozWifiStatusChangeEvent.webidl b/dom/webidl/MozWifiStatusChangeEvent.webidl
deleted file mode 100644
index 20d16e4d9..000000000
--- a/dom/webidl/MozWifiStatusChangeEvent.webidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-[Constructor(DOMString type, optional MozWifiStatusChangeEventInit eventInitDict)]
-interface MozWifiStatusChangeEvent : Event
-{
- /**
- * Network object with a SSID field describing the network affected by
- * this change. This might be null.
- */
- readonly attribute any network;
-
- /**
- * String describing the current status of the wifi manager. See above for
- * the possible values.
- */
- readonly attribute DOMString? status;
-};
-
-dictionary MozWifiStatusChangeEventInit : EventInit
-{
- any network = null;
- DOMString status = "";
-};
diff --git a/dom/webidl/Performance.webidl b/dom/webidl/Performance.webidl
index eaede253c..0bd2677df 100644
--- a/dom/webidl/Performance.webidl
+++ b/dom/webidl/Performance.webidl
@@ -17,6 +17,9 @@ typedef sequence <PerformanceEntry> PerformanceEntryList;
interface Performance {
[DependsOn=DeviceState, Affects=Nothing]
DOMHighResTimeStamp now();
+
+ [Constant]
+ readonly attribute DOMHighResTimeStamp timeOrigin;
};
[Exposed=Window]
diff --git a/dom/webidl/PerformanceNavigationTiming.webidl b/dom/webidl/PerformanceNavigationTiming.webidl
new file mode 100644
index 000000000..fa3ecaec4
--- /dev/null
+++ b/dom/webidl/PerformanceNavigationTiming.webidl
@@ -0,0 +1,33 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * https://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming
+ *
+ * Copyright © 2016 W3C® (MIT, ERCIM, Keio, Beihang).
+ * W3C liability, trademark and document use rules apply.
+ */
+
+enum NavigationType {
+ "navigate",
+ "reload",
+ "back_forward",
+ "prerender"
+};
+
+interface PerformanceNavigationTiming : PerformanceResourceTiming {
+ readonly attribute DOMHighResTimeStamp unloadEventStart;
+ readonly attribute DOMHighResTimeStamp unloadEventEnd;
+ readonly attribute DOMHighResTimeStamp domInteractive;
+ readonly attribute DOMHighResTimeStamp domContentLoadedEventStart;
+ readonly attribute DOMHighResTimeStamp domContentLoadedEventEnd;
+ readonly attribute DOMHighResTimeStamp domComplete;
+ readonly attribute DOMHighResTimeStamp loadEventStart;
+ readonly attribute DOMHighResTimeStamp loadEventEnd;
+ readonly attribute NavigationType type;
+ readonly attribute unsigned short redirectCount;
+
+ jsonifier;
+};
diff --git a/dom/webidl/PerformanceObserver.webidl b/dom/webidl/PerformanceObserver.webidl
index a3a14cb1e..4cebecbeb 100644
--- a/dom/webidl/PerformanceObserver.webidl
+++ b/dom/webidl/PerformanceObserver.webidl
@@ -9,6 +9,7 @@
dictionary PerformanceObserverInit {
required sequence<DOMString> entryTypes;
+ boolean buffered = false;
};
callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries, PerformanceObserver observer);
diff --git a/dom/webidl/PerformanceResourceTiming.webidl b/dom/webidl/PerformanceResourceTiming.webidl
index 021b84ae2..112228325 100644
--- a/dom/webidl/PerformanceResourceTiming.webidl
+++ b/dom/webidl/PerformanceResourceTiming.webidl
@@ -4,7 +4,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
- * http://w3c-test.org/webperf/specs/ResourceTiming/#performanceresourcetiming
+ * https://w3c.github.io/resource-timing/#performanceresourcetiming
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
@@ -12,14 +12,10 @@
interface PerformanceResourceTiming : PerformanceEntry
{
- // A string with the name of that element that initiated the load.
- // If the initiator is a CSS resource, the initiatorType attribute must return
- // the string "css".
- // If the initiator is an XMLHttpRequest object, the initiatorType attribute
- // must return the string "xmlhttprequest".
readonly attribute DOMString initiatorType;
readonly attribute DOMString nextHopProtocol;
+ readonly attribute DOMHighResTimeStamp workerStart;
readonly attribute DOMHighResTimeStamp redirectStart;
readonly attribute DOMHighResTimeStamp redirectEnd;
readonly attribute DOMHighResTimeStamp fetchStart;
diff --git a/dom/webidl/PerformanceTiming.webidl b/dom/webidl/PerformanceTiming.webidl
index e14201440..4aa403a50 100644
--- a/dom/webidl/PerformanceTiming.webidl
+++ b/dom/webidl/PerformanceTiming.webidl
@@ -33,5 +33,11 @@ interface PerformanceTiming {
readonly attribute unsigned long long loadEventStart;
readonly attribute unsigned long long loadEventEnd;
+ // This is a Chrome proprietary extension and not part of the
+ // performance/navigation timing specification.
+ // Returns 0 if a non-blank paint has not happened.
+ [Pref="dom.performance.time_to_non_blank_paint.enabled"]
+ readonly attribute unsigned long long timeToNonBlankPaint;
+
jsonifier;
};
diff --git a/dom/webidl/PointerEvent.webidl b/dom/webidl/PointerEvent.webidl
index 2e83922c8..4e8a0eb90 100644
--- a/dom/webidl/PointerEvent.webidl
+++ b/dom/webidl/PointerEvent.webidl
@@ -17,8 +17,10 @@ interface PointerEvent : MouseEvent
readonly attribute long width;
readonly attribute long height;
readonly attribute float pressure;
+ readonly attribute float tangentialPressure;
readonly attribute long tiltX;
readonly attribute long tiltY;
+ readonly attribute long twist;
readonly attribute DOMString pointerType;
readonly attribute boolean isPrimary;
};
@@ -29,8 +31,10 @@ dictionary PointerEventInit : MouseEventInit
long width = 1;
long height = 1;
float pressure = 0;
+ float tangentialPressure = 0;
long tiltX = 0;
long tiltY = 0;
+ long twist = 0;
DOMString pointerType = "";
boolean isPrimary = false;
};
diff --git a/dom/webidl/Response.webidl b/dom/webidl/Response.webidl
index 8713146aa..08f31fe29 100644
--- a/dom/webidl/Response.webidl
+++ b/dom/webidl/Response.webidl
@@ -7,7 +7,7 @@
* https://fetch.spec.whatwg.org/#response-class
*/
-[Constructor(optional BodyInit body, optional ResponseInit init),
+[Constructor(optional BodyInit? body, optional ResponseInit init),
Exposed=(Window,Worker)]
interface Response {
[NewObject] static Response error();
diff --git a/dom/webidl/Selection.webidl b/dom/webidl/Selection.webidl
index c90844dfa..c3eac016c 100644
--- a/dom/webidl/Selection.webidl
+++ b/dom/webidl/Selection.webidl
@@ -33,6 +33,7 @@ interface Selection {
void deleteFromDocument();
readonly attribute unsigned long rangeCount;
+ readonly attribute DOMString type;
[Throws]
Range getRangeAt(unsigned long index);
[Throws]
@@ -77,7 +78,7 @@ partial interface Selection {
void removeSelectionListener(nsISelectionListener listenerToRemove);
[ChromeOnly,BinaryName="rawType"]
- readonly attribute short type;
+ readonly attribute short selectionType;
[ChromeOnly,Throws,Pref="dom.testing.selection.GetRangesForInterval"]
sequence<Range> GetRangesForInterval(Node beginNode, long beginOffset, Node endNode, long endOffset,
diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl
index 36b1f0313..468f1cc8a 100644
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -343,12 +343,6 @@ partial interface Window {
attribute EventHandler onuserproximity;
attribute EventHandler ondevicelight;
-#ifdef MOZ_B2G
- attribute EventHandler onmoztimechange;
- attribute EventHandler onmoznetworkupload;
- attribute EventHandler onmoznetworkdownload;
-#endif
-
void dump(DOMString str);
/**
@@ -385,7 +379,7 @@ Window implements TouchEventHandlers;
Window implements OnErrorEventHandlerForWindow;
-#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#if defined(MOZ_WIDGET_ANDROID)
// https://compat.spec.whatwg.org/#windoworientation-interface
partial interface Window {
[NeedsCallerType]
diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build
index 8682aee97..4c2567a1c 100644
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -347,6 +347,7 @@ WEBIDL_FILES = [
'PerformanceMark.webidl',
'PerformanceMeasure.webidl',
'PerformanceNavigation.webidl',
+ 'PerformanceNavigationTiming.webidl',
'PerformanceObserver.webidl',
'PerformanceObserverEntryList.webidl',
'PerformanceResourceTiming.webidl',
@@ -676,22 +677,9 @@ if CONFIG['MOZ_SECUREELEMENT']:
'SecureElementManager.webidl',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- WEBIDL_FILES += [
- 'MozNetworkStats.webidl',
- 'MozNetworkStatsAlarm.webidl',
- 'MozNetworkStatsData.webidl',
- 'MozNetworkStatsInterface.webidl',
- 'MozNetworkStatsManager.webidl',
- 'MozSpeakerManager.webidl',
- 'MozWifiCapabilities.webidl',
- 'MozWifiManager.webidl',
- 'MozWifiP2pManager.webidl',
- ]
-else:
- WEBIDL_FILES += [
- 'InstallTrigger.webidl',
- ]
+WEBIDL_FILES += [
+ 'InstallTrigger.webidl',
+]
GENERATED_EVENTS_WEBIDL_FILES = [
'AnimationPlaybackEvent.webidl',
@@ -760,14 +748,6 @@ if CONFIG['MOZ_GAMEPAD']:
'GamepadEvent.webidl',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- GENERATED_EVENTS_WEBIDL_FILES += [
- 'MozWifiConnectionInfoEvent.webidl',
- 'MozWifiP2pStatusChangeEvent.webidl',
- 'MozWifiStationInfoEvent.webidl',
- 'MozWifiStatusChangeEvent.webidl',
- ]
-
if CONFIG['MOZ_BUILD_APP'] in ['xulrunner'] or CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_SUITE']:
WEBIDL_FILES += [
'BrowserFeedWriter.webidl',
@@ -778,14 +758,6 @@ if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_FENNEC'] or CONFIG['MOZ_XULRUNNER']:
'External.webidl',
]
-if CONFIG['MOZ_B2G']:
- WEBIDL_FILES += [
- 'MozApplicationEvent.webidl'
- ]
- GENERATED_EVENTS_WEBIDL_FILES += [
- 'MozApplicationEvent.webidl'
- ]
-
if CONFIG['ACCESSIBILITY']:
WEBIDL_FILES += [
'AccessibleNode.webidl',
diff --git a/dom/wifi/DOMWifiManager.js b/dom/wifi/DOMWifiManager.js
deleted file mode 100644
index 8bedfc398..000000000
--- a/dom/wifi/DOMWifiManager.js
+++ /dev/null
@@ -1,543 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-
-const DEBUG = false; // set to false to suppress debug messages
-
-const DOMWIFIMANAGER_CONTRACTID = "@mozilla.org/wifimanager;1";
-const DOMWIFIMANAGER_CID = Components.ID("{c9b5f09e-25d2-40ca-aef4-c4d13d93c706}");
-
-function MozWifiNetwork() {
-}
-
-MozWifiNetwork.prototype = {
-
- init: function(aWindow) {
- this._window = aWindow;
- },
-
- __init: function(obj) {
- for (let key in obj) {
- this[key] = obj[key];
- }
- },
-
- classID: Components.ID("{c01fd751-43c0-460a-8b64-abf652ec7220}"),
- contractID: "@mozilla.org/mozwifinetwork;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
- Ci.nsIDOMGlobalPropertyInitializer])
-};
-
-function MozWifiConnection(obj) {
- this.status = obj.status;
- this.network = obj.network;
-}
-
-MozWifiConnection.prototype = {
- classID: Components.ID("{23579da4-201b-4319-bd42-9b7f337343ac}"),
- contractID: "@mozilla.org/mozwificonnection;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
-};
-
-function MozWifiConnectionInfo(obj) {
- this.signalStrength = obj.signalStrength;
- this.relSignalStrength = obj.relSignalStrength;
- this.linkSpeed = obj.linkSpeed;
- this.ipAddress = obj.ipAddress;
-}
-
-MozWifiConnectionInfo.prototype = {
- classID: Components.ID("{83670352-6ed4-4c35-8de9-402296a1959c}"),
- contractID: "@mozilla.org/mozwificonnectioninfo;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
-}
-
-function MozWifiCapabilities(obj) {
- this.security = obj.security;
- this.eapMethod = obj.eapMethod;
- this.eapPhase2 = obj.eapPhase2;
- this.certificate = obj.certificate;
-}
-
-MozWifiCapabilities.prototype = {
- classID: Components.ID("08c88ece-8092-481b-863b-5515a52e411a"),
- contractID: "@mozilla.org/mozwificapabilities;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
-}
-
-function DOMWifiManager() {
- this.defineEventHandlerGetterSetter("onstatuschange");
- this.defineEventHandlerGetterSetter("onconnectioninfoupdate");
- this.defineEventHandlerGetterSetter("onenabled");
- this.defineEventHandlerGetterSetter("ondisabled");
- this.defineEventHandlerGetterSetter("onstationinfoupdate");
-}
-
-DOMWifiManager.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
- classDescription: "DOMWifiManager",
- classID: DOMWIFIMANAGER_CID,
- contractID: DOMWIFIMANAGER_CONTRACTID,
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver]),
-
- // nsIDOMGlobalPropertyInitializer implementation
- init: function(aWindow) {
- // Maintain this state for synchronous APIs.
- this._currentNetwork = null;
- this._connectionStatus = "disconnected";
- this._enabled = false;
- this._lastConnectionInfo = null;
- this._capabilities = null;
- this._stationNumber = 0;
-
- const messages = ["WifiManager:getNetworks:Return:OK", "WifiManager:getNetworks:Return:NO",
- "WifiManager:getKnownNetworks:Return:OK", "WifiManager:getKnownNetworks:Return:NO",
- "WifiManager:associate:Return:OK", "WifiManager:associate:Return:NO",
- "WifiManager:forget:Return:OK", "WifiManager:forget:Return:NO",
- "WifiManager:wps:Return:OK", "WifiManager:wps:Return:NO",
- "WifiManager:setPowerSavingMode:Return:OK", "WifiManager:setPowerSavingMode:Return:NO",
- "WifiManager:setHttpProxy:Return:OK", "WifiManager:setHttpProxy:Return:NO",
- "WifiManager:setStaticIpMode:Return:OK", "WifiManager:setStaticIpMode:Return:NO",
- "WifiManager:importCert:Return:OK", "WifiManager:importCert:Return:NO",
- "WifiManager:getImportedCerts:Return:OK", "WifiManager:getImportedCerts:Return:NO",
- "WifiManager:deleteCert:Return:OK", "WifiManager:deleteCert:Return:NO",
- "WifiManager:setWifiEnabled:Return:OK", "WifiManager:setWifiEnabled:Return:NO",
- "WifiManager:wifiDown", "WifiManager:wifiUp",
- "WifiManager:onconnecting", "WifiManager:onassociate",
- "WifiManager:onconnect", "WifiManager:ondisconnect",
- "WifiManager:onwpstimeout", "WifiManager:onwpsfail",
- "WifiManager:onwpsoverlap", "WifiManager:connectioninfoupdate",
- "WifiManager:onauthenticating", "WifiManager:onconnectingfailed",
- "WifiManager:stationinfoupdate"];
- this.initDOMRequestHelper(aWindow, messages);
- this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
-
- var state = this._mm.sendSyncMessage("WifiManager:getState")[0];
- if (state) {
- this._currentNetwork = this._convertWifiNetwork(state.network);
- this._lastConnectionInfo = this._convertConnectionInfo(state.connectionInfo);
- this._enabled = state.enabled;
- this._connectionStatus = state.status;
- this._macAddress = state.macAddress;
- this._capabilities = this._convertWifiCapabilities(state.capabilities);
- } else {
- this._currentNetwork = null;
- this._lastConnectionInfo = null;
- this._enabled = false;
- this._connectionStatus = "disconnected";
- this._macAddress = "";
- }
- },
-
- _convertWifiNetworkToJSON: function(aNetwork) {
- let json = {};
-
- for (let key in aNetwork) {
- // In WifiWorker.js there are lots of check using "key in network".
- // So if the value of any property of WifiNetwork is undefined, do not clone it.
- if (aNetwork[key] != undefined) {
- json[key] = aNetwork[key];
- }
- }
- return json;
- },
-
- _convertWifiNetwork: function(aNetwork) {
- let network = aNetwork ? new this._window.MozWifiNetwork(aNetwork) : null;
- return network;
- },
-
- _convertWifiNetworks: function(aNetworks) {
- let networks = new this._window.Array();
- for (let i in aNetworks) {
- networks.push(this._convertWifiNetwork(aNetworks[i]));
- }
- return networks;
- },
-
- _convertConnection: function(aConn) {
- let conn = aConn ? new MozWifiConnection(aConn) : null;
- return conn;
- },
-
- _convertConnectionInfo: function(aInfo) {
- let info = aInfo ? new MozWifiConnectionInfo(aInfo) : null;
- return info;
- },
-
- _convertWifiCapabilities: function(aCapabilities) {
- let capabilities = aCapabilities ?
- new MozWifiCapabilities(aCapabilities) : null;
- return capabilities;
- },
-
- _sendMessageForRequest: function(name, data, request) {
- let id = this.getRequestId(request);
- this._mm.sendAsyncMessage(name, { data: data, rid: id, mid: this._id });
- },
-
- receiveMessage: function(aMessage) {
- let msg = aMessage.json;
- if (msg.mid && msg.mid != this._id)
- return;
-
- let request;
- if (msg.rid) {
- request = this.takeRequest(msg.rid);
- if (!request) {
- return;
- }
- }
-
- switch (aMessage.name) {
- case "WifiManager:setWifiEnabled:Return:OK":
- Services.DOMRequest.fireSuccess(request, msg.data);
- break;
-
- case "WifiManager:setWifiEnabled:Return:NO":
- Services.DOMRequest.fireError(request, "Unable to enable/disable Wifi");
- break;
-
- case "WifiManager:getNetworks:Return:OK":
- Services.DOMRequest.fireSuccess(request, this._convertWifiNetworks(msg.data));
- break;
-
- case "WifiManager:getNetworks:Return:NO":
- Services.DOMRequest.fireError(request, "Unable to scan for networks");
- break;
-
- case "WifiManager:getKnownNetworks:Return:OK":
- Services.DOMRequest.fireSuccess(request, this._convertWifiNetworks(msg.data));
- break;
-
- case "WifiManager:getKnownNetworks:Return:NO":
- Services.DOMRequest.fireError(request, "Unable to get known networks");
- break;
-
- case "WifiManager:associate:Return:OK":
- Services.DOMRequest.fireSuccess(request, true);
- break;
-
- case "WifiManager:associate:Return:NO":
- Services.DOMRequest.fireError(request, "Unable to add the network");
- break;
-
- case "WifiManager:forget:Return:OK":
- Services.DOMRequest.fireSuccess(request, true);
- break;
-
- case "WifiManager:forget:Return:NO":
- Services.DOMRequest.fireError(request, msg.data);
- break;
-
- case "WifiManager:wps:Return:OK":
- Services.DOMRequest.fireSuccess(request, msg.data);
- break;
-
- case "WifiManager:wps:Return:NO":
- Services.DOMRequest.fireError(request, msg.data);
- break;
-
- case "WifiManager:setPowerSavingMode:Return:OK":
- Services.DOMRequest.fireSuccess(request, msg.data);
- break;
-
- case "WifiManager:setPowerSavingMode:Return:NO":
- Services.DOMRequest.fireError(request, msg.data);
- break;
-
- case "WifiManager:setHttpProxy:Return:OK":
- Services.DOMRequest.fireSuccess(request, msg.data);
- break;
-
- case "WifiManager:setHttpProxy:Return:NO":
- Services.DOMRequest.fireError(request, msg.data);
- break;
-
- case "WifiManager:setStaticIpMode:Return:OK":
- Services.DOMRequest.fireSuccess(request, msg.data);
- break;
-
- case "WifiManager:setStaticIpMode:Return:NO":
- Services.DOMRequest.fireError(request, msg.data);
- break;
-
- case "WifiManager:importCert:Return:OK":
- Services.DOMRequest.fireSuccess(request, Cu.cloneInto(msg.data, this._window));
- break;
-
- case "WifiManager:importCert:Return:NO":
- Services.DOMRequest.fireError(request, msg.data);
- break;
-
- case "WifiManager:getImportedCerts:Return:OK":
- Services.DOMRequest.fireSuccess(request, Cu.cloneInto(msg.data, this._window));
- break;
-
- case "WifiManager:getImportedCerts:Return:NO":
- Services.DOMRequest.fireError(request, msg.data);
- break;
-
- case "WifiManager:deleteCert:Return:OK":
- Services.DOMRequest.fireSuccess(request, msg.data);
- break;
-
- case "WifiManager:deleteCert:Return:NO":
- Services.DOMRequest.fireError(request, msg.data);
- break;
-
- case "WifiManager:wifiDown":
- this._enabled = false;
- this._currentNetwork = null;
- this._fireEnabledOrDisabled(false);
- break;
-
- case "WifiManager:wifiUp":
- this._enabled = true;
- this._macAddress = msg.macAddress;
- this._fireEnabledOrDisabled(true);
- break;
-
- case "WifiManager:onconnecting":
- this._currentNetwork = this._convertWifiNetwork(msg.network);
- this._connectionStatus = "connecting";
- this._fireStatusChangeEvent(msg.network);
- break;
-
- case "WifiManager:onassociate":
- this._currentNetwork = this._convertWifiNetwork(msg.network);
- this._connectionStatus = "associated";
- this._fireStatusChangeEvent(msg.network);
- break;
-
- case "WifiManager:onconnect":
- this._currentNetwork = this._convertWifiNetwork(msg.network);
- this._connectionStatus = "connected";
- this._fireStatusChangeEvent(msg.network);
- break;
-
- case "WifiManager:ondisconnect":
- this._currentNetwork = null;
- this._connectionStatus = "disconnected";
- this._lastConnectionInfo = null;
- this._fireStatusChangeEvent(msg.network);
- break;
-
- case "WifiManager:onwpstimeout":
- this._currentNetwork = null;
- this._connectionStatus = "wps-timedout";
- this._lastConnectionInfo = null;
- this._fireStatusChangeEvent(msg.network);
- break;
-
- case "WifiManager:onwpsfail":
- this._currentNetwork = null;
- this._connectionStatus = "wps-failed";
- this._lastConnectionInfo = null;
- this._fireStatusChangeEvent(msg.network);
- break;
-
- case "WifiManager:onwpsoverlap":
- this._currentNetwork = null;
- this._connectionStatus = "wps-overlapped";
- this._lastConnectionInfo = null;
- this._fireStatusChangeEvent(msg.network);
- break;
-
- case "WifiManager:connectioninfoupdate":
- this._lastConnectionInfo = this._convertConnectionInfo(msg);
- this._fireConnectionInfoUpdate(msg);
- break;
- case "WifiManager:onconnectingfailed":
- this._currentNetwork = null;
- this._connectionStatus = "connectingfailed";
- this._lastConnectionInfo = null;
- this._fireStatusChangeEvent(msg.network);
- break;
- case "WifiManager:onauthenticating":
- this._currentNetwork = this._convertWifiNetwork(msg.network);
- this._connectionStatus = "authenticating";
- this._fireStatusChangeEvent(msg.network);
- break;
- case "WifiManager:stationinfoupdate":
- this._stationNumber = msg.station;
- this._fireStationInfoUpdate(msg);
- break;
- }
- },
-
- _fireStatusChangeEvent: function StatusChangeEvent(aNetwork) {
- var event = new this._window.MozWifiStatusChangeEvent("statuschange",
- { network: this._convertWifiNetwork(aNetwork),
- status: this._connectionStatus
- });
- this.__DOM_IMPL__.dispatchEvent(event);
- },
-
- _fireConnectionInfoUpdate: function onConnectionInfoUpdate(info) {
- var evt = new this._window.MozWifiConnectionInfoEvent("connectioninfoupdate",
- { network: this._currentNetwork,
- signalStrength: info.signalStrength,
- relSignalStrength: info.relSignalStrength,
- linkSpeed: info.linkSpeed,
- ipAddress: info.ipAddress,
- });
- this.__DOM_IMPL__.dispatchEvent(evt);
- },
-
- _fireEnabledOrDisabled: function enabledDisabled(enabled) {
- var evt = new this._window.Event(enabled ? "enabled" : "disabled");
- this.__DOM_IMPL__.dispatchEvent(evt);
- },
-
- _fireStationInfoUpdate: function onStationInfoUpdate(info) {
- var evt = new this._window.MozWifiStationInfoEvent("stationinfoupdate",
- { station: this._stationNumber}
- );
- this.__DOM_IMPL__.dispatchEvent(evt);
- },
-
- setWifiEnabled: function setWifiEnabled(enabled) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:setWifiEnabled", enabled, request);
- return request;
- },
-
- getNetworks: function getNetworks() {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:getNetworks", null, request);
- return request;
- },
-
- getKnownNetworks: function getKnownNetworks() {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:getKnownNetworks", null, request);
- return request;
- },
-
- associate: function associate(network) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:associate",
- this._convertWifiNetworkToJSON(network), request);
- return request;
- },
-
- forget: function forget(network) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:forget",
- this._convertWifiNetworkToJSON(network), request);
- return request;
- },
-
- wps: function wps(detail) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:wps", detail, request);
- return request;
- },
-
- setPowerSavingMode: function setPowerSavingMode(enabled) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:setPowerSavingMode", enabled, request);
- return request;
- },
-
- setHttpProxy: function setHttpProxy(network, info) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:setHttpProxy",
- { network: this._convertWifiNetworkToJSON(network), info:info}, request);
- return request;
- },
-
- setStaticIpMode: function setStaticIpMode(network, info) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:setStaticIpMode",
- { network: this._convertWifiNetworkToJSON(network), info: info}, request);
- return request;
- },
-
- importCert: function nsIDOMWifiManager_importCert(certBlob, certPassword, certNickname) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:importCert",
- {
- certBlob: certBlob,
- certPassword: certPassword,
- certNickname: certNickname
- }, request);
- return request;
- },
-
- getImportedCerts: function nsIDOMWifiManager_getImportedCerts() {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:getImportedCerts", null, request);
- return request;
- },
-
- deleteCert: function nsIDOMWifiManager_deleteCert(certNickname) {
- var request = this.createRequest();
- this._sendMessageForRequest("WifiManager:deleteCert",
- {
- certNickname: certNickname
- }, request);
- return request;
- },
-
- get enabled() {
- return this._enabled;
- },
-
- get macAddress() {
- return this._macAddress;
- },
-
- get connection() {
- let _connection = this._convertConnection({ status: this._connectionStatus,
- network: this._currentNetwork,
- });
- return _connection;
- },
-
- get connectionInformation() {
- return this._lastConnectionInfo;
- },
-
- get capabilities() {
- return this._capabilities;
- },
-
- defineEventHandlerGetterSetter: function(name) {
- Object.defineProperty(this, name, {
- get: function() {
- return this.__DOM_IMPL__.getEventHandler(name);
- },
- set: function(handler) {
- this.__DOM_IMPL__.setEventHandler(name, handler);
- }
- });
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
- DOMWifiManager, MozWifiNetwork, MozWifiConnection, MozWifiCapabilities,
- MozWifiConnectionInfo
-]);
-
-var debug;
-if (DEBUG) {
- debug = function (s) {
- dump("-*- DOMWifiManager component: " + s + "\n");
- };
-} else {
- debug = function (s) {};
-}
diff --git a/dom/wifi/DOMWifiManager.manifest b/dom/wifi/DOMWifiManager.manifest
deleted file mode 100644
index 3ba83c1b2..000000000
--- a/dom/wifi/DOMWifiManager.manifest
+++ /dev/null
@@ -1,18 +0,0 @@
-# DOMWifiManager.js
-component {c9b5f09e-25d2-40ca-aef4-c4d13d93c706} DOMWifiManager.js
-contract @mozilla.org/wifimanager;1 {c9b5f09e-25d2-40ca-aef4-c4d13d93c706}
-
-component {c01fd751-43c0-460a-8b64-abf652ec7220} DOMWifiManager.js
-contract @mozilla.org/mozwifinetwork;1 {c01fd751-43c0-460a-8b64-abf652ec7220}
-
-component {23579da4-201b-4319-bd42-9b7f337343ac} DOMWifiManager.js
-contract @mozilla.org/mozwificonnection;1 {23579da4-201b-4319-bd42-9b7f337343ac}
-
-component {83670352-6ed4-4c35-8de9-402296a1959c} DOMWifiManager.js
-contract @mozilla.org/mozwificonnectioninfo;1 {83670352-6ed4-4c35-8de9-402296a1959c}
-
-component {ad5c5295-85fb-4460-8e0c-e130d3f029ab} DOMWifiManager.js
-contract @mozilla.org/mozwificertificateinfo;1 {ad5c5295-85fb-4460-8e0c-e130d3f029ab}
-
-component {08c88ece-8092-481b-863b-5515a52e411a} DOMWifiManager.js
-contract @mozilla.org/mozwificapabilities;1 {08c88ece-8092-481b-863b-5515a52e411a}
diff --git a/dom/wifi/DOMWifiP2pManager.js b/dom/wifi/DOMWifiP2pManager.js
deleted file mode 100644
index 3a5637521..000000000
--- a/dom/wifi/DOMWifiP2pManager.js
+++ /dev/null
@@ -1,328 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-
-const DEBUG = false;
-
-// interface MozWifiP2pGroupOwner implementation.
-
-function MozWifiP2pGroupOwner(aGo) {
- this.groupName = aGo.groupName;
- this.macAddress = aGo.macAddress;
- this.ipAddress = aGo.ipAddress;
- this.passphrase = aGo.passphrase;
- this.ssid = aGo.ssid;
- this.wpsCapabilities = aGo.wpsCapabilities;
- this.freq = aGo.freq;
- this.isLocal = aGo.isLocal;
-}
-
-MozWifiP2pGroupOwner.prototype = {
- classID: Components.ID("{a9b81450-349d-11e3-aa6e-0800200c9a66}"),
- contractID: "@mozilla.org/wifip2pgroupowner;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
-};
-
-// interface MozWifiP2pManager implementation.
-
-const MOZ_WIFIP2PMANAGER_CONTRACTID = "@mozilla.org/wifip2pmanager;1";
-const MOZ_WIFIP2PMANAGER_CID = Components.ID("{8d9125a0-3498-11e3-aa6e-0800200c9a66}");
-
-function MozWifiP2pManager() {
- this.defineEventHandlerGetterSetter("onstatuschange");
- this.defineEventHandlerGetterSetter("onpeerinfoupdate");
- this.defineEventHandlerGetterSetter("onenabled");
- this.defineEventHandlerGetterSetter("ondisabled");
-
- this.currentPeer = null;
- this.enabled = false;
- this.groupOwner = null;
-}
-
-// For smaller, read-only APIs, we expose any property that doesn't begin with
-// an underscore.
-function exposeReadOnly(obj) {
- let exposedProps = {};
- for (let i in obj) {
- if (i[0] === "_") {
- continue;
- }
- exposedProps[i] = "r";
- }
-
- obj.__exposedProps__ = exposedProps;
- return obj;
-}
-
-function debug(msg) {
- if (DEBUG) {
- dump('-------------- MozWifiP2pManager: ' + msg);
- }
-}
-
-MozWifiP2pManager.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
-
- classID: MOZ_WIFIP2PMANAGER_CID,
- contractID: MOZ_WIFIP2PMANAGER_CONTRACTID,
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver,
- Ci.nsISupports]),
-
- //
- // nsIDOMGlobalPropertyInitializer implementation.
- //
-
- init: function(aWindow) {
- const messages = ["WifiP2pManager:setScanEnabled:Return:OK",
- "WifiP2pManager:setScanEnabled:Return:NO",
- "WifiP2pManager:getPeerList:Return:OK",
- "WifiP2pManager:getPeerList:Return:NO",
- "WifiP2pManager:connect:Return:OK",
- "WifiP2pManager:connect:Return:NO",
- "WifiP2pManager:disconnect:Return:OK",
- "WifiP2pManager:disconnect:Return:NO",
- "WifiP2pManager:setPairingConfirmation:Return",
- "WifiP2pManager:setDeviceName:Return:OK",
- "WifiP2pManager:setDeviceName:Return:NO",
-
- "WifiP2pManager:p2pDown",
- "WifiP2pManager:p2pUp",
- "WifiP2pManager:onconnecting",
- "WifiP2pManager:onconnected",
- "WifiP2pManager:ondisconnected",
- "WifiP2pManager:ongroupnstop",
- "WifiP2pManager:onconnectingfailed",
- "WifiP2pManager:onwpstimeout",
- "WifiP2pManager:onwpsfail",
- "WifiP2pManager:onpeerinfoupdate",
- ];
-
- this.initDOMRequestHelper(aWindow, messages);
- this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
-
- // Notify the internal a new DOM mananger is created.
- let state = this._mm.sendSyncMessage("WifiP2pManager:getState")[0];
- if (state) {
- debug('State: ' + JSON.stringify(state));
- this.enabled = state.enabled;
- this.currentPeer = state.currentPeer;
- if (state.groupOwner) {
- this.groupOwner = new MozWifiP2pGroupOwner(state.groupOwner);
- }
- } else {
- debug('Failed to get state');
- }
- },
-
- uninit: function() {
- },
-
- _sendMessageForRequest: function(name, data, request) {
- let id = this.getRequestId(request);
- this._mm.sendAsyncMessage(name, { data: data, rid: id, mid: this._id });
- },
-
- receiveMessage: function(aMessage) {
- let msg = aMessage.json;
- if (msg.mid && msg.mid !== this._id) {
- return;
- }
-
- let request;
- switch (aMessage.name) {
- case "WifiP2pManager:setScanEnabled:Return:OK":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
- break;
-
- case "WifiP2pManager:setScanEnabled:Return:NO":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireError(request, "Unable to enable/disable Wifi P2P peer discovery.");
- break;
-
- case "WifiP2pManager:getPeerList:Return:OK":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireSuccess(request, Cu.cloneInto(msg.data, this._window));
- break;
-
- case "WifiP2pManager:getPeerList:Return:NO":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireError(request, "Unable to disable Wifi P2P peer discovery.");
- break;
-
- case "WifiP2pManager:connect:Return:OK":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
- break;
-
- case "WifiP2pManager:connect:Return:NO":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireError(request, "Unable to connect to Wifi P2P peer.");
- break;
-
- case "WifiP2pManager:disconnect:Return:OK":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
- break;
-
- case "WifiP2pManager:disconnect:Return:NO":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireError(request, "Unable to disconnect to Wifi P2P peer.");
- break;
-
- case "WifiP2pManager:setDeviceName:Return:OK":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
- break;
-
- case "WifiP2pManager:setDeviceName:Return:NO":
- request = this.takeRequest(msg.rid);
- Services.DOMRequest.fireError(request, "Unable to set device name.");
- break;
-
- case "WifiP2pManager:p2pDown":
- this.enabled = false;
- this.currentPeer = null;
- this._fireEnabledOrDisabled(false);
- break;
-
- case "WifiP2pManager:p2pUp":
- this.enabled = true;
- this._fireEnabledOrDisabled(true);
- break;
-
- case "WifiP2pManager:onconnecting":
- debug('onconnecting with peer: ' + JSON.stringify(msg.peer));
- this.currentPeer = msg.peer;
- this._fireStatusChangeEvent(msg.peer.address);
- break;
-
- case "WifiP2pManager:onconnected":
- debug('onconnected with peer: ' + JSON.stringify(msg.peer));
- this.currentPeer = msg.peer;
- this.groupOwner = new MozWifiP2pGroupOwner(msg.groupOwner);
- this._fireStatusChangeEvent(msg.peer.address);
- break;
-
- case "WifiP2pManager:ondisconnected":
- debug('ondisconnected with peer: ' + JSON.stringify(msg.peer));
- this.currentPeer = null;
- this.groupOwner = null;
- this._fireStatusChangeEvent(msg.peer.address);
- break;
-
- case "WifiP2pManager:onconnectingfailed":
- this._fireStatusChangeEvent(null);
- break;
-
- case "WifiP2pManager:onwpstimeout":
- this._fireStatusChangeEvent(null);
- break;
-
- case "WifiP2pManager:onwpsfail":
- this._fireStatusChangeEvent(null);
- break;
-
- case "WifiP2pManager:onpeerinfoupdate":
- this._firePeerInfoUpdateEvent();
- break;
- }
- },
-
- _firePeerInfoUpdateEvent: function PeerInfoUpdate() {
- let evt = new this._window.Event("peerinfoupdate");
- this.__DOM_IMPL__.dispatchEvent(evt);
- },
-
- _fireStatusChangeEvent: function WifiP2pStatusChange(peerAddress) {
- let evt = new this._window.MozWifiP2pStatusChangeEvent("statuschange",
- { peerAddress: peerAddress });
- this.__DOM_IMPL__.dispatchEvent(evt);
- },
-
- _fireEnabledOrDisabled: function enabledDisabled(enabled) {
- let evt = new this._window.Event(enabled ? "enabled" : "disabled");
- this.__DOM_IMPL__.dispatchEvent(evt);
- },
-
- //
- // WifiP2pManager.webidl implementation.
- //
-
- enableScan: function () {
- let request = this.createRequest();
- this._sendMessageForRequest("WifiP2pManager:enableScan", null, request);
- return request;
- },
-
- disableScan: function () {
- let request = this.createRequest();
- this._sendMessageForRequest("WifiP2pManager:disableScan", null, request);
- return request;
- },
-
- setScanEnabled: function(enabled) {
- let request = this.createRequest();
- this._sendMessageForRequest("WifiP2pManager:setScanEnabled", enabled, request);
- return request;
- },
-
- connect: function (address, wpsMethod, goIntent) {
- let request = this.createRequest();
- let connectionInfo = { address: address, wpsMethod: wpsMethod, goIntent: goIntent };
- this._sendMessageForRequest("WifiP2pManager:connect", connectionInfo, request);
- return request;
- },
-
- disconnect: function (address) {
- let request = this.createRequest();
- this._sendMessageForRequest("WifiP2pManager:disconnect", address, request);
- return request;
- },
-
- getPeerList: function () {
- let request = this.createRequest();
- this._sendMessageForRequest("WifiP2pManager:getPeerList", null, request);
- return request;
- },
-
- setPairingConfirmation: function (accepted, pin) {
- let request = this.createRequest();
- let result = { accepted: accepted, pin: pin };
- this._sendMessageForRequest("WifiP2pManager:setPairingConfirmation", result, request);
- return request;
- },
-
- setDeviceName: function(newDeviceName) {
- let request = this.createRequest();
- this._sendMessageForRequest("WifiP2pManager:setDeviceName", newDeviceName, request);
- return request;
- },
-
- // Helpers.
- defineEventHandlerGetterSetter: function(event) {
- Object.defineProperty(this, event, {
- get: function() {
- return this.__DOM_IMPL__.getEventHandler(event);
- },
-
- set: function(handler) {
- this.__DOM_IMPL__.setEventHandler(event, handler);
- }
- });
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozWifiP2pManager, MozWifiP2pGroupOwner]);
diff --git a/dom/wifi/DOMWifiP2pManager.manifest b/dom/wifi/DOMWifiP2pManager.manifest
deleted file mode 100644
index bc80efa48..000000000
--- a/dom/wifi/DOMWifiP2pManager.manifest
+++ /dev/null
@@ -1,6 +0,0 @@
-# DOMWifiP2pManager.js
-component {8d9125a0-3498-11e3-aa6e-0800200c9a66} DOMWifiP2pManager.js
-contract @mozilla.org/wifip2pmanager;1 {8d9125a0-3498-11e3-aa6e-0800200c9a66}
-
-component {a9b81450-349d-11e3-aa6e-0800200c9a66} DOMWifiP2pManager.js
-contract @mozilla.org/wifip2pgroupowner;1 {a9b81450-349d-11e3-aa6e-0800200c9a66} \ No newline at end of file
diff --git a/dom/wifi/StateMachine.jsm b/dom/wifi/StateMachine.jsm
deleted file mode 100644
index 94b876f82..000000000
--- a/dom/wifi/StateMachine.jsm
+++ /dev/null
@@ -1,205 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-
-this.EXPORTED_SYMBOLS = ["StateMachine"];
-
-const DEBUG = false;
-
-this.StateMachine = function(aDebugTag) {
- function debug(aMsg) {
- dump('-------------- StateMachine:' + aDebugTag + ': ' + aMsg);
- }
-
- var sm = {};
-
- var _initialState;
- var _curState;
- var _prevState;
- var _paused;
- var _eventQueue = [];
- var _deferredEventQueue = [];
- var _defaultEventHandler;
-
- // Public interfaces.
-
- sm.setDefaultEventHandler = function(aDefaultEventHandler) {
- _defaultEventHandler = aDefaultEventHandler;
- };
-
- sm.start = function(aInitialState) {
- _initialState = aInitialState;
- sm.gotoState(_initialState);
- };
-
- sm.sendEvent = function (aEvent) {
- if (!_initialState) {
- if (DEBUG) {
- debug('StateMachine is not running. Call StateMachine.start() first.');
- }
- return;
- }
- _eventQueue.push(aEvent);
- asyncCall(handleFirstEvent);
- };
-
- sm.getPreviousState = function() {
- return _prevState;
- };
-
- sm.getCurrentState = function() {
- return _curState;
- };
-
- // State object maker.
- // @param aName string for this state's name.
- // @param aDelegate object:
- // .handleEvent: required.
- // .enter: called before entering this state (optional).
- // .exit: called before exiting this state (optional).
- sm.makeState = function (aName, aDelegate) {
- if (!aDelegate.handleEvent) {
- throw "handleEvent is a required delegate function.";
- }
- var nop = function() {};
- return {
- name: aName,
- enter: (aDelegate.enter || nop),
- exit: (aDelegate.exit || nop),
- handleEvent: aDelegate.handleEvent
- };
- };
-
- sm.deferEvent = function (aEvent) {
- // The definition of a 'deferred event' is:
- // We are not able to handle this event now but after receiving
- // certain event or entering a new state, we might be able to handle
- // it. For example, we couldn't handle CONNECT_EVENT in the
- // diconnecting state. But once we finish doing "disconnecting", we
- // could then handle CONNECT_EVENT!
- //
- // So, the deferred event may be handled in the following cases:
- // 1. Once we entered a new state.
- // 2. Once we handled a regular event.
- if (DEBUG) {
- debug('Deferring event: ' + JSON.stringify(aEvent));
- }
- _deferredEventQueue.push(aEvent);
- };
-
- // Goto the new state. If the current state is null, the exit
- // function won't be called.
- sm.gotoState = function (aNewState) {
- if (_curState) {
- if (DEBUG) {
- debug("exiting state: " + _curState.name);
- }
- _curState.exit();
- }
-
- _prevState = _curState;
- _curState = aNewState;
-
- if (DEBUG) {
- debug("entering state: " + _curState.name);
- }
- _curState.enter();
-
- // We are in the new state now. We got a chance to handle the
- // deferred events.
- handleDeferredEvents();
-
- sm.resume();
- };
-
- // No incoming event will be handled after you call pause().
- // (But they will be queued.)
- sm.pause = function() {
- _paused = true;
- };
-
- // Continue to handle incoming events.
- sm.resume = function() {
- _paused = false;
- asyncCall(handleFirstEvent);
- };
-
- //----------------------------------------------------------
- // Private stuff
- //----------------------------------------------------------
-
- function asyncCall(f) {
- Services.tm.currentThread.dispatch(f, Ci.nsIThread.DISPATCH_NORMAL);
- }
-
- function handleFirstEvent() {
- var hadDeferredEvents;
-
- if (0 === _eventQueue.length) {
- return;
- }
-
- if (_paused) {
- return; // The state machine is paused now.
- }
-
- hadDeferredEvents = _deferredEventQueue.length > 0;
-
- handleOneEvent(_eventQueue.shift()); // The handler may defer this event.
-
- // We've handled one event. If we had deferred events before, now is
- // a good chance to handle them.
- if (hadDeferredEvents) {
- handleDeferredEvents();
- }
-
- // Continue to handle the next regular event.
- handleFirstEvent();
- }
-
- function handleDeferredEvents() {
- if (_deferredEventQueue.length && DEBUG) {
- debug('Handle deferred events: ' + _deferredEventQueue.length);
- }
- for (let i = 0; i < _deferredEventQueue.length; i++) {
- handleOneEvent(_deferredEventQueue.shift());
- }
- }
-
- function handleOneEvent(aEvent)
- {
- if (DEBUG) {
- debug('Handling event: ' + JSON.stringify(aEvent));
- }
-
- var handled = _curState.handleEvent(aEvent);
-
- if (undefined === handled) {
- throw "handleEvent returns undefined: " + _curState.name;
- }
- if (!handled) {
- // Event is not handled in the current state. Try handleEventCommon().
- handled = (_defaultEventHandler ? _defaultEventHandler(aEvent) : handled);
- }
- if (undefined === handled) {
- throw "handleEventCommon returns undefined: " + _curState.name;
- }
- if (!handled) {
- if (DEBUG) {
- debug('!!!!!!!!! FIXME !!!!!!!!! Event not handled: ' + JSON.stringify(aEvent));
- }
- }
-
- return handled;
- }
-
- return sm;
-};
diff --git a/dom/wifi/WifiCertService.cpp b/dom/wifi/WifiCertService.cpp
deleted file mode 100644
index 85e0d2f5b..000000000
--- a/dom/wifi/WifiCertService.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WifiCertService.h"
-
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/EndianUtils.h"
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/dom/File.h"
-#include "mozilla/dom/ToJSValue.h"
-#include "cert.h"
-#include "certdb.h"
-#include "CryptoTask.h"
-#include "nsIDOMBlob.h"
-#include "nsIWifiService.h"
-#include "nsNetUtil.h"
-#include "nsIInputStream.h"
-#include "nsServiceManagerUtils.h"
-#include "nsXULAppAPI.h"
-#include "ScopedNSSTypes.h"
-
-#define NS_WIFICERTSERVICE_CID \
- { 0x83585afd, 0x0e11, 0x43aa, {0x83, 0x46, 0xf3, 0x4d, 0x97, 0x5e, 0x46, 0x77} }
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-namespace mozilla {
-
-// The singleton Wifi Cert service, to be used on the main thread.
-StaticRefPtr<WifiCertService> gWifiCertService;
-
-class ImportCertTask final: public CryptoTask
-{
-public:
- ImportCertTask(int32_t aId, Blob* aCertBlob,
- const nsAString& aCertPassword,
- const nsAString& aCertNickname)
- : mBlob(aCertBlob)
- , mPassword(aCertPassword)
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- mResult.mId = aId;
- mResult.mStatus = 0;
- mResult.mUsageFlag = 0;
- mResult.mNickname = aCertNickname;
- }
-
-private:
- virtual void ReleaseNSSResources() {}
-
- virtual nsresult CalculateResult() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- // read data from blob.
- nsCString blobBuf;
- nsresult rv = ReadBlob(blobBuf);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- char* buf;
- uint32_t size = blobBuf.GetMutableData(&buf);
- if (size == 0) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- // Try import as DER format first.
- rv = ImportDERBlob(buf, size);
- if (NS_SUCCEEDED(rv)) {
- return rv;
- }
-
- // Try import as PKCS#12 format.
- return ImportPKCS12Blob(buf, size, mPassword);
- }
-
- virtual void CallCallback(nsresult rv)
- {
- if (NS_FAILED(rv)) {
- mResult.mStatus = -1;
- }
- gWifiCertService->DispatchResult(mResult);
- }
-
- nsresult ImportDERBlob(char* buf, uint32_t size)
- {
- // Create certificate object.
- ScopedCERTCertificate cert(CERT_DecodeCertFromPackage(buf, size));
- if (!cert) {
- return MapSECStatus(SECFailure);
- }
-
- // Import certificate.
- return ImportCert(cert);
- }
-
- static SECItem*
- HandleNicknameCollision(SECItem* aOldNickname, PRBool* aCancel, void* aWincx)
- {
- const char* dummyName = "Imported User Cert";
- const size_t dummyNameLen = strlen(dummyName);
- SECItem* newNick = ::SECITEM_AllocItem(nullptr, nullptr, dummyNameLen + 1);
- if (!newNick) {
- return nullptr;
- }
-
- newNick->type = siAsciiString;
- // Dummy name, will be renamed later.
- memcpy(newNick->data, dummyName, dummyNameLen + 1);
- newNick->len = dummyNameLen;
-
- return newNick;
- }
-
- static SECStatus
- HandleNicknameUpdate(const CERTCertificate *aCert,
- const SECItem *default_nickname,
- SECItem **new_nickname,
- void *arg)
- {
- WifiCertServiceResultOptions *result = (WifiCertServiceResultOptions *)arg;
-
- nsCString userNickname;
- CopyUTF16toUTF8(result->mNickname, userNickname);
-
- nsCString fullNickname;
- if (aCert->isRoot && (aCert->nsCertType & NS_CERT_TYPE_SSL_CA)) {
- // Accept self-signed SSL CA as server certificate.
- fullNickname.AssignLiteral("WIFI_SERVERCERT_");
- fullNickname += userNickname;
- result->mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_SERVER;
- } else if (aCert->nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
- // User Certificate
- fullNickname.AssignLiteral("WIFI_USERCERT_");
- fullNickname += userNickname;
- result->mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER;
- }
- char* nickname;
- uint32_t length = fullNickname.GetMutableData(&nickname);
-
- SECItem* newNick = ::SECITEM_AllocItem(nullptr, nullptr, length + 1);
- if (!newNick) {
- return SECFailure;
- }
-
- newNick->type = siAsciiString;
- memcpy(newNick->data, nickname, length + 1);
- newNick->len = length;
-
- *new_nickname = newNick;
- return SECSuccess;
- }
-
- nsresult ImportPKCS12Blob(char* buf, uint32_t size, const nsAString& aPassword)
- {
- nsString password(aPassword);
-
- // password is null-terminated wide-char string.
- // passwordItem is required to be big-endian form of password, stored in char
- // array, including the null-termination.
- uint32_t length = password.Length() + 1;
- ScopedSECItem passwordItem(
- ::SECITEM_AllocItem(nullptr, nullptr, length * sizeof(nsString::char_type)));
-
- if (!passwordItem) {
- return NS_ERROR_FAILURE;
- }
-
- mozilla::NativeEndian::copyAndSwapToBigEndian(passwordItem->data,
- password.BeginReading(),
- length);
- // Create a decoder.
- ScopedSEC_PKCS12DecoderContext p12dcx(SEC_PKCS12DecoderStart(
- passwordItem, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr,
- nullptr));
-
- if (!p12dcx) {
- return NS_ERROR_FAILURE;
- }
-
- // Assign data to decorder.
- SECStatus srv = SEC_PKCS12DecoderUpdate(p12dcx,
- reinterpret_cast<unsigned char*>(buf),
- size);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- // Verify certificates.
- srv = SEC_PKCS12DecoderVerify(p12dcx);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- // Set certificate nickname and usage flag.
- srv = SEC_PKCS12DecoderRenameCertNicknames(p12dcx, HandleNicknameUpdate,
- &mResult);
-
- // Validate certificates.
- srv = SEC_PKCS12DecoderValidateBags(p12dcx, HandleNicknameCollision);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- // Initialize slot.
- ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
- if (!slot) {
- return NS_ERROR_FAILURE;
- }
- if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
- srv = PK11_InitPin(slot, "", "");
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
- }
-
- // Import cert and key.
- srv = SEC_PKCS12DecoderImportBags(p12dcx);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- // User certificate must be imported from PKCS#12.
- return (mResult.mUsageFlag & nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER)
- ? NS_OK : NS_ERROR_FAILURE;
- }
-
- nsresult ReadBlob(/*out*/ nsCString& aBuf)
- {
- NS_ENSURE_ARG_POINTER(mBlob);
-
- static const uint64_t MAX_FILE_SIZE = 16384;
-
- ErrorResult rv;
- uint64_t size = mBlob->GetSize(rv);
- if (NS_WARN_IF(rv.Failed())) {
- return rv.StealNSResult();
- }
-
- if (size > MAX_FILE_SIZE) {
- return NS_ERROR_FILE_TOO_BIG;
- }
-
- nsCOMPtr<nsIInputStream> inputStream;
- mBlob->GetInternalStream(getter_AddRefs(inputStream), rv);
- if (NS_WARN_IF(rv.Failed())) {
- return rv.StealNSResult();
- }
-
- rv = NS_ReadInputStreamToString(inputStream, aBuf, (uint32_t)size);
- if (NS_WARN_IF(rv.Failed())) {
- return rv.StealNSResult();
- }
-
- return NS_OK;
- }
-
- nsresult ImportCert(CERTCertificate* aCert)
- {
- nsCString userNickname, fullNickname;
-
- CopyUTF16toUTF8(mResult.mNickname, userNickname);
- // Determine certificate nickname by adding prefix according to its type.
- if (aCert->isRoot && (aCert->nsCertType & NS_CERT_TYPE_SSL_CA)) {
- // Accept self-signed SSL CA as server certificate.
- fullNickname.AssignLiteral("WIFI_SERVERCERT_");
- fullNickname += userNickname;
- mResult.mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_SERVER;
- } else if (aCert->nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
- // User Certificate
- fullNickname.AssignLiteral("WIFI_USERCERT_");
- fullNickname += userNickname;
- mResult.mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER;
- } else {
- return NS_ERROR_ABORT;
- }
-
- char* nickname;
- uint32_t length;
- length = fullNickname.GetMutableData(&nickname);
- if (length == 0) {
- return NS_ERROR_UNEXPECTED;
- }
-
- // Import certificate, duplicated nickname will cause error.
- SECStatus srv = CERT_AddTempCertToPerm(aCert, nickname, nullptr);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- return NS_OK;
- }
-
- RefPtr<Blob> mBlob;
- nsString mPassword;
- WifiCertServiceResultOptions mResult;
-};
-
-class DeleteCertTask final: public CryptoTask
-{
-public:
- DeleteCertTask(int32_t aId, const nsAString& aCertNickname)
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- mResult.mId = aId;
- mResult.mStatus = 0;
- mResult.mUsageFlag = 0;
- mResult.mNickname = aCertNickname;
- }
-
-private:
- virtual void ReleaseNSSResources() {}
-
- virtual nsresult CalculateResult() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCString userNickname;
- CopyUTF16toUTF8(mResult.mNickname, userNickname);
-
- // Delete server certificate.
- nsCString serverCertName("WIFI_SERVERCERT_", 16);
- serverCertName += userNickname;
- nsresult rv = deleteCert(serverCertName);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // Delete user certificate and private key.
- nsCString userCertName("WIFI_USERCERT_", 14);
- userCertName += userNickname;
- rv = deleteCert(userCertName);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- return NS_OK;
- }
-
- nsresult deleteCert(const nsCString &aCertNickname)
- {
- ScopedCERTCertificate cert(
- CERT_FindCertByNickname(CERT_GetDefaultCertDB(), aCertNickname.get())
- );
- // Because we delete certificates in blind, so it's acceptable to delete
- // a non-exist certificate.
- if (!cert) {
- return NS_OK;
- }
-
- ScopedPK11SlotInfo slot(
- PK11_KeyForCertExists(cert, nullptr, nullptr)
- );
-
- SECStatus srv;
- if (slot) {
- // Delete private key along with certificate.
- srv = PK11_DeleteTokenCertAndKey(cert, nullptr);
- } else {
- srv = SEC_DeletePermCertificate(cert);
- }
-
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- return NS_OK;
- }
-
- virtual void CallCallback(nsresult rv)
- {
- if (NS_FAILED(rv)) {
- mResult.mStatus = -1;
- }
- gWifiCertService->DispatchResult(mResult);
- }
-
- WifiCertServiceResultOptions mResult;
-};
-
-NS_IMPL_ISUPPORTS(WifiCertService, nsIWifiCertService)
-
-NS_IMETHODIMP
-WifiCertService::Start(nsIWifiEventListener* aListener)
-{
- MOZ_ASSERT(aListener);
-
- mListener = aListener;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-WifiCertService::Shutdown()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mListener = nullptr;
-
- return NS_OK;
-}
-
-void
-WifiCertService::DispatchResult(const WifiCertServiceResultOptions& aOptions)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mozilla::AutoSafeJSContext cx;
- JS::RootedValue val(cx);
- nsCString dummyInterface;
-
- if (!ToJSValue(cx, aOptions, &val)) {
- return;
- }
-
- // Certll the listener with a JS value.
- mListener->OnCommand(val, dummyInterface);
-}
-
-WifiCertService::WifiCertService()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!gWifiCertService);
-}
-
-WifiCertService::~WifiCertService()
-{
- MOZ_ASSERT(!gWifiCertService);
-
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return;
- }
- shutdown(ShutdownCalledFrom::Object);
-}
-
-already_AddRefed<WifiCertService>
-WifiCertService::FactoryCreate()
-{
- if (!XRE_IsParentProcess()) {
- return nullptr;
- }
-
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!gWifiCertService) {
- gWifiCertService = new WifiCertService();
- ClearOnShutdown(&gWifiCertService);
- }
-
- RefPtr<WifiCertService> service = gWifiCertService.get();
- return service.forget();
-}
-
-NS_IMETHODIMP
-WifiCertService::ImportCert(int32_t aId, nsIDOMBlob* aCertBlob,
- const nsAString& aCertPassword,
- const nsAString& aCertNickname)
-{
- RefPtr<Blob> blob = static_cast<Blob*>(aCertBlob);
- RefPtr<CryptoTask> task = new ImportCertTask(aId, blob, aCertPassword,
- aCertNickname);
- return task->Dispatch("WifiImportCert");
-}
-
-NS_IMETHODIMP
-WifiCertService::DeleteCert(int32_t aId, const nsAString& aCertNickname)
-{
- RefPtr<CryptoTask> task = new DeleteCertTask(aId, aCertNickname);
- return task->Dispatch("WifiDeleteCert");
-}
-
-NS_IMETHODIMP
-WifiCertService::HasPrivateKey(const nsAString& aCertNickname, bool *aHasKey)
-{
- *aHasKey = false;
-
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- nsCString certNickname;
- CopyUTF16toUTF8(aCertNickname, certNickname);
-
- ScopedCERTCertificate cert(
- CERT_FindCertByNickname(CERT_GetDefaultCertDB(), certNickname.get())
- );
- if (!cert) {
- return NS_OK;
- }
-
- ScopedPK11SlotInfo slot(
- PK11_KeyForCertExists(cert, nullptr, nullptr)
- );
- if (slot) {
- *aHasKey = true;
- }
-
- return NS_OK;
-}
-
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WifiCertService,
- WifiCertService::FactoryCreate)
-
-NS_DEFINE_NAMED_CID(NS_WIFICERTSERVICE_CID);
-
-static const mozilla::Module::CIDEntry kWifiCertServiceCIDs[] = {
- { &kNS_WIFICERTSERVICE_CID, false, nullptr, WifiCertServiceConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kWifiCertServiceContracts[] = {
- { "@mozilla.org/wifi/certservice;1", &kNS_WIFICERTSERVICE_CID },
- { nullptr }
-};
-
-static const mozilla::Module kWifiCertServiceModule = {
- mozilla::Module::kVersion,
- kWifiCertServiceCIDs,
- kWifiCertServiceContracts,
- nullptr
-};
-
-} // namespace mozilla
-
-NSMODULE_DEFN(WifiCertServiceModule) = &kWifiCertServiceModule;
diff --git a/dom/wifi/WifiCertService.h b/dom/wifi/WifiCertService.h
deleted file mode 100644
index f542bb0c8..000000000
--- a/dom/wifi/WifiCertService.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef WifiCertService_h
-#define WifiCertService_h
-
-#include "nsIWifiCertService.h"
-#include "nsCOMPtr.h"
-#include "nsNSSShutDown.h"
-#include "nsThread.h"
-#include "mozilla/dom/WifiOptionsBinding.h"
-
-namespace mozilla {
-namespace dom {
-
-class WifiCertService final : public nsIWifiCertService,
- public nsNSSShutDownObject
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIWIFICERTSERVICE
-
- static already_AddRefed<WifiCertService>
- FactoryCreate();
- void DispatchResult(const mozilla::dom::WifiCertServiceResultOptions& aOptions);
-
-private:
- WifiCertService();
- ~WifiCertService();
- virtual void virtualDestroyNSSReference() {};
- nsCOMPtr<nsIWifiEventListener> mListener;
-};
-
-} // namespce dom
-} // namespace mozilla
-
-#endif // WifiCertService_h
diff --git a/dom/wifi/WifiCommand.jsm b/dom/wifi/WifiCommand.jsm
deleted file mode 100644
index 93b0f1a1e..000000000
--- a/dom/wifi/WifiCommand.jsm
+++ /dev/null
@@ -1,594 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["WifiCommand"];
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/systemlibs.js");
-
-const SUPP_PROP = "init.svc.wpa_supplicant";
-const WPA_SUPPLICANT = "wpa_supplicant";
-const DEBUG = false;
-
-this.WifiCommand = function(aControlMessage, aInterface, aSdkVersion) {
- function debug(msg) {
- if (DEBUG) {
- dump('-------------- WifiCommand: ' + msg);
- }
- }
-
- var command = {};
-
- //-------------------------------------------------
- // Utilities.
- //-------------------------------------------------
- command.getSdkVersion = function() {
- return aSdkVersion;
- };
-
- //-------------------------------------------------
- // General commands.
- //-------------------------------------------------
-
- command.loadDriver = function (callback) {
- voidControlMessage("load_driver", function(status) {
- callback(status);
- });
- };
-
- command.unloadDriver = function (callback) {
- voidControlMessage("unload_driver", function(status) {
- callback(status);
- });
- };
-
- command.startSupplicant = function (callback) {
- voidControlMessage("start_supplicant", callback);
- };
-
- command.killSupplicant = function (callback) {
- // It is interesting to note that this function does exactly what
- // wifi_stop_supplicant does. Unforunately, on the Galaxy S2, Samsung
- // changed that function in a way that means that it doesn't recognize
- // wpa_supplicant as already running. Therefore, we have to roll our own
- // version here.
- stopProcess(SUPP_PROP, WPA_SUPPLICANT, callback);
- };
-
- command.terminateSupplicant = function (callback) {
- doBooleanCommand("TERMINATE", "OK", callback);
- };
-
- command.stopSupplicant = function (callback) {
- voidControlMessage("stop_supplicant", callback);
- };
-
- command.listNetworks = function (callback) {
- doStringCommand("LIST_NETWORKS", callback);
- };
-
- command.addNetwork = function (callback) {
- doIntCommand("ADD_NETWORK", callback);
- };
-
- command.setNetworkVariable = function (netId, name, value, callback) {
- doBooleanCommand("SET_NETWORK " + netId + " " + name + " " +
- value, "OK", callback);
- };
-
- command.getNetworkVariable = function (netId, name, callback) {
- doStringCommand("GET_NETWORK " + netId + " " + name, callback);
- };
-
- command.removeNetwork = function (netId, callback) {
- doBooleanCommand("REMOVE_NETWORK " + netId, "OK", callback);
- };
-
- command.enableNetwork = function (netId, disableOthers, callback) {
- doBooleanCommand((disableOthers ? "SELECT_NETWORK " : "ENABLE_NETWORK ") +
- netId, "OK", callback);
- };
-
- command.disableNetwork = function (netId, callback) {
- doBooleanCommand("DISABLE_NETWORK " + netId, "OK", callback);
- };
-
- command.status = function (callback) {
- doStringCommand("STATUS", callback);
- };
-
- command.ping = function (callback) {
- doBooleanCommand("PING", "PONG", callback);
- };
-
- command.scanResults = function (callback) {
- doStringCommand("SCAN_RESULTS", callback);
- };
-
- command.disconnect = function (callback) {
- doBooleanCommand("DISCONNECT", "OK", callback);
- };
-
- command.reconnect = function (callback) {
- doBooleanCommand("RECONNECT", "OK", callback);
- };
-
- command.reassociate = function (callback) {
- doBooleanCommand("REASSOCIATE", "OK", callback);
- };
-
- command.setBackgroundScan = function (enable, callback) {
- doBooleanCommand("SET pno " + (enable ? "1" : "0"),
- "OK",
- function(ok) {
- callback(true, ok);
- });
- };
-
- command.doSetScanMode = function (setActive, callback) {
- doBooleanCommand(setActive ?
- "DRIVER SCAN-ACTIVE" :
- "DRIVER SCAN-PASSIVE", "OK", callback);
- };
-
- command.scan = function (callback) {
- doBooleanCommand("SCAN", "OK", callback);
- };
-
- command.setLogLevel = function (level, callback) {
- doBooleanCommand("LOG_LEVEL " + level, "OK", callback);
- };
-
- command.getLogLevel = function (callback) {
- doStringCommand("LOG_LEVEL", callback);
- };
-
- command.wpsPbc = function (callback, iface) {
- let cmd = 'WPS_PBC';
-
- // If the network interface is specified and we are based on JB,
- // append the argument 'interface=[iface]' to the supplicant command.
- //
- // Note: The argument "interface" is only required for wifi p2p on JB.
- // For other cases, the argument is useless and even leads error.
- // Check the evil work here:
- // http://androidxref.com/4.2.2_r1/xref/external/wpa_supplicant_8/wpa_supplicant/ctrl_iface_unix.c#172
- //
- if (iface && isJellybean()) {
- cmd += (' inferface=' + iface);
- }
-
- doBooleanCommand(cmd, "OK", callback);
- };
-
- command.wpsPin = function (detail, callback) {
- let cmd = 'WPS_PIN ';
-
- // See the comment above in wpsPbc().
- if (detail.iface && isJellybean()) {
- cmd += ('inferface=' + iface + ' ');
- }
-
- cmd += (detail.bssid === undefined ? "any" : detail.bssid);
- cmd += (detail.pin === undefined ? "" : (" " + detail.pin));
-
- doStringCommand(cmd, callback);
- };
-
- command.wpsCancel = function (callback) {
- doBooleanCommand("WPS_CANCEL", "OK", callback);
- };
-
- command.startDriver = function (callback) {
- doBooleanCommand("DRIVER START", "OK");
- };
-
- command.stopDriver = function (callback) {
- doBooleanCommand("DRIVER STOP", "OK");
- };
-
- command.startPacketFiltering = function (callback) {
- var commandChain = ["DRIVER RXFILTER-ADD 0",
- "DRIVER RXFILTER-ADD 1",
- "DRIVER RXFILTER-ADD 3",
- "DRIVER RXFILTER-START"];
-
- doBooleanCommandChain(commandChain, callback);
- };
-
- command.stopPacketFiltering = function (callback) {
- var commandChain = ["DRIVER RXFILTER-STOP",
- "DRIVER RXFILTER-REMOVE 3",
- "DRIVER RXFILTER-REMOVE 1",
- "DRIVER RXFILTER-REMOVE 0"];
-
- doBooleanCommandChain(commandChain, callback);
- };
-
- command.doGetRssi = function (cmd, callback) {
- doCommand(cmd, function(data) {
- var rssi = -200;
-
- if (!data.status) {
- // If we are associating, the reply is "OK".
- var reply = data.reply;
- if (reply !== "OK") {
- // Format is: <SSID> rssi XX". SSID can contain spaces.
- var offset = reply.lastIndexOf("rssi ");
- if (offset !== -1) {
- rssi = reply.substr(offset + 5) | 0;
- }
- }
- }
- callback(rssi);
- });
- };
-
- command.getRssi = function (callback) {
- command.doGetRssi("DRIVER RSSI", callback);
- };
-
- command.getRssiApprox = function (callback) {
- command.doGetRssi("DRIVER RSSI-APPROX", callback);
- };
-
- command.getLinkSpeed = function (callback) {
- doStringCommand("DRIVER LINKSPEED", function(reply) {
- if (reply) {
- reply = reply.split(" ")[1] | 0; // Format: LinkSpeed XX
- }
- callback(reply);
- });
- };
-
- let infoKeys = [{regexp: /RSSI=/i, prop: 'rssi'},
- {regexp: /LINKSPEED=/i, prop: 'linkspeed'}];
-
- command.getConnectionInfoICS = function (callback) {
- doStringCommand("SIGNAL_POLL", function(reply) {
- if (!reply) {
- callback(null);
- return;
- }
-
- // Find any values matching |infoKeys|. This gets executed frequently
- // enough that we want to avoid creating intermediate strings as much as
- // possible.
- let rval = {};
- for (let i = 0; i < infoKeys.length; i++) {
- let re = infoKeys[i].regexp;
- let iKeyStart = reply.search(re);
- if (iKeyStart !== -1) {
- let prop = infoKeys[i].prop;
- let iValueStart = reply.indexOf('=', iKeyStart) + 1;
- let iNewlineAfterValue = reply.indexOf('\n', iValueStart);
- let iValueEnd = iNewlineAfterValue !== -1
- ? iNewlineAfterValue
- : reply.length;
- rval[prop] = reply.substring(iValueStart, iValueEnd) | 0;
- }
- }
-
- callback(rval);
- });
- };
-
- command.getMacAddress = function (callback) {
- doStringCommand("DRIVER MACADDR", function(reply) {
- if (reply) {
- reply = reply.split(" ")[2]; // Format: Macaddr = XX.XX.XX.XX.XX.XX
- }
- callback(reply);
- });
- };
-
- command.connectToHostapd = function(callback) {
- voidControlMessage("connect_to_hostapd", callback);
- };
-
- command.closeHostapdConnection = function(callback) {
- voidControlMessage("close_hostapd_connection", callback);
- };
-
- command.hostapdCommand = function (callback, request) {
- var msg = { cmd: "hostapd_command",
- request: request,
- iface: aInterface };
-
- aControlMessage(msg, function(data) {
- callback(data.status ? null : data.reply);
- });
- };
-
- command.hostapdGetStations = function (callback) {
- var msg = { cmd: "hostapd_get_stations",
- iface: aInterface };
-
- aControlMessage(msg, function(data) {
- callback(data.status);
- });
- };
-
- command.setPowerModeICS = function (mode, callback) {
- doBooleanCommand("DRIVER POWERMODE " + (mode === "AUTO" ? 0 : 1), "OK", callback);
- };
-
- command.setPowerModeJB = function (mode, callback) {
- doBooleanCommand("SET ps " + (mode === "AUTO" ? 1 : 0), "OK", callback);
- };
-
- command.getPowerMode = function (callback) {
- doStringCommand("DRIVER GETPOWER", function(reply) {
- if (reply) {
- reply = (reply.split()[2]|0); // Format: powermode = XX
- }
- callback(reply);
- });
- };
-
- command.setNumAllowedChannels = function (numChannels, callback) {
- doBooleanCommand("DRIVER SCAN-CHANNELS " + numChannels, "OK", callback);
- };
-
- command.getNumAllowedChannels = function (callback) {
- doStringCommand("DRIVER SCAN-CHANNELS", function(reply) {
- if (reply) {
- reply = (reply.split()[2]|0); // Format: Scan-Channels = X
- }
- callback(reply);
- });
- };
-
- command.setBluetoothCoexistenceMode = function (mode, callback) {
- doBooleanCommand("DRIVER BTCOEXMODE " + mode, "OK", callback);
- };
-
- command.setBluetoothCoexistenceScanMode = function (mode, callback) {
- doBooleanCommand("DRIVER BTCOEXSCAN-" + (mode ? "START" : "STOP"),
- "OK", callback);
- };
-
- command.saveConfig = function (callback) {
- // Make sure we never write out a value for AP_SCAN other than 1.
- doBooleanCommand("AP_SCAN 1", "OK", function(ok) {
- doBooleanCommand("SAVE_CONFIG", "OK", callback);
- });
- };
-
- command.reloadConfig = function (callback) {
- doBooleanCommand("RECONFIGURE", "OK", callback);
- };
-
- command.setScanResultHandling = function (mode, callback) {
- doBooleanCommand("AP_SCAN " + mode, "OK", callback);
- };
-
- command.addToBlacklist = function (bssid, callback) {
- doBooleanCommand("BLACKLIST " + bssid, "OK", callback);
- };
-
- command.clearBlacklist = function (callback) {
- doBooleanCommand("BLACKLIST clear", "OK", callback);
- };
-
- command.setSuspendOptimizationsICS = function (enabled, callback) {
- doBooleanCommand("DRIVER SETSUSPENDOPT " + (enabled ? 0 : 1),
- "OK", callback);
- };
-
- command.setSuspendOptimizationsJB = function (enabled, callback) {
- doBooleanCommand("DRIVER SETSUSPENDMODE " + (enabled ? 1 : 0),
- "OK", callback);
- };
-
- command.connectToSupplicant = function(callback) {
- voidControlMessage("connect_to_supplicant", callback);
- };
-
- command.closeSupplicantConnection = function(callback) {
- voidControlMessage("close_supplicant_connection", callback);
- };
-
- command.getMacAddress = function(callback) {
- doStringCommand("DRIVER MACADDR", function(reply) {
- if (reply) {
- reply = reply.split(" ")[2]; // Format: Macaddr = XX.XX.XX.XX.XX.XX
- }
- callback(reply);
- });
- };
-
- command.setDeviceName = function(deviceName, callback) {
- doBooleanCommand("SET device_name " + deviceName, "OK", callback);
- };
-
- //-------------------------------------------------
- // P2P commands.
- //-------------------------------------------------
-
- command.p2pProvDiscovery = function(address, wpsMethod, callback) {
- var command = "P2P_PROV_DISC " + address + " " + wpsMethod;
- doBooleanCommand(command, "OK", callback);
- };
-
- command.p2pConnect = function(config, callback) {
- var command = "P2P_CONNECT " + config.address + " " + config.wpsMethodWithPin + " ";
- if (config.joinExistingGroup) {
- command += "join";
- } else {
- command += "go_intent=" + config.goIntent;
- }
-
- debug('P2P connect command: ' + command);
- doBooleanCommand(command, "OK", callback);
- };
-
- command.p2pGroupRemove = function(iface, callback) {
- debug("groupRemove()");
- doBooleanCommand("P2P_GROUP_REMOVE " + iface, "OK", callback);
- };
-
- command.p2pEnable = function(detail, callback) {
- var commandChain = ["SET device_name " + detail.deviceName,
- "SET device_type " + detail.deviceType,
- "SET config_methods " + detail.wpsMethods,
- "P2P_SET conc_pref sta",
- "P2P_FLUSH"];
-
- doBooleanCommandChain(commandChain, callback);
- };
-
- command.p2pDisable = function(callback) {
- doBooleanCommand("P2P_SET disabled 1", "OK", callback);
- };
-
- command.p2pEnableScan = function(timeout, callback) {
- doBooleanCommand("P2P_FIND " + timeout, "OK", callback);
- };
-
- command.p2pDisableScan = function(callback) {
- doBooleanCommand("P2P_STOP_FIND", "OK", callback);
- };
-
- command.p2pGetGroupCapab = function(address, callback) {
- command.p2pPeer(address, function(reply) {
- debug('p2p_peer reply: ' + reply);
- if (!reply) {
- callback(0);
- return;
- }
- var capab = /group_capab=0x([0-9a-fA-F]+)/.exec(reply)[1];
- if (!capab) {
- callback(0);
- } else {
- callback(parseInt(capab, 16));
- }
- });
- };
-
- command.p2pPeer = function(address, callback) {
- doStringCommand("P2P_PEER " + address, callback);
- };
-
- command.p2pGroupAdd = function(netId, callback) {
- doBooleanCommand("P2P_GROUP_ADD persistent=" + netId, callback);
- };
-
- command.p2pReinvoke = function(netId, address, callback) {
- doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + address, "OK", callback);
- };
-
- //----------------------------------------------------------
- // Private stuff.
- //----------------------------------------------------------
-
- function voidControlMessage(cmd, callback) {
- aControlMessage({ cmd: cmd, iface: aInterface }, function (data) {
- callback(data.status);
- });
- }
-
- function doCommand(request, callback) {
- var msg = { cmd: "command",
- request: request,
- iface: aInterface };
-
- aControlMessage(msg, callback);
- }
-
- function doIntCommand(request, callback) {
- doCommand(request, function(data) {
- callback(data.status ? -1 : (data.reply|0));
- });
- }
-
- function doBooleanCommand(request, expected, callback) {
- doCommand(request, function(data) {
- callback(data.status ? false : (data.reply === expected));
- });
- }
-
- function doStringCommand(request, callback) {
- doCommand(request, function(data) {
- callback(data.status ? null : data.reply);
- });
- }
-
- function doBooleanCommandChain(commandChain, callback, i) {
- if (undefined === i) {
- i = 0;
- }
-
- doBooleanCommand(commandChain[i], "OK", function(ok) {
- if (!ok) {
- return callback(false);
- }
- i++;
- if (i === commandChain.length || !commandChain[i]) {
- // Reach the end or empty command.
- return callback(true);
- }
- doBooleanCommandChain(commandChain, callback, i);
- });
- }
-
- //--------------------------------------------------
- // Helper functions.
- //--------------------------------------------------
-
- function stopProcess(service, process, callback) {
- var count = 0;
- var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- function tick() {
- let result = libcutils.property_get(service);
- if (result === null) {
- callback();
- return;
- }
- if (result === "stopped" || ++count >= 5) {
- // Either we succeeded or ran out of time.
- timer = null;
- callback();
- return;
- }
-
- // Else it's still running, continue waiting.
- timer.initWithCallback(tick, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
- }
-
- setProperty("ctl.stop", process, tick);
- }
-
- // Wrapper around libcutils.property_set that returns true if setting the
- // value was successful.
- // Note that the callback is not called asynchronously.
- function setProperty(key, value, callback) {
- let ok = true;
- try {
- libcutils.property_set(key, value);
- } catch(e) {
- ok = false;
- }
- callback(ok);
- }
-
- function isJellybean() {
- // According to http://developer.android.com/guide/topics/manifest/uses-sdk-element.html
- // ----------------------------------------------------
- // | Platform Version | API Level | VERSION_CODE |
- // ----------------------------------------------------
- // | Android 4.1, 4.1.1 | 16 | JELLY_BEAN_MR2 |
- // | Android 4.2, 4.2.2 | 17 | JELLY_BEAN_MR1 |
- // | Android 4.3 | 18 | JELLY_BEAN |
- // ----------------------------------------------------
- return aSdkVersion === 16 || aSdkVersion === 17 || aSdkVersion === 18;
- }
-
- return command;
-};
diff --git a/dom/wifi/WifiHotspotUtils.cpp b/dom/wifi/WifiHotspotUtils.cpp
deleted file mode 100644
index 5fdb9b76e..000000000
--- a/dom/wifi/WifiHotspotUtils.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WifiHotspotUtils.h"
-#include <dlfcn.h>
-#include <errno.h>
-#include <string.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <cutils/properties.h>
-
-#include "prinit.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/Sprintf.h"
-#include "nsDebug.h"
-#include "nsPrintfCString.h"
-
-static void* sWifiHotspotUtilsLib;
-static PRCallOnceType sInitWifiHotspotUtilsLib;
-// Socket pair used to exit from a blocking read.
-static struct wpa_ctrl* ctrl_conn;
-static const char *ctrl_iface_dir = "/data/misc/wifi/hostapd";
-static char *ctrl_ifname = nullptr;
-
-DEFINE_DLFUNC(wpa_ctrl_open, struct wpa_ctrl*, const char*)
-DEFINE_DLFUNC(wpa_ctrl_close, void, struct wpa_ctrl*)
-DEFINE_DLFUNC(wpa_ctrl_attach, int32_t, struct wpa_ctrl*)
-DEFINE_DLFUNC(wpa_ctrl_detach, int32_t, struct wpa_ctrl*)
-DEFINE_DLFUNC(wpa_ctrl_request, int32_t, struct wpa_ctrl*,
- const char*, size_t cmd_len, char *reply,
- size_t *reply_len, void (*msg_cb)(char *msg, size_t len))
-
-
-static PRStatus
-InitWifiHotspotUtilsLib()
-{
- sWifiHotspotUtilsLib = dlopen("/system/lib/libwpa_client.so", RTLD_LAZY);
- // We might fail to open the hardware lib. That's OK.
- return PR_SUCCESS;
-}
-
-static void*
-GetWifiHotspotLibHandle()
-{
- PR_CallOnce(&sInitWifiHotspotUtilsLib, InitWifiHotspotUtilsLib);
- return sWifiHotspotUtilsLib;
-}
-
-struct wpa_ctrl *
-WifiHotspotUtils::openConnection(const char *ifname)
-{
- if (!ifname) {
- return nullptr;
- }
-
- USE_DLFUNC(wpa_ctrl_open)
- ctrl_conn = wpa_ctrl_open(nsPrintfCString("%s/%s", ctrl_iface_dir, ifname).get());
- return ctrl_conn;
-}
-
-int32_t
-WifiHotspotUtils::sendCommand(struct wpa_ctrl *ctrl, const char *cmd,
- char *reply, size_t *reply_len)
-{
- int32_t ret;
-
- if (!ctrl_conn) {
- NS_WARNING(nsPrintfCString("Not connected to hostapd - \"%s\" command dropped.\n", cmd).get());
- return -1;
- }
-
- USE_DLFUNC(wpa_ctrl_request)
- ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, nullptr);
- if (ret == -2) {
- NS_WARNING(nsPrintfCString("'%s' command timed out.\n", cmd).get());
- return -2;
- } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
- return -1;
- }
-
- // Make the reply printable.
- reply[*reply_len] = '\0';
- if (strncmp(cmd, "STA-FIRST", 9) == 0 ||
- strncmp(cmd, "STA-NEXT", 8) == 0) {
- char *pos = reply;
-
- while (*pos && *pos != '\n')
- pos++;
- *pos = '\0';
- }
-
- return 0;
-}
-
-
-// static
-void*
-WifiHotspotUtils::GetSharedLibrary()
-{
- void* wpaClientLib = GetWifiHotspotLibHandle();
- if (!wpaClientLib) {
- NS_WARNING("No /system/lib/libwpa_client.so");
- }
- return wpaClientLib;
-}
-
-int32_t WifiHotspotUtils::do_wifi_connect_to_hostapd()
-{
- struct dirent *dent;
-
- DIR *dir = opendir(ctrl_iface_dir);
- if (dir) {
- while ((dent = readdir(dir))) {
- if (strcmp(dent->d_name, ".") == 0 ||
- strcmp(dent->d_name, "..") == 0) {
- continue;
- }
- ctrl_ifname = strdup(dent->d_name);
- break;
- }
- closedir(dir);
- }
-
- ctrl_conn = openConnection(ctrl_ifname);
- if (!ctrl_conn) {
- NS_WARNING(nsPrintfCString("Unable to open connection to hostapd on \"%s\": %s",
- ctrl_ifname, strerror(errno)).get());
- return -1;
- }
-
- USE_DLFUNC(wpa_ctrl_attach)
- if (wpa_ctrl_attach(ctrl_conn) != 0) {
- USE_DLFUNC(wpa_ctrl_close)
- wpa_ctrl_close(ctrl_conn);
- ctrl_conn = nullptr;
- return -1;
- }
-
- return 0;
-}
-
-int32_t WifiHotspotUtils::do_wifi_close_hostapd_connection()
-{
- if (!ctrl_conn) {
- NS_WARNING("Invalid ctrl_conn.");
- return -1;
- }
-
- USE_DLFUNC(wpa_ctrl_detach)
- if (wpa_ctrl_detach(ctrl_conn) < 0) {
- NS_WARNING("Failed to detach wpa_ctrl.");
- }
-
- USE_DLFUNC(wpa_ctrl_close)
- wpa_ctrl_close(ctrl_conn);
- ctrl_conn = nullptr;
- return 0;
-}
-
-int32_t WifiHotspotUtils::do_wifi_hostapd_command(const char *command,
- char *reply,
- size_t *reply_len)
-{
- return sendCommand(ctrl_conn, command, reply, reply_len);
-}
-
-int32_t WifiHotspotUtils::do_wifi_hostapd_get_stations()
-{
- char addr[32], cmd[64];
- int stations = 0;
- size_t addrLen = sizeof(addr);
-
- if (sendCommand(ctrl_conn, "STA-FIRST", addr, &addrLen)) {
- return 0;
- }
- stations++;
-
- SprintfLiteral(cmd, "STA-NEXT %s", addr);
- while (sendCommand(ctrl_conn, cmd, addr, &addrLen) == 0) {
- stations++;
- SprintfLiteral(cmd, "STA-NEXT %s", addr);
- }
-
- return stations;
-}
diff --git a/dom/wifi/WifiHotspotUtils.h b/dom/wifi/WifiHotspotUtils.h
deleted file mode 100644
index 7afdec7da..000000000
--- a/dom/wifi/WifiHotspotUtils.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Abstraction on top of the network support from libnetutils that we
- * use to set up network connections.
- */
-
-#ifndef WifiHotspotUtils_h
-#define WifiHotspotUtils_h
-
-// Forward declaration.
-struct wpa_ctrl;
-
-class WifiHotspotUtils
-{
-public:
- static void* GetSharedLibrary();
-
- int32_t do_wifi_connect_to_hostapd();
- int32_t do_wifi_close_hostapd_connection();
- int32_t do_wifi_hostapd_command(const char *command,
- char *reply,
- size_t *reply_len);
- int32_t do_wifi_hostapd_get_stations();
-
-private:
- struct wpa_ctrl * openConnection(const char *ifname);
- int32_t sendCommand(struct wpa_ctrl *ctrl, const char *cmd,
- char *reply, size_t *reply_len);
-};
-
-// Defines a function type with the right arguments and return type.
-#define DEFINE_DLFUNC(name, ret, args...) typedef ret (*FUNC##name)(args);
-
-// Set up a dlsymed function ready to use.
-#define USE_DLFUNC(name) \
- FUNC##name name = (FUNC##name) dlsym(GetSharedLibrary(), #name); \
- if (!name) { \
- MOZ_CRASH("Symbol not found in shared library : " #name); \
- }
-
-#endif // WifiHotspotUtils_h
diff --git a/dom/wifi/WifiNetUtil.jsm b/dom/wifi/WifiNetUtil.jsm
deleted file mode 100644
index 2a1866515..000000000
--- a/dom/wifi/WifiNetUtil.jsm
+++ /dev/null
@@ -1,154 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-this.EXPORTED_SYMBOLS = ["WifiNetUtil"];
-
-const DHCP_PROP = "init.svc.dhcpcd";
-const DHCP = "dhcpcd";
-const DEBUG = false;
-
-this.WifiNetUtil = function(controlMessage) {
- function debug(msg) {
- if (DEBUG) {
- dump('-------------- NetUtil: ' + msg);
- }
- }
-
- var util = {};
-
- util.runDhcp = function (ifname, gen, callback) {
- util.stopDhcp(ifname, function() {
- gNetworkService.dhcpRequest(ifname, function(success, dhcpInfo) {
- util.runIpConfig(ifname, dhcpInfo, function(data) {
- callback(data, gen);
- });
- });
- });
- };
-
- util.stopDhcp = function (ifname, callback) {
- // This function does exactly what dhcp_stop does. Unforunately, if we call
- // this function twice before the previous callback is returned. We may block
- // our self waiting for the callback. It slows down the wifi startup procedure.
- // Therefore, we have to roll our own version here.
- let dhcpService = DHCP_PROP + "_" + ifname;
- let suffix = (ifname.substr(0, 3) === "p2p") ? "p2p" : ifname;
- let processName = DHCP + "_" + suffix;
-
- // The implementation of |dhcp_do_request| would wait until the
- // |result_prop_name| (e.g. dhcp.wlan0.result) to be non-null
- // or 30 second timeout. So we manually change the result property
- // to 'ko' to avoid timeout.
- //
- // http://androidxref.com/4.4.4_r1/xref/system/core/libnetutils/dhcp_utils.c#234
- setProperty('dhcp.' + suffix + '.result', 'ko', function() {
- stopProcess(dhcpService, processName, callback);
- });
- };
-
- util.startDhcpServer = function (config, callback) {
- gNetworkService.setDhcpServer(true, config, function (error) {
- callback(!error);
- });
- };
-
- util.stopDhcpServer = function (callback) {
- gNetworkService.setDhcpServer(false, null, function (error) {
- callback(!error);
- });
- };
-
- util.runIpConfig = function (name, data, callback) {
- if (!data) {
- debug("IP config failed to run");
- callback({ info: data });
- return;
- }
-
- setProperty("net." + name + ".dns1", ipToString(data.dns1),
- function(ok) {
- if (!ok) {
- debug("Unable to set net.<ifname>.dns1");
- return;
- }
- setProperty("net." + name + ".dns2", ipToString(data.dns2),
- function(ok) {
- if (!ok) {
- debug("Unable to set net.<ifname>.dns2");
- return;
- }
- setProperty("net." + name + ".gw", ipToString(data.gateway),
- function(ok) {
- if (!ok) {
- debug("Unable to set net.<ifname>.gw");
- return;
- }
- callback({ info: data });
- });
- });
- });
- };
-
- //--------------------------------------------------
- // Helper functions.
- //--------------------------------------------------
-
- function stopProcess(service, process, callback) {
- var count = 0;
- var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- function tick() {
- let result = libcutils.property_get(service);
- if (result === null) {
- callback();
- return;
- }
- if (result === "stopped" || ++count >= 5) {
- // Either we succeeded or ran out of time.
- timer = null;
- callback();
- return;
- }
-
- // Else it's still running, continue waiting.
- timer.initWithCallback(tick, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
- }
-
- setProperty("ctl.stop", process, tick);
- }
-
- // Wrapper around libcutils.property_set that returns true if setting the
- // value was successful.
- // Note that the callback is not called asynchronously.
- function setProperty(key, value, callback) {
- let ok = true;
- try {
- libcutils.property_set(key, value);
- } catch(e) {
- ok = false;
- }
- callback(ok);
- }
-
- function ipToString(n) {
- return String((n >> 0) & 0xFF) + "." +
- ((n >> 8) & 0xFF) + "." +
- ((n >> 16) & 0xFF) + "." +
- ((n >> 24) & 0xFF);
- }
-
- return util;
-};
diff --git a/dom/wifi/WifiP2pManager.jsm b/dom/wifi/WifiP2pManager.jsm
deleted file mode 100644
index c1b687438..000000000
--- a/dom/wifi/WifiP2pManager.jsm
+++ /dev/null
@@ -1,1649 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/StateMachine.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSysMsgr",
- "@mozilla.org/system-message-internal;1",
- "nsISystemMessagesInternal");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-this.EXPORTED_SYMBOLS = ["WifiP2pManager"];
-
-const EVENT_IGNORED = -1;
-const EVENT_UNKNOWN = -2;
-
-// Events from supplicant for p2p.
-const EVENT_P2P_DEVICE_FOUND = 0;
-const EVENT_P2P_DEVICE_LOST = 1;
-const EVENT_P2P_GROUP_STARTED = 2;
-const EVENT_P2P_GROUP_REMOVED = 3;
-const EVENT_P2P_PROV_DISC_PBC_REQ = 4;
-const EVENT_P2P_PROV_DISC_PBC_RESP = 5;
-const EVENT_P2P_PROV_DISC_SHOW_PIN = 6;
-const EVENT_P2P_PROV_DISC_ENTER_PIN = 7;
-const EVENT_P2P_GO_NEG_REQUEST = 8;
-const EVENT_P2P_GO_NEG_SUCCESS = 9;
-const EVENT_P2P_GO_NEG_FAILURE = 10;
-const EVENT_P2P_GROUP_FORMATION_SUCCESS = 11;
-const EVENT_P2P_GROUP_FORMATION_FAILURE = 12;
-const EVENT_P2P_FIND_STOPPED = 13;
-const EVENT_P2P_INVITATION_RESULT = 14;
-const EVENT_P2P_INVITATION_RECEIVED = 15;
-const EVENT_P2P_PROV_DISC_FAILURE = 16;
-
-// Events from supplicant but not p2p specific.
-const EVENT_AP_STA_DISCONNECTED = 100;
-const EVENT_AP_STA_CONNECTED = 101;
-
-// Events from DOM.
-const EVENT_P2P_SET_PAIRING_CONFIRMATION = 1000;
-const EVENT_P2P_CMD_CONNECT = 1001;
-const EVENT_P2P_CMD_DISCONNECT = 1002;
-const EVENT_P2P_CMD_ENABLE = 1003;
-const EVENT_P2P_CMD_DISABLE = 1004;
-const EVENT_P2P_CMD_ENABLE_SCAN = 1005;
-const EVENT_P2P_CMD_DISABLE_SCAN = 1006;
-const EVENT_P2P_CMD_BLOCK_SCAN = 1007;
-const EVENT_P2P_CMD_UNBLOCK_SCAN = 1008;
-
-// Internal events.
-const EVENT_TIMEOUT_PAIRING_CONFIRMATION = 10000;
-const EVENT_TIMEOUT_NEG_REQ = 10001;
-const EVENT_TIMEOUT_CONNECTING = 10002;
-const EVENT_P2P_ENABLE_SUCCESS = 10003;
-const EVENT_P2P_ENABLE_FAILED = 10004;
-const EVENT_P2P_DISABLE_SUCCESS = 10005;
-
-// WPS method string.
-const WPS_METHOD_PBC = "pbc";
-const WPS_METHOD_DISPLAY = "display";
-const WPS_METHOD_KEYPAD = "keypad";
-
-// Role string.
-const P2P_ROLE_GO = "GO";
-const P2P_ROLE_CLIENT = "client";
-
-// System message for pairing request.
-const PAIRING_REQUEST_SYS_MSG = "wifip2p-pairing-request";
-
-// Configuration.
-const P2P_INTERFACE_NAME = "p2p0";
-const DEFAULT_GO_INTENT = 15;
-const DEFAULT_P2P_DEVICE_NAME = "FirefoxPhone";
-const P2P_SCAN_TIMEOUT_SEC = 120;
-const DEFAULT_P2P_WPS_METHODS = "virtual_push_button physical_display keypad"; // For wpa_supplicant.
-const DEFAULT_P2P_DEVICE_TYPE = "10-0050F204-5"; // For wpa_supplicant.
-
-const GO_NETWORK_INTERFACE = {
- ip: "192.168.2.1",
- maskLength: 24,
- gateway: "192.168.2.1",
- dns1: "0.0.0.0",
- dns2: "0.0.0.0",
- dhcpServer: "192.168.2.1"
-};
-
-const GO_DHCP_SERVER_IP_RANGE = {
- startIp: "192.168.2.10",
- endIp: "192.168.2.30"
-};
-
-var gDebug = false;
-
-// Device Capability bitmap
-const DEVICE_CAPAB_SERVICE_DISCOVERY = 1;
-const DEVICE_CAPAB_CLIENT_DISCOVERABILITY = 1<<1;
-const DEVICE_CAPAB_CONCURRENT_OPER = 1<<2;
-const DEVICE_CAPAB_INFRA_MANAGED = 1<<3;
-const DEVICE_CAPAB_DEVICE_LIMIT = 1<<4;
-const DEVICE_CAPAB_INVITATION_PROCEDURE = 1<<5;
-
-// Group Capability bitmap
-const GROUP_CAPAB_GROUP_OWNER = 1;
-const GROUP_CAPAB_PERSISTENT_GROUP = 1<<1;
-const GROUP_CAPAB_GROUP_LIMIT = 1<<2;
-const GROUP_CAPAB_INTRA_BSS_DIST = 1<<3;
-const GROUP_CAPAB_CROSS_CONN = 1<<4;
-const GROUP_CAPAB_PERSISTENT_RECONN = 1<<5;
-const GROUP_CAPAB_GROUP_FORMATION = 1<<6;
-
-// Constants defined in wpa_supplicants.
-const DEV_PW_REGISTRAR_SPECIFIED = 5;
-const DEV_PW_USER_SPECIFIED = 1;
-const DEV_PW_PUSHBUTTON = 4;
-
-this.WifiP2pManager = function (aP2pCommand, aNetUtil) {
- function debug(aMsg) {
- if (gDebug) {
- dump('-------------- WifiP2pManager: ' + aMsg);
- }
- }
-
- let manager = {};
-
- let _stateMachine = P2pStateMachine(aP2pCommand, aNetUtil);
-
- // Set debug flag to true or false.
- //
- // @param aDebug Boolean to indicate enabling or disabling the debug flag.
- manager.setDebug = function(aDebug) {
- gDebug = aDebug;
- };
-
- // Set observer of observing internal state machine events.
- //
- // @param aObserver Used to notify WifiWorker what's happening
- // in the internal p2p state machine.
- manager.setObserver = function(aObserver) {
- _stateMachine.setObserver(aObserver);
- };
-
- // Handle wpa_supplicant events.
- //
- // @param aEventString string from wpa_supplicant.
- manager.handleEvent = function(aEventString) {
- let event = parseEventString(aEventString);
- if (EVENT_UNKNOWN === event.id || EVENT_IGNORED === event.id) {
- debug('Unknow or ignored event: ' + aEventString);
- return false;
- }
- return _stateMachine.sendEvent(event);
- };
-
- // Set the confirmation of pairing request.
- //
- // @param aResult Object of confirmation result which contains:
- // .accepted: user granted.
- // .pin: pin code which is displaying or input by user.
- // .wpsMethod: string of "pbc" or "display" or "keypad".
- manager.setPairingConfirmation = function(aResult) {
- let event = {
- id: EVENT_P2P_SET_PAIRING_CONFIRMATION,
- info: {
- accepted: aResult.accepted,
- pin: aResult.pin
- }
- };
- _stateMachine.sendEvent(event);
- };
-
- // Connect to a known peer.
- //
- // @param aAddress MAC address of the peer to connect.
- // @param aWpsMethod String of "pbc" or "display" or "keypad".
- // @param aGoIntent Number from 0 to 15.
- // @param aCallback Callback |true| on attempting to connect.
- // |false| on failed to connect.
- manager.connect = function(aAddress, aWpsMethod, aGoIntent, aCallback) {
- let event = {
- id: EVENT_P2P_CMD_CONNECT,
- info: {
- wpsMethod: aWpsMethod,
- address: aAddress,
- goIntent: aGoIntent,
- onDoConnect: aCallback
- }
- };
- _stateMachine.sendEvent(event);
- };
-
- // Disconnect with a known peer.
- //
- // @param aAddress The address the user desires to disconect.
- // @param aCallback Callback |true| on "attempting" to disconnect.
- // |false| on failed to disconnect.
- manager.disconnect = function(aAddress, aCallback) {
- let event = {
- id: EVENT_P2P_CMD_DISCONNECT,
- info: {
- address: aAddress,
- onDoDisconnect: aCallback
- }
- };
- _stateMachine.sendEvent(event);
- };
-
- // Enable/disable wifi p2p.
- //
- // @param aEnabled |true| to enable, |false| to disable.
- // @param aCallbacks object for callbacks:
- // .onEnabled
- // .onDisabled
- // .onSupplicantConnected
- manager.setEnabled = function(aEnabled, aCallbacks) {
- let event = {
- id: (aEnabled ? EVENT_P2P_CMD_ENABLE : EVENT_P2P_CMD_DISABLE),
- info: {
- onEnabled: aCallbacks.onEnabled,
- onDisabled: aCallbacks.onDisabled,
- onSupplicantConnected: aCallbacks.onSupplicantConnected
- }
- };
- _stateMachine.sendEvent(event);
- };
-
- // Enable/disable the wifi p2p scan.
- //
- // @param aEnabled |true| to enable scan, |false| to disable scan.
- // @param aCallback Callback |true| on success to enable/disable scan.
- // |false| on failed to enable/disable scan.
- manager.setScanEnabled = function(aEnabled, aCallback) {
- let event = {
- id: (aEnabled ? EVENT_P2P_CMD_ENABLE_SCAN : EVENT_P2P_CMD_DISABLE_SCAN),
- info: { callback: aCallback }
- };
- _stateMachine.sendEvent(event);
- };
-
- // Block wifi p2p scan.
- manager.blockScan = function() {
- _stateMachine.sendEvent({ id: EVENT_P2P_CMD_BLOCK_SCAN });
- };
-
- // Un-block and do the pending scan if any.
- manager.unblockScan = function() {
- _stateMachine.sendEvent({ id: EVENT_P2P_CMD_UNBLOCK_SCAN });
- };
-
- // Set the p2p device name.
- manager.setDeviceName = function(newDeivceName, callback) {
- aP2pCommand.setDeviceName(newDeivceName, callback);
- };
-
- // Parse wps_supplicant event string.
- //
- // @param aEventString The raw event string from wpa_supplicant.
- //
- // @return Object:
- // .id: a number to represent an event.
- // .info: the additional information carried by this event string.
- function parseEventString(aEventString) {
- if (isIgnoredEvent(aEventString)) {
- return { id: EVENT_IGNORED };
- }
-
- let match = RegExp("p2p_dev_addr=([0-9a-fA-F:]+) " +
- "pri_dev_type=([0-9a-zA-Z-]+) " +
- "name='(.*)' " +
- "config_methods=0x([0-9a-fA-F]+) " +
- "dev_capab=0x([0-9a-fA-F]+) " +
- "group_capab=0x([0-9a-fA-F]+) ").exec(aEventString + ' ');
-
- let tokens = aEventString.split(" ");
-
- let id = EVENT_UNKNOWN;
-
- // general info.
- let info = {};
-
- if (match) {
- info = {
- address: match[1] ? match[1] : null,
- type: match[2] ? match[2] : null,
- name: match[3] ? match[3] : null,
- wpsFlag: match[4] ? parseInt(match[4], 16) : null,
- devFlag: match[5] ? parseInt(match[5], 16) : null,
- groupFlag: match[6] ? parseInt(match[6], 16) : null
- };
- }
-
- if (0 === aEventString.indexOf("P2P-DEVICE-FOUND")) {
- id = EVENT_P2P_DEVICE_FOUND;
- info.wpsCapabilities = wpsFlagToCapabilities(info.wpsFlag);
- info.isGroupOwner = isPeerGroupOwner(info.groupFlag);
- } else if (0 === aEventString.indexOf("P2P-DEVICE-LOST")) {
- // e.g. "P2P-DEVICE-LOST p2p_dev_addr=5e:0a:5b:15:1f:80".
- id = EVENT_P2P_DEVICE_LOST;
- info.address = /p2p_dev_addr=([0-9a-f:]+)/.exec(aEventString)[1];
- } else if (0 === aEventString.indexOf("P2P-GROUP-STARTED")) {
- // e.g. "P2P-GROUP-STARTED wlan0-p2p-0 GO ssid="DIRECT-3F Testing
- // passphrase="12345678" go_dev_addr=02:40:61:c2:f3:b7 [PERSISTENT]".
-
- id = EVENT_P2P_GROUP_STARTED;
- let groupMatch = RegExp('ssid="(.*)" ' +
- 'freq=([0-9]*) ' +
- '(passphrase|psk)=([^ ]+) ' +
- 'go_dev_addr=([0-9a-f:]+)').exec(aEventString);
- info.ssid = groupMatch[1];
- info.freq = groupMatch[2];
- if ('passphrase' === groupMatch[3]) {
- let s = groupMatch[4]; // e.g. "G7jHkkz9".
- info.passphrase = s.substring(1, s.length-1); // Trim the double quote.
- } else { // psk
- info.psk = groupMatch[4];
- }
- info.goAddress = groupMatch[5];
- info.ifname = tokens[1];
- info.role = tokens[2];
- } else if (0 === aEventString.indexOf("P2P-GROUP-REMOVED")) {
- id = EVENT_P2P_GROUP_REMOVED;
- // e.g. "P2P-GROUP-REMOVED wlan0-p2p-0 GO".
- info.ifname = tokens[1];
- info.role = tokens[2];
- } else if (0 === aEventString.indexOf("P2P-PROV-DISC-PBC-REQ")) {
- id = EVENT_P2P_PROV_DISC_PBC_REQ;
- info.wpsMethod = WPS_METHOD_PBC;
- } else if (0 === aEventString.indexOf("P2P-PROV-DISC-PBC-RESP")) {
- id = EVENT_P2P_PROV_DISC_PBC_RESP;
- // The address is different from the general pattern.
- info.address = aEventString.split(" ")[1];
- info.wpsMethod = WPS_METHOD_PBC;
- } else if (0 === aEventString.indexOf("P2P-PROV-DISC-SHOW-PIN")) {
- id = EVENT_P2P_PROV_DISC_SHOW_PIN;
- // Obtain peer address and pin from tokens.
- info.address = tokens[1];
- info.pin = tokens[2];
- info.wpsMethod = WPS_METHOD_DISPLAY;
- } else if (0 === aEventString.indexOf("P2P-PROV-DISC-ENTER-PIN")) {
- id = EVENT_P2P_PROV_DISC_ENTER_PIN;
- // Obtain peer address from tokens.
- info.address = tokens[1];
- info.wpsMethod = WPS_METHOD_KEYPAD;
- } else if (0 === aEventString.indexOf("P2P-GO-NEG-REQUEST")) {
- id = EVENT_P2P_GO_NEG_REQUEST;
- info.address = tokens[1];
- switch (parseInt(tokens[2].split("=")[1], 10)) {
- case DEV_PW_REGISTRAR_SPECIFIED: // (5) Peer is display.
- info.wpsMethod = WPS_METHOD_KEYPAD;
- break;
- case DEV_PW_USER_SPECIFIED: // (1) Peer is keypad.
- info.wpsMethod = WPS_METHOD_DISPLAY;
- break;
- case DEV_PW_PUSHBUTTON: // (4) Peer is pbc.
- info.wpsMethod = WPS_METHOD_PBC;
- break;
- default:
- debug('Unknown wps method from event P2P-GO-NEG-REQUEST');
- break;
- }
- } else if (0 === aEventString.indexOf("P2P-GO-NEG-SUCCESS")) {
- id = EVENT_P2P_GO_NEG_SUCCESS;
- } else if (0 === aEventString.indexOf("P2P-GO-NEG-FAILURE")) {
- id = EVENT_P2P_GO_NEG_FAILURE;
- } else if (0 === aEventString.indexOf("P2P-GROUP-FORMATION-FAILURE")) {
- id = EVENT_P2P_GROUP_FORMATION_FAILURE;
- } else if (0 === aEventString.indexOf("P2P-GROUP-FORMATION-SUCCESS")) {
- id = EVENT_P2P_GROUP_FORMATION_SUCCESS;
- } else if (0 === aEventString.indexOf("P2P-FIND-STOPPED")) {
- id = EVENT_P2P_FIND_STOPPED;
- } else if (0 === aEventString.indexOf("P2P-INVITATION-RESULT")) {
- id = EVENT_P2P_INVITATION_RESULT;
- info.status = /status=([0-9]+)/.exec(aEventString)[1];
- } else if (0 === aEventString.indexOf("P2P-INVITATION-RECEIVED")) {
- // e.g. "P2P-INVITATION-RECEIVED sa=32:85:a9:da:e6:1f persistent=7".
- id = EVENT_P2P_INVITATION_RECEIVED;
- info.address = /sa=([0-9a-f:]+)/.exec(aEventString)[1];
- info.netId = /persistent=([0-9]+)/.exec(aEventString)[1];
- } else if (0 === aEventString.indexOf("P2P-PROV-DISC-FAILURE")) {
- id = EVENT_P2P_PROV_DISC_FAILURE;
- } else {
- // Not P2P event but we do receive it. Try to recognize it.
- if (0 === aEventString.indexOf("AP-STA-DISCONNECTED")) {
- id = EVENT_AP_STA_DISCONNECTED;
- info.address = tokens[1];
- } else if (0 === aEventString.indexOf("AP-STA-CONNECTED")) {
- id = EVENT_AP_STA_CONNECTED;
- info.address = tokens[1];
- } else {
- // Neither P2P event nor recognized supplicant event.
- debug('Unknwon event string: ' + aEventString);
- }
- }
-
- let event = {id: id, info: info};
- debug('Event parsing result: ' + aEventString + ": " + JSON.stringify(event));
-
- return event;
- }
-
- function isIgnoredEvent(aEventString) {
- const IGNORED_EVENTS = [
- "CTRL-EVENT-BSS-ADDED",
- "CTRL-EVENT-BSS-REMOVED",
- "CTRL-EVENT-SCAN-RESULTS",
- "CTRL-EVENT-STATE-CHANGE",
- "WPS-AP-AVAILABLE",
- "WPS-ENROLLEE-SEEN"
- ];
- for(let i = 0; i < IGNORED_EVENTS.length; i++) {
- if (0 === aEventString.indexOf(IGNORED_EVENTS[i])) {
- return true;
- }
- }
- return false;
- }
-
- function isPeerGroupOwner(aGroupFlag) {
- return (aGroupFlag & GROUP_CAPAB_GROUP_OWNER) !== 0;
- }
-
- // Convert flag to a wps capability array.
- //
- // @param aWpsFlag Number that represents the wps capabilities.
- // @return Array of WPS flag.
- function wpsFlagToCapabilities(aWpsFlag) {
- let wpsCapabilities = [];
- if (aWpsFlag & 0x8) {
- wpsCapabilities.push(WPS_METHOD_DISPLAY);
- }
- if (aWpsFlag & 0x80) {
- wpsCapabilities.push(WPS_METHOD_PBC);
- }
- if (aWpsFlag & 0x100) {
- wpsCapabilities.push(WPS_METHOD_KEYPAD);
- }
- return wpsCapabilities;
- }
-
- _stateMachine.start();
- return manager;
-};
-
-function P2pStateMachine(aP2pCommand, aNetUtil) {
- function debug(aMsg) {
- if (gDebug) {
- dump('-------------- WifiP2pStateMachine: ' + aMsg);
- }
- }
-
- let p2pSm = {}; // The state machine to return.
-
- let _sm = StateMachine('WIFIP2P'); // The general purpose state machine.
-
- // Information we need to keep track across states.
- let _observer;
-
- let _onEnabled;
- let _onDisabled;
- let _onSupplicantConnected;
- let _savedConfig = {}; // Configuration used to do P2P_CONNECT.
- let _groupInfo = {}; // The information of the group we have formed.
- let _removedGroupInfo = {}; // Used to store the group info we are going to remove.
-
- let _scanBlocked = false;
- let _scanPostponded = false;
-
- let _localDevice = {
- address: "",
- deviceName: DEFAULT_P2P_DEVICE_NAME + "_" + libcutils.property_get("ro.build.product"),
- wpsCapabilities: [WPS_METHOD_PBC, WPS_METHOD_KEYPAD, WPS_METHOD_DISPLAY]
- };
-
- let _p2pNetworkInterface = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
-
- info: {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]),
-
- state: Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
- type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI_P2P,
- name: P2P_INTERFACE_NAME,
- ips: [],
- prefixLengths: [],
- dnses: [],
- gateways: [],
-
- getAddresses: function (ips, prefixLengths) {
- ips.value = this.ips.slice();
- prefixLengths.value = this.prefixLengths.slice();
-
- return this.ips.length;
- },
-
- getGateways: function (count) {
- if (count) {
- count.value = this.gateways.length;
- }
- return this.gateways.slice();
- },
-
- getDnses: function (count) {
- if (count) {
- count.value = this.dnses.length;
- }
- return this.dnses.slice();
- }
- },
-
- httpProxyHost: null,
- httpProxyPort: null,
-
- // help
- registered: false
- };
-
- //---------------------------------------------------------
- // State machine APIs.
- //---------------------------------------------------------
-
- // Register the observer which is implemented in WifiP2pWorkerObserver.jsm.
- //
- // @param aObserver:
- // .onEnabled
- // .onDisbaled
- // .onPeerFound
- // .onPeerLost
- // .onConnecting
- // .onConnected
- // .onDisconnected
- // .onLocalDeviceChanged
- p2pSm.setObserver = function(aObserver) {
- _observer = aObserver;
- };
-
- p2pSm.start = function() {
- _sm.start(stateDisabled);
- };
-
- p2pSm.sendEvent = function(aEvent) {
- let willBeHandled = isInP2pManagedState(_sm.getCurrentState());
- _sm.sendEvent(aEvent);
- return willBeHandled;
- };
-
- // Initialize internal state machine _sm.
- _sm.setDefaultEventHandler(handleEventCommon);
-
- //----------------------------------------------------------
- // State definition.
- //----------------------------------------------------------
-
- // The initial state.
- var stateDisabled = _sm.makeState("DISABLED", {
- enter: function() {
- _onEnabled = null;
- _onSupplicantConnected = null;
- _savedConfig = null;
- _groupInfo = null;
- _removedGroupInfo = null;
- _scanBlocked = false;
- _scanPostponded = false;
-
- unregisterP2pNetworkInteface();
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_CMD_ENABLE:
- _onEnabled = aEvent.info.onEnabled;
- _onSupplicantConnected = aEvent.info.onSupplicantConnected;
- _sm.gotoState(stateEnabling);
- break;
-
- default:
- return false;
- } // End of switch.
- return true;
- }
- });
-
- // The state where we are trying to enable wifi p2p.
- var stateEnabling = _sm.makeState("ENABLING", {
- enter: function() {
-
- function onFailure()
- {
- _onEnabled(false);
- _observer.onDisabled();
- _sm.gotoState(stateDisabled);
- }
-
- function onSuccess()
- {
- _onEnabled(true);
- _observer.onEnabled();
- _sm.gotoState(stateInactive);
- }
-
- _sm.pause();
-
- // This function will only call back on success.
- function connectToSupplicantIfNeeded(callback) {
- if (aP2pCommand.getSdkVersion() >= 19) {
- // No need to connect to supplicant on KK. Call back directly.
- callback();
- return;
- }
- aP2pCommand.connectToSupplicant(function (status) {
- if (0 !== status) {
- debug('Failed to connect to p2p0');
- onFailure();
- return;
- }
- debug('wpa_supplicant p2p0 connected!');
- _onSupplicantConnected();
- callback();
- });
- }
-
- // Step 1: Connect to p2p0 if needed.
- connectToSupplicantIfNeeded(function callback () {
- let detail;
-
- // Step 2: Get MAC address.
- if (!_localDevice.address) {
- aP2pCommand.getMacAddress(function (address) {
- if (!address) {
- debug('Failed to get MAC address....');
- onFailure();
- return;
- }
- debug('Got mac address: ' + address);
- _localDevice.address = address;
- _observer.onLocalDeviceChanged(_localDevice);
- });
- }
-
- // Step 3: Enable p2p with the device name and wps methods.
- detail = { deviceName: _localDevice.deviceName,
- deviceType: libcutils.property_get("ro.moz.wifi.p2p_device_type") || DEFAULT_P2P_DEVICE_TYPE,
- wpsMethods: libcutils.property_get("ro.moz.wifi.p2p_wps_methods") || DEFAULT_P2P_WPS_METHODS };
-
- aP2pCommand.p2pEnable(detail, function (success) {
- if (!success) {
- debug('Failed to enable p2p');
- onFailure();
- return;
- }
-
- debug('P2P is enabled! Enabling net interface...');
-
- // Step 4: Enable p2p0 net interface. wpa_supplicant may have
- // already done it for us.
- gNetworkService.enableInterface(P2P_INTERFACE_NAME, function (success) {
- onSuccess();
- });
- });
- });
- },
-
- handleEvent: function(aEvent) {
- // We won't receive any event since all of them will be blocked.
- return true;
- }
- });
-
- // The state just after enabling wifi direct.
- var stateInactive = _sm.makeState("INACTIVE", {
- enter: function() {
- registerP2pNetworkInteface();
-
- if (_sm.getPreviousState() !== stateEnabling) {
- _observer.onDisconnected(_savedConfig);
- }
-
- _savedConfig = null; // Used to connect p2p peer.
- _groupInfo = null; // The information of the formed group.
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- // Receiving the following 3 states implies someone is trying to
- // connect to me.
- case EVENT_P2P_PROV_DISC_PBC_REQ:
- case EVENT_P2P_PROV_DISC_SHOW_PIN:
- case EVENT_P2P_PROV_DISC_ENTER_PIN:
- debug('Someone is trying to connect to me: ' + JSON.stringify(aEvent.info));
-
- _savedConfig = {
- name: aEvent.info.name,
- address: aEvent.info.address,
- wpsMethod: aEvent.info.wpsMethod,
- goIntent: DEFAULT_GO_INTENT,
- pin: aEvent.info.pin // EVENT_P2P_PROV_DISC_SHOW_PIN only.
- };
-
- _sm.gotoState(stateWaitingForConfirmation);
- break;
-
- // Connect to a peer.
- case EVENT_P2P_CMD_CONNECT:
- debug('Trying to connect to peer: ' + JSON.stringify(aEvent.info));
-
- _savedConfig = {
- address: aEvent.info.address,
- wpsMethod: aEvent.info.wpsMethod,
- goIntent: aEvent.info.goIntent
- };
-
- _sm.gotoState(stateProvisionDiscovery);
- aEvent.info.onDoConnect(true);
- break;
-
- case EVENT_P2P_INVITATION_RECEIVED:
- _savedConfig = {
- address: aEvent.info.address,
- wpsMethod: WPS_METHOD_PBC,
- goIntent: DEFAULT_GO_INTENT,
- netId: aEvent.info.netId
- };
- _sm.gotoState(stateWaitingForInvitationConfirmation);
- break;
-
- case EVENT_P2P_GROUP_STARTED:
- // Most likely the peer just reinvoked a peristen group and succeeeded.
-
- _savedConfig = { address: aEvent.info.goAddress };
-
- _sm.pause();
- handleGroupStarted(aEvent.info, function (success) {
- _sm.resume();
- });
- break;
-
- case EVENT_AP_STA_DISCONNECTED:
- // We will hit this case when we used to be a group owner and
- // requested to remove the group we owned.
- break;
-
- default:
- return false;
- } // End of switch.
- return true;
- },
- });
-
- // Waiting for user's confirmation.
- var stateWaitingForConfirmation = _sm.makeState("WAITING_FOR_CONFIRMATION", {
- timeoutTimer: null,
-
- enter: function() {
- gSysMsgr.broadcastMessage(PAIRING_REQUEST_SYS_MSG, _savedConfig);
- this.timeoutTimer = initTimeoutTimer(30000, EVENT_TIMEOUT_PAIRING_CONFIRMATION);
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_SET_PAIRING_CONFIRMATION:
- if (!aEvent.info.accepted) {
- debug('User rejected this request');
- _sm.gotoState(stateInactive); // Reset to inactive state.
- break;
- }
-
- debug('User accepted this request');
-
- // The only information we may have to grab from user.
- _savedConfig.pin = aEvent.info.pin;
-
- // The case that user requested to form a group ealier on.
- // Just go to connecting state and do p2p_connect.
- if (_sm.getPreviousState() === stateProvisionDiscovery) {
- _sm.gotoState(stateConnecting);
- break;
- }
-
- // Otherwise, wait for EVENT_P2P_GO_NEG_REQUEST.
- _sm.gotoState(stateWaitingForNegReq);
- break;
-
- case EVENT_TIMEOUT_PAIRING_CONFIRMATION:
- debug('Confirmation timeout!');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_P2P_GO_NEG_REQUEST:
- _sm.deferEvent(aEvent);
- break;
-
- default:
- return false;
- } // End of switch.
-
- return true;
- },
-
- exit: function() {
- this.timeoutTimer.cancel();
- this.timeoutTimer = null;
- }
- });
-
- var stateWaitingForNegReq = _sm.makeState("WAITING_FOR_NEG_REQ", {
- timeoutTimer: null,
-
- enter: function() {
- debug('Wait for EVENT_P2P_GO_NEG_REQUEST');
- this.timeoutTimer = initTimeoutTimer(30000, EVENT_TIMEOUT_NEG_REQ);
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_GO_NEG_REQUEST:
- if (aEvent.info.wpsMethod !== _savedConfig.wpsMethod) {
- debug('Unmatched wps method: ' + aEvent.info.wpsMethod + ", " + _savedConfig.wpsMetho);
- }
- _sm.gotoState(stateConnecting);
- break;
-
- case EVENT_TIMEOUT_NEG_REQ:
- debug("Waiting for NEG-REQ timeout");
- _sm.gotoState(stateInactive);
- break;
-
- default:
- return false;
- } // End of switch.
- return true;
- },
-
- exit: function() {
- this.timeoutTimer.cancel();
- this.timeoutTimer = null;
- }
- });
-
- // Waiting for user's confirmation for invitation.
- var stateWaitingForInvitationConfirmation = _sm.makeState("WAITING_FOR_INV_CONFIRMATION", {
- timeoutTimer: null,
-
- enter: function() {
- gSysMsgr.broadcastMessage(PAIRING_REQUEST_SYS_MSG, _savedConfig);
- this.timeoutTimer = initTimeoutTimer(30000, EVENT_TIMEOUT_PAIRING_CONFIRMATION);
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_SET_PAIRING_CONFIRMATION:
- if (!aEvent.info.accepted) {
- debug('User rejected this request');
- _sm.gotoState(stateInactive); // Reset to inactive state.
- break;
- }
-
- debug('User accepted this request');
- _sm.pause();
- aP2pCommand.p2pGetGroupCapab(_savedConfig.address, function (gc) {
- let isPeeGroupOwner = gc & GROUP_CAPAB_GROUP_OWNER;
- _sm.gotoState(isPeeGroupOwner ? stateGroupAdding : stateReinvoking);
- });
-
- break;
-
- case EVENT_TIMEOUT_PAIRING_CONFIRMATION:
- debug('Confirmation timeout!');
- _sm.gotoState(stateInactive);
- break;
-
- default:
- return false;
- } // End of switch.
-
- return true;
- },
-
- exit: function() {
- this.timeoutTimer.cancel();
- this.timeoutTimer = null;
- }
- });
-
- var stateGroupAdding = _sm.makeState("GROUP_ADDING", {
- timeoutTimer: null,
-
- enter: function() {
- let self = this;
-
- _observer.onConnecting(_savedConfig);
-
- _sm.pause();
- aP2pCommand.p2pGroupAdd(_savedConfig.netId, function (success) {
- if (!success) {
- _sm.gotoState(stateInactive);
- return;
- }
- // Waiting for EVENT_P2P_GROUP_STARTED.
- self.timeoutTimer = initTimeoutTimer(60000, EVENT_TIMEOUT_CONNECTING);
- _sm.resume();
- });
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_GROUP_STARTED:
- _sm.pause();
- handleGroupStarted(aEvent.info, function (success) {
- _sm.resume();
- });
- break;
-
- case EVENT_P2P_GO_NEG_FAILURE:
- debug('Negotiation failure. Go back to inactive state');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_TIMEOUT_CONNECTING:
- debug('Connecting timeout! Go back to inactive state');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_P2P_GROUP_FORMATION_SUCCESS:
- case EVENT_P2P_GO_NEG_SUCCESS:
- break;
-
- case EVENT_P2P_GROUP_FORMATION_FAILURE:
- debug('Group formation failure');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_P2P_GROUP_REMOVED:
- debug('Received P2P-GROUP-REMOVED due to previous failed handleGroupdStarted()');
- _removedGroupInfo = {
- role: aEvent.info.role,
- ifname: aEvent.info.ifname
- };
- _sm.gotoState(stateDisconnecting);
- break;
-
- default:
- return false;
- } // End of switch.
-
- return true;
- },
-
- exit: function() {
- this.timeoutTimer.cancel();
- this.timeoutTimer = null;
- }
- });
-
- var stateReinvoking = _sm.makeState("REINVOKING", {
- timeoutTimer: null,
-
- enter: function() {
- let self = this;
-
- _observer.onConnecting(_savedConfig);
- _sm.pause();
- aP2pCommand.p2pReinvoke(_savedConfig.netId, _savedConfig.address, function(success) {
- if (!success) {
- _sm.gotoState(stateInactive);
- return;
- }
- // Waiting for EVENT_P2P_GROUP_STARTED.
- self.timeoutTimer = initTimeoutTimer(60000, EVENT_TIMEOUT_CONNECTING);
- _sm.resume();
- });
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_GROUP_STARTED:
- _sm.pause();
- handleGroupStarted(aEvent.info, function(success) {
- _sm.resume();
- });
- break;
-
- case EVENT_P2P_GO_NEG_FAILURE:
- debug('Negotiation failure. Go back to inactive state');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_TIMEOUT_CONNECTING:
- debug('Connecting timeout! Go back to inactive state');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_P2P_GROUP_FORMATION_SUCCESS:
- case EVENT_P2P_GO_NEG_SUCCESS:
- break;
-
- case EVENT_P2P_GROUP_FORMATION_FAILURE:
- debug('Group formation failure');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_P2P_GROUP_REMOVED:
- debug('Received P2P-GROUP-REMOVED due to previous failed handleGroupdStarted()');
- _removedGroupInfo = {
- role: aEvent.info.role,
- ifname: aEvent.info.ifname
- };
- _sm.gotoState(stateDisconnecting);
- break;
-
- default:
- return false;
- } // End of switch.
-
- return true;
- },
-
- exit: function() {
- this.timeoutTimer.cancel();
- }
- });
-
- var stateProvisionDiscovery = _sm.makeState("PROVISION_DISCOVERY", {
- enter: function() {
- function onDiscoveryCommandSent(success) {
- if (!success) {
- _sm.gotoState(stateInactive);
- debug('Failed to send p2p_prov_disc. Go back to inactive state.');
- return;
- }
-
- debug('p2p_prov_disc has been sent.');
-
- _sm.resume();
- // Waiting for EVENT_P2P_PROV_DISC_PBC_RESP or
- // EVENT_P2P_PROV_DISC_SHOW_PIN or
- // EVENT_P2P_PROV_DISC_ENTER_PIN.
- }
-
- _sm.pause();
- aP2pCommand.p2pProvDiscovery(_savedConfig.address,
- toPeerWpsMethod(_savedConfig.wpsMethod),
- onDiscoveryCommandSent);
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_PROV_DISC_PBC_RESP:
- _sm.gotoState(stateConnecting); // No need for local user grant.
- break;
- case EVENT_P2P_PROV_DISC_SHOW_PIN:
- case EVENT_P2P_PROV_DISC_ENTER_PIN:
- if (aEvent.info.wpsMethod !== _savedConfig.wpsMethod) {
- debug('Unmatched wps method: ' + aEvent.info.wpsMethod + ":" + _savedConfig.wpsMethod);
- }
- if (EVENT_P2P_PROV_DISC_SHOW_PIN === aEvent.id) {
- _savedConfig.pin = aEvent.info.pin;
- }
- _sm.gotoState(stateWaitingForConfirmation);
- break;
-
- case EVENT_P2P_PROV_DISC_FAILURE:
- _sm.gotoState(stateInactive);
- break;
-
- default:
- return false;
- } // End of switch.
- return true;
- }
- });
-
- // We are going to connect to the peer.
- // |_savedConfig| is supposed to have been filled properly.
- var stateConnecting = _sm.makeState("CONNECTING", {
- timeoutTimer: null,
-
- enter: function() {
- let self = this;
-
- if (null === _savedConfig.goIntent) {
- _savedConfig.goIntent = DEFAULT_GO_INTENT;
- }
-
- _observer.onConnecting(_savedConfig);
-
- let wpsMethodWithPin;
- if (WPS_METHOD_KEYPAD === _savedConfig.wpsMethod ||
- WPS_METHOD_DISPLAY === _savedConfig.wpsMethod) {
- // e.g. '12345678 display or '12345678 keypad'.
- wpsMethodWithPin = (_savedConfig.pin + ' ' + _savedConfig.wpsMethod);
- } else {
- // e.g. 'pbc'.
- wpsMethodWithPin = _savedConfig.wpsMethod;
- }
-
- _sm.pause();
-
- aP2pCommand.p2pGetGroupCapab(_savedConfig.address, function(gc) {
- debug('group capabilities of ' + _savedConfig.address + ': ' + gc);
-
- let isPeerGroupOwner = gc & GROUP_CAPAB_GROUP_OWNER;
- let config = { address: _savedConfig.address,
- wpsMethodWithPin: wpsMethodWithPin,
- goIntent: _savedConfig.goIntent,
- joinExistingGroup: isPeerGroupOwner };
-
- aP2pCommand.p2pConnect(config, function (success) {
- if (!success) {
- debug('Failed to send p2p_connect');
- _sm.gotoState(stateInactive);
- return;
- }
- debug('Waiting for EVENT_P2P_GROUP_STARTED.');
- self.timeoutTimer = initTimeoutTimer(60000, EVENT_TIMEOUT_CONNECTING);
- _sm.resume();
- });
- });
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_GROUP_STARTED:
- _sm.pause();
- handleGroupStarted(aEvent.info, function (success) {
- _sm.resume();
- });
- break;
-
- case EVENT_P2P_GO_NEG_FAILURE:
- debug('Negotiation failure. Go back to inactive state');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_TIMEOUT_CONNECTING:
- debug('Connecting timeout! Go back to inactive state');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_P2P_GROUP_FORMATION_SUCCESS:
- case EVENT_P2P_GO_NEG_SUCCESS:
- break;
-
- case EVENT_P2P_GROUP_FORMATION_FAILURE:
- debug('Group formation failure');
- _sm.gotoState(stateInactive);
- break;
-
- case EVENT_P2P_GROUP_REMOVED:
- debug('Received P2P-GROUP-REMOVED due to previous failed ' +
- 'handleGroupdStarted()');
- _removedGroupInfo = {
- role: aEvent.info.role,
- ifname: aEvent.info.ifname
- };
- _sm.gotoState(stateDisconnecting);
- break;
-
- default:
- return false;
- } // End of switch.
-
- return true;
- },
-
- exit: function() {
- this.timeoutTimer.cancel();
- }
- });
-
- var stateConnected = _sm.makeState("CONNECTED", {
- groupOwner: null,
-
- enter: function() {
- this.groupOwner = {
- macAddress: _groupInfo.goAddress,
- ipAddress: _groupInfo.networkInterface.info.gateways[0],
- passphrase: _groupInfo.passphrase,
- ssid: _groupInfo.ssid,
- freq: _groupInfo.freq,
- isLocal: _groupInfo.isGroupOwner
- };
-
- if (!_groupInfo.isGroupOwner) {
- _observer.onConnected(this.groupOwner, _savedConfig);
- } else {
- // If I am a group owner, notify onConnected until EVENT_AP_STA_CONNECTED
- // is received.
- }
-
- _removedGroupInfo = null;
- },
-
- handleEvent: function(aEvent) {
- switch (aEvent.id) {
- case EVENT_AP_STA_CONNECTED:
- if (_groupInfo.isGroupOwner) {
- _observer.onConnected(this.groupOwner, _savedConfig);
- }
- break;
-
- case EVENT_P2P_GROUP_REMOVED:
- _removedGroupInfo = {
- role: aEvent.info.role,
- ifname: aEvent.info.ifname
- };
- _sm.gotoState(stateDisconnecting);
- break;
-
- case EVENT_AP_STA_DISCONNECTED:
- debug('Client disconnected: ' + aEvent.info.address);
-
- // Now we suppose it's the only client. Remove my group.
- _sm.pause();
- aP2pCommand.p2pGroupRemove(_groupInfo.ifname, function (success) {
- debug('Requested to remove p2p group. Wait for EVENT_P2P_GROUP_REMOVED.');
- _sm.resume();
- });
- break;
-
- case EVENT_P2P_CMD_DISCONNECT:
- // Since we only support single connection, we can ignore
- // the given peer address.
- _sm.pause();
- aP2pCommand.p2pGroupRemove(_groupInfo.ifname, function(success) {
- aEvent.info.onDoDisconnect(true);
- _sm.resume();
- });
-
- debug('Sent disconnect command. Wait for EVENT_P2P_GROUP_REMOVED.');
- break;
-
- case EVENT_P2P_PROV_DISC_PBC_REQ:
- case EVENT_P2P_PROV_DISC_SHOW_PIN:
- case EVENT_P2P_PROV_DISC_ENTER_PIN:
- debug('Someone is trying to connect to me: ' + JSON.stringify(aEvent.info));
-
- _savedConfig = {
- name: aEvent.info.name,
- address: aEvent.info.address,
- wpsMethod: aEvent.info.wpsMethod,
- pin: aEvent.info.pin
- };
-
- _sm.gotoState(stateWaitingForJoiningConfirmation);
- break;
-
- default:
- return false;
- } // end of switch
- return true;
- }
- });
-
- var stateWaitingForJoiningConfirmation = _sm.makeState("WAITING_FOR_JOINING_CONFIRMATION", {
- timeoutTimer: null,
-
- enter: function() {
- gSysMsgr.broadcastMessage(PAIRING_REQUEST_SYS_MSG, _savedConfig);
- this.timeoutTimer = initTimeoutTimer(30000, EVENT_TIMEOUT_PAIRING_CONFIRMATION);
- },
-
- handleEvent: function (aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_SET_PAIRING_CONFIRMATION:
- if (!aEvent.info.accepted) {
- debug('User rejected invitation!');
- _sm.gotoState(stateConnected);
- break;
- }
-
- let onWpsCommandSent = function(success) {
- _observer.onConnecting(_savedConfig);
- _sm.gotoState(stateConnected);
- };
-
- _sm.pause();
- if (WPS_METHOD_PBC === _savedConfig.wpsMethod) {
- aP2pCommand.wpsPbc(onWpsCommandSent, _groupInfo.ifname);
- } else {
- let detail = { pin: _savedConfig.pin, iface: _groupInfo.ifname };
- aP2pCommand.wpsPin(detail, onWpsCommandSent);
- }
- break;
-
- case EVENT_TIMEOUT_PAIRING_CONFIRMATION:
- debug('WAITING_FOR_JOINING_CONFIRMATION timeout!');
- _sm.gotoState(stateConnected);
- break;
-
- default:
- return false;
- } // End of switch.
- return true;
- },
-
- exit: function() {
- this.timeoutTimer.cancel();
- this.timeoutTimer = null;
- }
- });
-
- var stateDisconnecting = _sm.makeState("DISCONNECTING", {
- enter: function() {
- _sm.pause();
- handleGroupRemoved(_removedGroupInfo, function (success) {
- if (!success) {
- debug('Failed to handle group removed event. What can I do?');
- }
- _sm.gotoState(stateInactive);
- });
- },
-
- handleEvent: function(aEvent) {
- return false; // We will not receive any event in this state.
- }
- });
-
- var stateDisabling = _sm.makeState("DISABLING", {
- enter: function() {
- _sm.pause();
- aNetUtil.stopDhcpServer(function (success) { // Stopping DHCP server is harmless.
- debug('Stop DHCP server result: ' + success);
- aP2pCommand.p2pDisable(function(success) {
- debug('P2P function disabled');
- closeSupplicantConnectionIfNeeded(function() {
- debug('Supplicant connection closed');
- gNetworkService.disableInterface(P2P_INTERFACE_NAME, function (success){
- debug('Disabled interface: ' + P2P_INTERFACE_NAME);
- _onDisabled(true);
- _observer.onDisabled();
- _sm.gotoState(stateDisabled);
- });
- });
- });
- });
-
- function closeSupplicantConnectionIfNeeded(callback) {
- // No need to connect to supplicant on KK. Call back directly.
- if (aP2pCommand.getSdkVersion() >= 19) {
- callback();
- return;
- }
- aP2pCommand.closeSupplicantConnection(callback);
- }
- },
-
- handleEvent: function(aEvent) {
- return false; // We will not receive any event in this state.
- }
- });
-
- //----------------------------------------------------------
- // Helper functions.
- //----------------------------------------------------------
-
- // Handle 'P2P_GROUP_STARTED' event. Note that this function
- // will also do the state transitioning and error handling.
- //
- // @param aInfo Information carried by "P2P_GROUP_STARTED" event:
- // .role: P2P_ROLE_GO or P2P_ROLE_CLIENT
- // .ssid:
- // .freq:
- // .passphrase: Used to connect to GO for legacy device.
- // .goAddress:
- // .ifname: e.g. p2p-p2p0
- //
- // @param aCallback Callback function.
- function handleGroupStarted(aInfo, aCallback) {
- debug('handleGroupStarted: ' + JSON.stringify(aInfo));
-
- function onSuccess()
- {
- _sm.gotoState(stateConnected);
- aCallback(true);
- }
-
- function onFailure()
- {
- debug('Failed to handleGroupdStarted(). Remove the group...');
- aP2pCommand.p2pGroupRemove(aInfo.ifname, function (success) {
- aCallback(false);
-
- if (success) {
- return; // Stay in current state and wait for EVENT_P2P_GROUP_REMOVED.
- }
-
- debug('p2pGroupRemove command error!');
- _sm.gotoState(stateInactive);
- });
- }
-
- // Save this group information.
- _groupInfo = aInfo;
- _groupInfo.isGroupOwner = (P2P_ROLE_GO === aInfo.role);
-
- if (_groupInfo.isGroupOwner) {
- debug('Group owner. Start DHCP server');
- let dhcpServerConfig = { ifname: aInfo.ifname,
- startIp: GO_DHCP_SERVER_IP_RANGE.startIp,
- endIp: GO_DHCP_SERVER_IP_RANGE.endIp,
- serverIp: GO_NETWORK_INTERFACE.ip,
- maskLength: GO_NETWORK_INTERFACE.maskLength };
-
- aNetUtil.startDhcpServer(dhcpServerConfig, function (success) {
- if (!success) {
- debug('Failed to start DHCP server');
- onFailure();
- return;
- }
-
- // Update p2p network interface.
- _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
- _p2pNetworkInterface.info.ips = [GO_NETWORK_INTERFACE.ip];
- _p2pNetworkInterface.info.prefixLengths = [GO_NETWORK_INTERFACE.maskLength];
- _p2pNetworkInterface.info.gateways = [GO_NETWORK_INTERFACE.ip];
- handleP2pNetworkInterfaceStateChanged();
-
- _groupInfo.networkInterface = _p2pNetworkInterface;
-
- debug('Everything is done. Happy p2p GO~');
- onSuccess();
- });
-
- return;
- }
-
- // We are the client.
-
- debug("Client. Request IP from DHCP server on interface: " + _groupInfo.ifname);
-
- aNetUtil.runDhcp(aInfo.ifname, 0, function(dhcpData) {
- if(!dhcpData || !dhcpData.info) {
- debug('Failed to run DHCP client');
- onFailure();
- return;
- }
-
- // Save network interface.
- debug("DHCP request success: " + JSON.stringify(dhcpData.info));
-
- // Update p2p network interface.
- let maskLength =
- netHelpers.getMaskLength(netHelpers.stringToIP(dhcpData.info.mask_str));
- if (!maskLength) {
- maskLength = 32; // max prefix for IPv4.
- }
- _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
- _p2pNetworkInterface.info.ips = [dhcpData.info.ipaddr_str];
- _p2pNetworkInterface.info.prefixLengths = [maskLength];
- if (typeof dhcpData.info.dns1_str == "string" &&
- dhcpData.info.dns1_str.length) {
- _p2pNetworkInterface.info.dnses.push(dhcpData.info.dns1_str);
- }
- if (typeof dhcpData.info.dns2_str == "string" &&
- dhcpData.info.dns2_str.length) {
- _p2pNetworkInterface.info.dnses.push(dhcpData.info.dns2_str);
- }
- _p2pNetworkInterface.info.gateways = [dhcpData.info.gateway_str];
- handleP2pNetworkInterfaceStateChanged();
-
- _groupInfo.networkInterface = _p2pNetworkInterface;
-
- debug('Happy p2p client~');
- onSuccess();
- });
- }
-
- function resetP2pNetworkInterface() {
- _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
- _p2pNetworkInterface.info.ips = [];
- _p2pNetworkInterface.info.prefixLengths = [];
- _p2pNetworkInterface.info.dnses = [];
- _p2pNetworkInterface.info.gateways = [];
- }
-
- function registerP2pNetworkInteface() {
- if (!_p2pNetworkInterface.registered) {
- resetP2pNetworkInterface();
- gNetworkManager.registerNetworkInterface(_p2pNetworkInterface);
- _p2pNetworkInterface.registered = true;
- }
- }
-
- function unregisterP2pNetworkInteface() {
- if (_p2pNetworkInterface.registered) {
- resetP2pNetworkInterface();
- gNetworkManager.unregisterNetworkInterface(_p2pNetworkInterface);
- _p2pNetworkInterface.registered = false;
- }
- }
-
- function handleP2pNetworkInterfaceStateChanged() {
- gNetworkManager.updateNetworkInterface(_p2pNetworkInterface);
- }
-
- // Handle 'P2P_GROUP_STARTED' event.
- //
- // @param aInfo information carried by "P2P_GROUP_REMOVED" event:
- // .ifname
- // .role: "GO" or "client".
- //
- // @param aCallback Callback function.
- function handleGroupRemoved(aInfo, aCallback) {
- if (!_groupInfo) {
- debug('No group info. Why?');
- aCallback(true);
- return;
- }
- if (_groupInfo.ifname !== aInfo.ifname ||
- _groupInfo.role !== aInfo.role) {
- debug('Unmatched group info: ' + JSON.stringify(_groupInfo) +
- ' v.s. ' + JSON.stringify(aInfo));
- }
-
- // Update p2p network interface.
- _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
- handleP2pNetworkInterfaceStateChanged();
-
- if (P2P_ROLE_GO === aInfo.role) {
- aNetUtil.stopDhcpServer(function(success) {
- debug('Stop DHCP server result: ' + success);
- aCallback(true);
- });
- } else {
- aNetUtil.stopDhcp(aInfo.ifname, function() {
- aCallback(true);
- });
- }
- }
-
- // Non state-specific event handler.
- function handleEventCommon(aEvent) {
- switch (aEvent.id) {
- case EVENT_P2P_DEVICE_FOUND:
- _observer.onPeerFound(aEvent.info);
- break;
-
- case EVENT_P2P_DEVICE_LOST:
- _observer.onPeerLost(aEvent.info);
- break;
-
- case EVENT_P2P_CMD_DISABLE:
- _onDisabled = aEvent.info.onDisabled;
- _sm.gotoState(stateDisabling);
- break;
-
- case EVENT_P2P_CMD_ENABLE_SCAN:
- if (_scanBlocked) {
- _scanPostponded = true;
- aEvent.info.callback(true);
- break;
- }
- aP2pCommand.p2pEnableScan(P2P_SCAN_TIMEOUT_SEC, aEvent.info.callback);
- break;
-
- case EVENT_P2P_CMD_DISABLE_SCAN:
- aP2pCommand.p2pDisableScan(aEvent.info.callback);
- break;
-
- case EVENT_P2P_FIND_STOPPED:
- break;
-
- case EVENT_P2P_CMD_BLOCK_SCAN:
- _scanBlocked = true;
- aP2pCommand.p2pDisableScan(function(success) {});
- break;
-
- case EVENT_P2P_CMD_UNBLOCK_SCAN:
- _scanBlocked = false;
- if (_scanPostponded) {
- aP2pCommand.p2pEnableScan(P2P_SCAN_TIMEOUT_SEC, function(success) {});
- }
- break;
-
- case EVENT_P2P_CMD_CONNECT:
- case EVENT_P2P_CMD_DISCONNECT:
- debug("The current state couldn't handle connect/disconnect request. Ignore it.");
- break;
-
- default:
- return false;
- } // End of switch.
- return true;
- }
-
- function isInP2pManagedState(aState) {
- let p2pManagedStates = [stateWaitingForConfirmation,
- stateWaitingForNegReq,
- stateProvisionDiscovery,
- stateWaitingForInvitationConfirmation,
- stateGroupAdding,
- stateReinvoking,
- stateConnecting,
- stateConnected,
- stateDisconnecting];
-
- for (let i = 0; i < p2pManagedStates.length; i++) {
- if (aState === p2pManagedStates[i]) {
- return true;
- }
- }
-
- return false;
- }
-
- function initTimeoutTimer(aTimeoutMs, aTimeoutEvent) {
- let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- function onTimerFired() {
- _sm.sendEvent({ id: aTimeoutEvent });
- timer = null;
- }
- timer.initWithCallback(onTimerFired.bind(this), aTimeoutMs,
- Ci.nsITimer.TYPE_ONE_SHOT);
- return timer;
- }
-
- // Converts local WPS method to peer WPS method.
- function toPeerWpsMethod(aLocalWpsMethod) {
- switch (aLocalWpsMethod) {
- case WPS_METHOD_DISPLAY:
- return WPS_METHOD_KEYPAD;
- case WPS_METHOD_KEYPAD:
- return WPS_METHOD_DISPLAY;
- case WPS_METHOD_PBC:
- return WPS_METHOD_PBC;
- default:
- return WPS_METHOD_PBC; // Use "push button" as the default method.
- }
- }
-
- return p2pSm;
-}
-
-this.WifiP2pManager.INTERFACE_NAME = P2P_INTERFACE_NAME;
diff --git a/dom/wifi/WifiP2pWorkerObserver.jsm b/dom/wifi/WifiP2pWorkerObserver.jsm
deleted file mode 100644
index d04e8db5e..000000000
--- a/dom/wifi/WifiP2pWorkerObserver.jsm
+++ /dev/null
@@ -1,319 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-const CONNECTION_STATUS_DISCONNECTED = "disconnected";
-const CONNECTION_STATUS_CONNECTING = "connecting";
-const CONNECTION_STATUS_CONNECTED = "connected";
-const CONNECTION_STATUS_DISCONNECTING = "disconnecting";
-
-const DEBUG = false;
-
-this.EXPORTED_SYMBOLS = ["WifiP2pWorkerObserver"];
-
-// WifiP2pWorkerObserver resides in WifiWorker to handle DOM message
-// by either 1) returning internally maintained information or
-// 2) delegating to aDomMsgResponder. It is also responsible
-// for observing events from WifiP2pManager and dispatch to DOM.
-//
-// @param aDomMsgResponder handles DOM messages, including
-// - setScanEnabled
-// - connect
-// - disconnect
-// - setPairingConfirmation
-// The instance is actually WifiP2pManager.
-this.WifiP2pWorkerObserver = function(aDomMsgResponder) {
- function debug(aMsg) {
- if (DEBUG) {
- dump('-------------- WifiP2pWorkerObserver: ' + aMsg);
- }
- }
-
- // Private member variables.
- let _localDevice;
- let _peerList = {}; // List of P2pDevice.
- let _domManagers = [];
- let _enabled = false;
- let _groupOwner = null;
- let _currentPeer = null;
-
- // Constructor of P2pDevice. It will be exposed to DOM.
- //
- // @param aPeer object representing a P2P device:
- // .name: string for the device name.
- // .address: Mac address.
- // .isGroupOwner: boolean to indicate if this device is the group owner.
- // .wpsCapabilities: array of string of {"pbc", "display", "keypad"}.
- function P2pDevice(aPeer) {
- this.address = aPeer.address;
- this.name = (aPeer.name ? aPeer.name : aPeer.address);
- this.isGroupOwner = aPeer.isGroupOwner;
- this.wpsCapabilities = aPeer.wpsCapabilities;
- this.connectionStatus = CONNECTION_STATUS_DISCONNECTED;
-
- // Since this object will be exposed to web, defined the exposed
- // properties here.
- this.__exposedProps__ = {
- address: "r",
- name: "r",
- isGroupOwner: "r",
- wpsCapabilities: "r",
- connectionStatus: "r"
- };
- }
-
- // Constructor of P2pGroupOwner.
- //
- // @param aGroupOwner:
- // .macAddress
- // .ipAddress
- // .passphrase
- // .ssid
- // .freq
- // .isLocal
- function P2pGroupOwner(aGroupOwner) {
- this.macAddress = aGroupOwner.macAddress; // The identifier to get further information.
- this.ipAddress = aGroupOwner.ipAddress;
- this.passphrase = aGroupOwner.passphrase;
- this.ssid = aGroupOwner.ssid; // e.g. DIRECT-xy.
- this.freq = aGroupOwner.freq;
- this.isLocal = aGroupOwner.isLocal;
-
- let detail = _peerList[aGroupOwner.macAddress];
- if (detail) {
- this.name = detail.name;
- this.wpsCapabilities = detail.wpsCapabilities;
- } else if (_localDevice.address === this.macAddress) {
- this.name = _localDevice.name;
- this.wpsCapabilities = _localDevice.wpsCapabilities;
- } else {
- debug("We don't know this group owner: " + aGroupOwner.macAddress);
- this.name = aGroupOwner.macAddress;
- this.wpsCapabilities = [];
- }
- }
-
- function fireEvent(aMessage, aData) {
- debug('domManager: ' + JSON.stringify(_domManagers));
- _domManagers.forEach(function(manager) {
- // Note: We should never have a dead message manager here because we
- // observe our child message managers shutting down below.
- manager.sendAsyncMessage("WifiP2pManager:" + aMessage, aData);
- });
- }
-
- function addDomManager(aMsg) {
- if (-1 === _domManagers.indexOf(aMsg.manager)) {
- _domManagers.push(aMsg.manager);
- }
- }
-
- function returnMessage(aMessage, aSuccess, aData, aMsg) {
- let rMsg = aMessage + ":Return:" + (aSuccess ? "OK" : "NO");
- aMsg.manager.sendAsyncMessage(rMsg,
- { data: aData, rid: aMsg.rid, mid: aMsg.mid });
- }
-
- function handlePeerListUpdated() {
- fireEvent("onpeerinfoupdate", {});
- }
-
- // Return a literal object as the constructed object.
- return {
- onLocalDeviceChanged: function(aDevice) {
- _localDevice = aDevice;
- debug('Local device updated to: ' + JSON.stringify(_localDevice));
- },
-
- onEnabled: function() {
- _peerList = [];
- _enabled = true;
- fireEvent("p2pUp", {});
- },
-
- onDisbaled: function() {
- _enabled = false;
- fireEvent("p2pDown", {});
- },
-
- onPeerFound: function(aPeer) {
- let newFoundPeer = new P2pDevice(aPeer);
- let origianlPeer = _peerList[aPeer.address];
- _peerList[aPeer.address] = newFoundPeer;
- if (origianlPeer) {
- newFoundPeer.connectionStatus = origianlPeer.connectionStatus;
- }
- handlePeerListUpdated();
- },
-
- onPeerLost: function(aPeer) {
- let lostPeer = _peerList[aPeer.address];
- if (!lostPeer) {
- debug('Unknown peer lost: ' + aPeer.address);
- return;
- }
- delete _peerList[aPeer.address];
- handlePeerListUpdated();
- },
-
- onConnecting: function(aPeer) {
- let peer = _peerList[aPeer.address];
- if (!peer) {
- debug('Unknown peer connecting: ' + aPeer.address);
- peer = new P2pDevice(aPeer);
- _peerList[aPeer.address] = peer;
- handlePeerListUpdated();
- }
- peer.connectionStatus = CONNECTION_STATUS_CONNECTING;
-
- fireEvent('onconnecting', { peer: peer });
- },
-
- onConnected: function(aGroupOwner, aPeer) {
- let go = new P2pGroupOwner(aGroupOwner);
- let peer = _peerList[aPeer.address];
- if (!peer) {
- debug('Unknown peer connected: ' + aPeer.address);
- peer = new P2pDevice(aPeer);
- _peerList[aPeer.address] = peer;
- handlePeerListUpdated();
- }
- peer.connectionStatus = CONNECTION_STATUS_CONNECTED;
- peer.isGroupOwner = (aPeer.address === aGroupOwner.address);
-
- _groupOwner = go;
- _currentPeer = peer;
-
- fireEvent('onconnected', { groupOwner: go, peer: peer });
- },
-
- onDisconnected: function(aPeer) {
- let peer = _peerList[aPeer.address];
- if (!peer) {
- debug('Unknown peer disconnected: ' + aPeer.address);
- return;
- }
-
- peer.connectionStatus = CONNECTION_STATUS_DISCONNECTED;
-
- _groupOwner = null;
- _currentPeer = null;
-
- fireEvent('ondisconnected', { peer: peer });
- },
-
- getObservedDOMMessages: function() {
- return [
- "WifiP2pManager:getState",
- "WifiP2pManager:getPeerList",
- "WifiP2pManager:setScanEnabled",
- "WifiP2pManager:connect",
- "WifiP2pManager:disconnect",
- "WifiP2pManager:setPairingConfirmation",
- "WifiP2pManager:setDeviceName"
- ];
- },
-
- onDOMMessage: function(aMessage) {
- let msg = aMessage.data || {};
- msg.manager = aMessage.target;
-
- if ("child-process-shutdown" === aMessage.name) {
- let i;
- if (-1 !== (i = _domManagers.indexOf(msg.manager))) {
- _domManagers.splice(i, 1);
- }
- return;
- }
-
- if (!aMessage.target.assertPermission("wifi-manage")) {
- return;
- }
-
- switch (aMessage.name) {
- case "WifiP2pManager:getState": // A new DOM manager is created.
- addDomManager(msg);
- return { // Synchronous call. Simply return it.
- enabled: _enabled,
- groupOwner: _groupOwner,
- currentPeer: _currentPeer
- };
-
- case "WifiP2pManager:setScanEnabled":
- {
- let enabled = msg.data;
-
- aDomMsgResponder.setScanEnabled(enabled, function(success) {
- returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
- });
- }
- break;
-
- case "WifiP2pManager:getPeerList":
- {
- // Convert the object to an array.
- let peerArray = [];
- for (let key in _peerList) {
- if (_peerList.hasOwnProperty(key)) {
- peerArray.push(_peerList[key]);
- }
- }
-
- returnMessage(aMessage.name, true, peerArray, msg);
- }
- break;
-
- case "WifiP2pManager:connect":
- {
- let peer = msg.data;
-
- let onDoConnect = function(success) {
- returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
- };
-
- aDomMsgResponder.connect(peer.address, peer.wpsMethod,
- peer.goIntent, onDoConnect);
- }
- break;
-
- case "WifiP2pManager:disconnect":
- {
- let address = msg.data;
-
- aDomMsgResponder.disconnect(address, function(success) {
- returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
- });
- }
- break;
-
- case "WifiP2pManager:setPairingConfirmation":
- {
- let result = msg.data;
- aDomMsgResponder.setPairingConfirmation(result);
- returnMessage(aMessage.name, true, true, msg);
- }
- break;
-
- case "WifiP2pManager:setDeviceName":
- {
- let newDeviceName = msg.data;
- aDomMsgResponder.setDeviceName(newDeviceName, function(success) {
- returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
- });
- }
- break;
-
- default:
- if (0 === aMessage.name.indexOf("WifiP2pManager:")) {
- debug("DOM WifiP2pManager message not handled: " + aMessage.name);
- }
- } // End of switch.
- }
- };
-};
diff --git a/dom/wifi/WifiProxyService.cpp b/dom/wifi/WifiProxyService.cpp
deleted file mode 100644
index 0ff5097af..000000000
--- a/dom/wifi/WifiProxyService.cpp
+++ /dev/null
@@ -1,357 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WifiProxyService.h"
-#include "nsServiceManagerUtils.h"
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/ToJSValue.h"
-#include "nsXULAppAPI.h"
-#include "WifiUtils.h"
-
-#ifdef MOZ_TASK_TRACER
-#include "GeckoTaskTracer.h"
-using namespace mozilla::tasktracer;
-#endif
-
-#define NS_WIFIPROXYSERVICE_CID \
- { 0xc6c9be7e, 0x744f, 0x4222, {0xb2, 0x03, 0xcd, 0x55, 0xdf, 0xc8, 0xbc, 0x12} }
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-namespace mozilla {
-
-// The singleton Wifi service, to be used on the main thread.
-static StaticRefPtr<WifiProxyService> gWifiProxyService;
-
-// The singleton supplicant class, that can be used on any thread.
-static UniquePtr<WpaSupplicant> gWpaSupplicant;
-
-// Runnable used dispatch the WaitForEvent result on the main thread.
-class WifiEventDispatcher : public Runnable
-{
-public:
- WifiEventDispatcher(const nsAString& aEvent, const nsACString& aInterface)
- : mEvent(aEvent)
- , mInterface(aInterface)
- {
- MOZ_ASSERT(!NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- gWifiProxyService->DispatchWifiEvent(mEvent, mInterface);
- return NS_OK;
- }
-
-private:
- nsString mEvent;
- nsCString mInterface;
-};
-
-// Runnable used to call WaitForEvent on the event thread.
-class EventRunnable : public Runnable
-{
-public:
- EventRunnable(const nsACString& aInterface)
- : mInterface(aInterface)
- {
- MOZ_ASSERT(NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
- nsAutoString event;
- gWpaSupplicant->WaitForEvent(event, mInterface);
- if (!event.IsEmpty()) {
-#ifdef MOZ_TASK_TRACER
- // Make wifi initialization events to be the source events of TaskTracer,
- // and originate the rest correlation tasks from here.
- AutoSourceEvent taskTracerEvent(SourceEventType::Wifi);
- AddLabel("%s %s", mInterface.get(), NS_ConvertUTF16toUTF8(event).get());
-#endif
- nsCOMPtr<nsIRunnable> runnable = new WifiEventDispatcher(event, mInterface);
- NS_DispatchToMainThread(runnable);
- }
- return NS_OK;
- }
-
-private:
- nsCString mInterface;
-};
-
-// Runnable used dispatch the Command result on the main thread.
-class WifiResultDispatcher : public Runnable
-{
-public:
- WifiResultDispatcher(WifiResultOptions& aResult, const nsACString& aInterface)
- : mResult(aResult)
- , mInterface(aInterface)
- {
- MOZ_ASSERT(!NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- gWifiProxyService->DispatchWifiResult(mResult, mInterface);
- return NS_OK;
- }
-
-private:
- WifiResultOptions mResult;
- nsCString mInterface;
-};
-
-// Runnable used to call SendCommand on the control thread.
-class ControlRunnable : public Runnable
-{
-public:
- ControlRunnable(CommandOptions aOptions, const nsACString& aInterface)
- : mOptions(aOptions)
- , mInterface(aInterface)
- {
- MOZ_ASSERT(NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- WifiResultOptions result;
- if (gWpaSupplicant->ExecuteCommand(mOptions, result, mInterface)) {
- nsCOMPtr<nsIRunnable> runnable = new WifiResultDispatcher(result, mInterface);
- NS_DispatchToMainThread(runnable);
- }
- return NS_OK;
- }
-private:
- CommandOptions mOptions;
- nsCString mInterface;
-};
-
-NS_IMPL_ISUPPORTS(WifiProxyService, nsIWifiProxyService)
-
-WifiProxyService::WifiProxyService()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!gWifiProxyService);
-}
-
-WifiProxyService::~WifiProxyService()
-{
- MOZ_ASSERT(!gWifiProxyService);
-}
-
-already_AddRefed<WifiProxyService>
-WifiProxyService::FactoryCreate()
-{
- if (!XRE_IsParentProcess()) {
- return nullptr;
- }
-
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!gWifiProxyService) {
- gWifiProxyService = new WifiProxyService();
- ClearOnShutdown(&gWifiProxyService);
-
- gWpaSupplicant = MakeUnique<WpaSupplicant>();
- ClearOnShutdown(&gWpaSupplicant);
- }
-
- RefPtr<WifiProxyService> service = gWifiProxyService.get();
- return service.forget();
-}
-
-NS_IMETHODIMP
-WifiProxyService::Start(nsIWifiEventListener* aListener,
- const char ** aInterfaces,
- uint32_t aNumOfInterfaces)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(aListener);
-
-#if ANDROID_VERSION >= 19
- // KK changes the way mux'ing/demux'ing different supplicant interfaces
- // (e.g. wlan0/p2p0) from multi-sockets to single socket embedded with
- // prefixed interface name (e.g. IFNAME=wlan0 xxxxxx). Therefore, we use
- // the first given interface as the global interface for KK.
- aNumOfInterfaces = 1;
-#endif
-
- nsresult rv;
-
- // Since EventRunnable runs in the manner of blocking, we have to
- // spin a thread for each interface.
- // (See the WpaSupplicant::WaitForEvent)
- mEventThreadList.SetLength(aNumOfInterfaces);
- for (uint32_t i = 0; i < aNumOfInterfaces; i++) {
- mEventThreadList[i].mInterface = aInterfaces[i];
- rv = NS_NewThread(getter_AddRefs(mEventThreadList[i].mThread));
- if (NS_FAILED(rv)) {
- NS_WARNING("Can't create wifi event thread");
- Shutdown();
- return NS_ERROR_FAILURE;
- }
- }
-
- rv = NS_NewThread(getter_AddRefs(mControlThread));
- if (NS_FAILED(rv)) {
- NS_WARNING("Can't create wifi control thread");
- Shutdown();
- return NS_ERROR_FAILURE;
- }
-
- mListener = aListener;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-WifiProxyService::Shutdown()
-{
- MOZ_ASSERT(NS_IsMainThread());
- for (size_t i = 0; i < mEventThreadList.Length(); i++) {
- if (mEventThreadList[i].mThread) {
- mEventThreadList[i].mThread->Shutdown();
- mEventThreadList[i].mThread = nullptr;
- }
- }
-
- mEventThreadList.Clear();
-
- if (mControlThread) {
- mControlThread->Shutdown();
- mControlThread = nullptr;
- }
-
- mListener = nullptr;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-WifiProxyService::SendCommand(JS::Handle<JS::Value> aOptions,
- const nsACString& aInterface,
- JSContext* aCx)
-{
- MOZ_ASSERT(NS_IsMainThread());
- WifiCommandOptions options;
-
- if (!options.Init(aCx, aOptions)) {
- NS_WARNING("Bad dictionary passed to WifiProxyService::SendCommand");
- return NS_ERROR_FAILURE;
- }
-
- if (!mControlThread) {
- return NS_ERROR_FAILURE;
- }
-
- // Dispatch the command to the control thread.
- CommandOptions commandOptions(options);
- nsCOMPtr<nsIRunnable> runnable = new ControlRunnable(commandOptions, aInterface);
- mControlThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-WifiProxyService::WaitForEvent(const nsACString& aInterface)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
-#if ANDROID_VERSION >= 19
- // We will only have one global interface for KK.
- if (!mEventThreadList.IsEmpty()) {
- nsCOMPtr<nsIRunnable> runnable = new EventRunnable(aInterface);
- mEventThreadList[0].mThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
- return NS_OK;
- }
-#else
- // Dispatch to the event thread which has the given interface name
- for (size_t i = 0; i < mEventThreadList.Length(); i++) {
- if (mEventThreadList[i].mInterface.Equals(aInterface)) {
- nsCOMPtr<nsIRunnable> runnable = new EventRunnable(aInterface);
- mEventThreadList[i].mThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
- return NS_OK;
- }
- }
-#endif
-
- return NS_ERROR_FAILURE;
-}
-
-void
-WifiProxyService::DispatchWifiResult(const WifiResultOptions& aOptions, const nsACString& aInterface)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mozilla::AutoSafeJSContext cx;
- JS::Rooted<JS::Value> val(cx);
-
- if (!ToJSValue(cx, aOptions, &val)) {
- return;
- }
-
- if (mListener) {
- // Call the listener with a JS value.
- mListener->OnCommand(val, aInterface);
- }
-}
-
-void
-WifiProxyService::DispatchWifiEvent(const nsAString& aEvent, const nsACString& aInterface)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
-#if ANDROID_VERSION < 19
- mListener->OnWaitEvent(aEvent, aInterface);
-#else
- // The interface might be embedded in the event string such as
- // "IFNAME=wlan0 CTRL-EVENT-BSS-ADDED 65 3c:94:d5:7c:11:8b".
- // Parse the interface name from the event string and use p2p0
- // as the default interface if "IFNAME" is not found.
- nsAutoString event;
- nsAutoString embeddedInterface(NS_LITERAL_STRING("p2p0"));
- if (StringBeginsWith(aEvent, NS_LITERAL_STRING("IFNAME"))) {
- int32_t ifnameFrom = aEvent.FindChar('=') + 1;
- int32_t ifnameTo = aEvent.FindChar(' ') - 1;
- embeddedInterface = Substring(aEvent, ifnameFrom, ifnameTo - ifnameFrom + 1);
- event = Substring(aEvent, aEvent.FindChar(' ') + 1);
- }
- else {
- event = aEvent;
- }
- mListener->OnWaitEvent(event, NS_ConvertUTF16toUTF8(embeddedInterface));
-#endif
-}
-
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WifiProxyService,
- WifiProxyService::FactoryCreate)
-
-NS_DEFINE_NAMED_CID(NS_WIFIPROXYSERVICE_CID);
-
-static const mozilla::Module::CIDEntry kWifiProxyServiceCIDs[] = {
- { &kNS_WIFIPROXYSERVICE_CID, false, nullptr, WifiProxyServiceConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kWifiProxyServiceContracts[] = {
- { "@mozilla.org/wifi/service;1", &kNS_WIFIPROXYSERVICE_CID },
- { nullptr }
-};
-
-static const mozilla::Module kWifiProxyServiceModule = {
- mozilla::Module::kVersion,
- kWifiProxyServiceCIDs,
- kWifiProxyServiceContracts,
- nullptr
-};
-
-} // namespace mozilla
-
-NSMODULE_DEFN(WifiProxyServiceModule) = &kWifiProxyServiceModule;
diff --git a/dom/wifi/WifiProxyService.h b/dom/wifi/WifiProxyService.h
deleted file mode 100644
index 406be47de..000000000
--- a/dom/wifi/WifiProxyService.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef WifiProxyService_h
-#define WifiProxyService_h
-
-#include "nsIWifiService.h"
-#include "nsCOMPtr.h"
-#include "nsThread.h"
-#include "mozilla/dom/WifiOptionsBinding.h"
-#include "nsTArray.h"
-
-namespace mozilla {
-
-class WifiProxyService final : public nsIWifiProxyService
-{
-private:
- struct EventThreadListEntry
- {
- nsCOMPtr<nsIThread> mThread;
- nsCString mInterface;
- };
-
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIWIFIPROXYSERVICE
-
- static already_AddRefed<WifiProxyService>
- FactoryCreate();
-
- void DispatchWifiEvent(const nsAString& aEvent, const nsACString& aInterface);
- void DispatchWifiResult(const mozilla::dom::WifiResultOptions& aOptions,
- const nsACString& aInterface);
-
-private:
- WifiProxyService();
- ~WifiProxyService();
-
- nsTArray<EventThreadListEntry> mEventThreadList;
- nsCOMPtr<nsIThread> mControlThread;
- nsCOMPtr<nsIWifiEventListener> mListener;
-};
-
-} // namespace mozilla
-
-#endif // WifiProxyService_h
diff --git a/dom/wifi/WifiUtils.cpp b/dom/wifi/WifiUtils.cpp
deleted file mode 100644
index 2526c9ea4..000000000
--- a/dom/wifi/WifiUtils.cpp
+++ /dev/null
@@ -1,521 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WifiUtils.h"
-#include <dlfcn.h>
-#include <errno.h>
-#include <cutils/properties.h>
-#include "prinit.h"
-#include "mozilla/Sprintf.h"
-#include "js/CharacterEncoding.h"
-
-using namespace mozilla::dom;
-
-#define BUFFER_SIZE 4096
-#define COMMAND_SIZE 256
-
-// Intentionally not trying to dlclose() this handle. That's playing
-// Russian roulette with security bugs.
-static void* sWifiLib;
-static PRCallOnceType sInitWifiLib;
-
-static PRStatus
-InitWifiLib()
-{
- sWifiLib = dlopen("/system/lib/libhardware_legacy.so", RTLD_LAZY);
- // We might fail to open the hardware lib. That's OK.
- return PR_SUCCESS;
-}
-
-static void*
-GetSharedLibrary()
-{
- PR_CallOnce(&sInitWifiLib, InitWifiLib);
- return sWifiLib;
-}
-
-static bool
-GetWifiP2pSupported()
-{
- char propP2pSupported[PROPERTY_VALUE_MAX];
- property_get("ro.moz.wifi.p2p_supported", propP2pSupported, "0");
- return (0 == strcmp(propP2pSupported, "1"));
-}
-
-static int
-hex2num(char c)
-{
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- return -1;
-}
-
-static int
-hex2byte(const char* hex)
-{
- int a, b;
- a = hex2num(*hex++);
- if (a < 0)
- return -1;
- b = hex2num(*hex++);
- if (b < 0)
- return -1;
- return (a << 4) | b;
-}
-
-// This function is equivalent to printf_decode() at src/utils/common.c in
-// the supplicant.
-
-static uint32_t
-convertToBytes(char* buf, uint32_t maxlen, const char* str)
-{
- const char *pos = str;
- uint32_t len = 0;
- int val;
-
- while (*pos) {
- if (len == maxlen)
- break;
- switch (*pos) {
- case '\\':
- pos++;
- switch (*pos) {
- case '\\':
- buf[len++] = '\\';
- pos++;
- break;
- case '"':
- buf[len++] = '"';
- pos++;
- break;
- case 'n':
- buf[len++] = '\n';
- pos++;
- break;
- case 'r':
- buf[len++] = '\r';
- pos++;
- break;
- case 't':
- buf[len++] = '\t';
- pos++;
- break;
- case 'e':
- buf[len++] = '\e';
- pos++;
- break;
- case 'x':
- pos++;
- val = hex2byte(pos);
- if (val < 0) {
- val = hex2num(*pos);
- if (val < 0)
- break;
- buf[len++] = val;
- pos++;
- } else {
- buf[len++] = val;
- pos += 2;
- }
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- val = *pos++ - '0';
- if (*pos >= '0' && *pos <= '7')
- val = val * 8 + (*pos++ - '0');
- if (*pos >= '0' && *pos <= '7')
- val = val * 8 + (*pos++ - '0');
- buf[len++] = val;
- break;
- default:
- break;
- }
- break;
- default:
- buf[len++] = *pos++;
- break;
- }
- }
- return len;
-}
-
-// This is the same algorithm as in InflateUTF8StringToBuffer with Copy and
-// while ignoring invalids.
-// https://mxr.mozilla.org/mozilla-central/source/js/src/vm/CharacterEncoding.cpp#231
-
-static const uint32_t REPLACE_UTF8 = 0xFFFD;
-
-static void
-LossyConvertUTF8toUTF16(const char* aInput, uint32_t aLength, nsAString& aOut)
-{
- JS::UTF8Chars src(aInput, aLength);
-
- char16_t dst[aLength]; // Allocating for worst case.
-
- // Count how many char16_t characters are needed in the inflated string.
- // |i| is the index into |src|, and |j| is the the index into |dst|.
- size_t srclen = src.length();
- uint32_t j = 0;
- for (uint32_t i = 0; i < srclen; i++, j++) {
- uint32_t v = uint32_t(src[i]);
- if (v == uint32_t('\0') && i < srclen - 1) {
- // If the leading byte is '\0' and it's not the last byte,
- // just ignore it to prevent from being truncated. This could
- // be caused by |convertToBytes| (e.g. \x00 would be converted to '\0')
- j--;
- continue;
- }
- if (!(v & 0x80)) {
- // ASCII code unit. Simple copy.
- dst[j] = char16_t(v);
- } else {
- // Non-ASCII code unit. Determine its length in bytes (n).
- uint32_t n = 1;
- while (v & (0x80 >> n))
- n++;
-
- #define INVALID(report, arg, n2) \
- do { \
- n = n2; \
- goto invalidMultiByteCodeUnit; \
- } while (0)
-
- // Check the leading byte.
- if (n < 2 || n > 4)
- INVALID(ReportInvalidCharacter, i, 1);
-
- // Check that |src| is large enough to hold an n-byte code unit.
- if (i + n > srclen)
- INVALID(ReportBufferTooSmall, /* dummy = */ 0, 1);
-
- // Check the second byte. From Unicode Standard v6.2, Table 3-7
- // Well-Formed UTF-8 Byte Sequences.
- if ((v == 0xE0 && ((uint8_t)src[i + 1] & 0xE0) != 0xA0) || // E0 A0~BF
- (v == 0xED && ((uint8_t)src[i + 1] & 0xE0) != 0x80) || // ED 80~9F
- (v == 0xF0 && ((uint8_t)src[i + 1] & 0xF0) == 0x80) || // F0 90~BF
- (v == 0xF4 && ((uint8_t)src[i + 1] & 0xF0) != 0x80)) // F4 80~8F
- {
- INVALID(ReportInvalidCharacter, i, 1);
- }
-
- // Check the continuation bytes.
- for (uint32_t m = 1; m < n; m++)
- if ((src[i + m] & 0xC0) != 0x80)
- INVALID(ReportInvalidCharacter, i, m);
-
- // Determine the code unit's length in char16_t units and act accordingly.
- v = JS::Utf8ToOneUcs4Char((uint8_t *)&src[i], n);
- if (v < 0x10000) {
- // The n-byte UTF8 code unit will fit in a single char16_t.
- dst[j] = char16_t(v);
- } else {
- v -= 0x10000;
- if (v <= 0xFFFFF) {
- // The n-byte UTF8 code unit will fit in two char16_t units.
- dst[j] = char16_t((v >> 10) + 0xD800);
- j++;
- dst[j] = char16_t((v & 0x3FF) + 0xDC00);
- } else {
- // The n-byte UTF8 code unit won't fit in two char16_t units.
- INVALID(ReportTooBigCharacter, v, 1);
- }
- }
-
- invalidMultiByteCodeUnit:
- // Move i to the last byte of the multi-byte code unit; the loop
- // header will do the final i++ to move to the start of the next
- // code unit.
- i += n - 1;
- }
- }
-
- dst[j] = 0;
- aOut = dst;
-}
-
-// Helper to check we have loaded the hardware shared library.
-#define CHECK_HWLIB(ret) \
- void* hwLib = GetSharedLibrary(); \
- if (!hwLib) { \
- NS_WARNING("No /system/lib/libhardware_legacy.so"); \
- return ret; \
- }
-
-#define DEFAULT_IMPL(name, ret, args...) \
- DEFINE_DLFUNC(name, ret, args...) \
- ret do_##name(args) { \
- USE_DLFUNC(name) \
- return name(args); \
- }
-
-// ICS implementation.
-class ICSWpaSupplicantImpl : public WpaSupplicantImpl
-{
-public:
- DEFAULT_IMPL(wifi_load_driver, int32_t, )
- DEFAULT_IMPL(wifi_unload_driver, int32_t, )
-
- DEFINE_DLFUNC(wifi_wait_for_event, int32_t, char*, size_t)
- int32_t do_wifi_wait_for_event(const char *iface, char *buf, size_t len) {
- USE_DLFUNC(wifi_wait_for_event)
- return wifi_wait_for_event(buf, len);
- }
-
- DEFINE_DLFUNC(wifi_command, int32_t, const char*, char*, size_t*)
- int32_t do_wifi_command(const char* iface, const char* cmd, char* buf, size_t* len) {
- USE_DLFUNC(wifi_command)
- return wifi_command(cmd, buf, len);
- }
-
- DEFINE_DLFUNC(wifi_start_supplicant, int32_t, )
- int32_t do_wifi_start_supplicant(int32_t) {
- USE_DLFUNC(wifi_start_supplicant)
- return wifi_start_supplicant();
- }
-
- DEFINE_DLFUNC(wifi_stop_supplicant, int32_t)
- int32_t do_wifi_stop_supplicant(int32_t) {
- USE_DLFUNC(wifi_stop_supplicant)
- return wifi_stop_supplicant();
- }
-
- DEFINE_DLFUNC(wifi_connect_to_supplicant, int32_t, )
- int32_t do_wifi_connect_to_supplicant(const char* iface) {
- USE_DLFUNC(wifi_connect_to_supplicant)
- return wifi_connect_to_supplicant();
- }
-
- DEFINE_DLFUNC(wifi_close_supplicant_connection, void, )
- void do_wifi_close_supplicant_connection(const char* iface) {
- USE_DLFUNC(wifi_close_supplicant_connection)
- return wifi_close_supplicant_connection();
- }
-};
-
-// JB implementation.
-// We only redefine the methods that have a different signature than on ICS.
-class JBWpaSupplicantImpl : public ICSWpaSupplicantImpl
-{
-public:
- DEFINE_DLFUNC(wifi_wait_for_event, int32_t, const char*, char*, size_t)
- int32_t do_wifi_wait_for_event(const char* iface, char* buf, size_t len) {
- USE_DLFUNC(wifi_wait_for_event)
- return wifi_wait_for_event(iface, buf, len);
- }
-
- DEFINE_DLFUNC(wifi_command, int32_t, const char*, const char*, char*, size_t*)
- int32_t do_wifi_command(const char* iface, const char* cmd, char* buf, size_t* len) {
- USE_DLFUNC(wifi_command)
- return wifi_command(iface, cmd, buf, len);
- }
-
- DEFINE_DLFUNC(wifi_start_supplicant, int32_t, int32_t)
- int32_t do_wifi_start_supplicant(int32_t arg) {
- USE_DLFUNC(wifi_start_supplicant)
- return wifi_start_supplicant(arg);
- }
-
- DEFINE_DLFUNC(wifi_stop_supplicant, int32_t, int32_t)
- int32_t do_wifi_stop_supplicant(int32_t arg) {
- USE_DLFUNC(wifi_stop_supplicant)
- return wifi_stop_supplicant(arg);
- }
-
- DEFINE_DLFUNC(wifi_connect_to_supplicant, int32_t, const char*)
- int32_t do_wifi_connect_to_supplicant(const char* iface) {
- USE_DLFUNC(wifi_connect_to_supplicant)
- return wifi_connect_to_supplicant(iface);
- }
-
- DEFINE_DLFUNC(wifi_close_supplicant_connection, void, const char*)
- void do_wifi_close_supplicant_connection(const char* iface) {
- USE_DLFUNC(wifi_close_supplicant_connection)
- wifi_close_supplicant_connection(iface);
- }
-};
-
-// KK implementation.
-// We only redefine the methods that have a different signature than on ICS.
-class KKWpaSupplicantImpl : public ICSWpaSupplicantImpl
-{
-public:
- DEFINE_DLFUNC(wifi_start_supplicant, int32_t, int32_t)
- int32_t do_wifi_start_supplicant(int32_t arg) {
- USE_DLFUNC(wifi_start_supplicant)
- return wifi_start_supplicant(arg);
- }
-
- DEFINE_DLFUNC(wifi_stop_supplicant, int32_t, int32_t)
- int32_t do_wifi_stop_supplicant(int32_t arg) {
- USE_DLFUNC(wifi_stop_supplicant)
- return wifi_stop_supplicant(arg);
- }
-
- DEFINE_DLFUNC(wifi_command, int32_t, const char*, char*, size_t*)
- int32_t do_wifi_command(const char* iface, const char* cmd, char* buf, size_t* len) {
- char command[COMMAND_SIZE];
- if (!strcmp(iface, "p2p0")) {
- // Commands for p2p0 interface don't need prefix
- SprintfLiteral(command, "%s", cmd);
- }
- else {
- SprintfLiteral(command, "IFNAME=%s %s", iface, cmd);
- }
- USE_DLFUNC(wifi_command)
- return wifi_command(command, buf, len);
- }
-};
-
-// Concrete class to use to access the wpa supplicant.
-WpaSupplicant::WpaSupplicant()
-{
- char propVersion[PROPERTY_VALUE_MAX];
- property_get("ro.build.version.sdk", propVersion, "0");
- mSdkVersion = strtol(propVersion, nullptr, 10);
-
- if (mSdkVersion < 16) {
- mImpl = MakeUnique<ICSWpaSupplicantImpl>();
- } else if (mSdkVersion < 19) {
- mImpl = MakeUnique<JBWpaSupplicantImpl>();
- } else {
- mImpl = MakeUnique<KKWpaSupplicantImpl>();
- }
- mWifiHotspotUtils = MakeUnique<WifiHotspotUtils>();
-};
-
-void WpaSupplicant::WaitForEvent(nsAString& aEvent, const nsCString& aInterface)
-{
- CHECK_HWLIB()
-
- char buffer[BUFFER_SIZE];
- int32_t ret = mImpl->do_wifi_wait_for_event(aInterface.get(), buffer, BUFFER_SIZE);
- CheckBuffer(buffer, ret, aEvent);
-}
-
-#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aOptions.prop).get()
-
-/**
- * Make a subnet mask.
- */
-uint32_t WpaSupplicant::MakeMask(uint32_t len) {
- uint32_t mask = 0;
- for (uint32_t i = 0; i < len; ++i) {
- mask |= (0x80000000 >> i);
- }
- return ntohl(mask);
-}
-
-bool WpaSupplicant::ExecuteCommand(CommandOptions aOptions,
- WifiResultOptions& aResult,
- const nsCString& aInterface)
-{
- CHECK_HWLIB(false)
-
- if (!mWifiHotspotUtils->GetSharedLibrary()) {
- return false;
- }
-
- // Always correlate the opaque ids.
- aResult.mId = aOptions.mId;
-
- if (aOptions.mCmd.EqualsLiteral("command")) {
- size_t len = BUFFER_SIZE - 1;
- char buffer[BUFFER_SIZE];
- NS_ConvertUTF16toUTF8 request(aOptions.mRequest);
- aResult.mStatus = mImpl->do_wifi_command(aInterface.get(), request.get(), buffer, &len);
- nsString value;
- if (aResult.mStatus == 0) {
- if (buffer[len - 1] == '\n') { // remove trailing new lines.
- len--;
- }
- buffer[len] = '\0';
- CheckBuffer(buffer, len, value);
- }
- aResult.mReply = value;
- } else if (aOptions.mCmd.EqualsLiteral("close_supplicant_connection")) {
- mImpl->do_wifi_close_supplicant_connection(aInterface.get());
- } else if (aOptions.mCmd.EqualsLiteral("load_driver")) {
- aResult.mStatus = mImpl->do_wifi_load_driver();
- } else if (aOptions.mCmd.EqualsLiteral("unload_driver")) {
- aResult.mStatus = mImpl->do_wifi_unload_driver();
- } else if (aOptions.mCmd.EqualsLiteral("start_supplicant")) {
- aResult.mStatus = mImpl->do_wifi_start_supplicant(GetWifiP2pSupported() ? 1 : 0);
- } else if (aOptions.mCmd.EqualsLiteral("stop_supplicant")) {
- aResult.mStatus = mImpl->do_wifi_stop_supplicant(0);
- } else if (aOptions.mCmd.EqualsLiteral("connect_to_supplicant")) {
- aResult.mStatus = mImpl->do_wifi_connect_to_supplicant(aInterface.get());
- } else if (aOptions.mCmd.EqualsLiteral("hostapd_command")) {
- size_t len = BUFFER_SIZE - 1;
- char buffer[BUFFER_SIZE];
- NS_ConvertUTF16toUTF8 request(aOptions.mRequest);
- aResult.mStatus = mWifiHotspotUtils->do_wifi_hostapd_command(request.get(),
- buffer,
- &len);
- nsString value;
- if (aResult.mStatus == 0) {
- if (buffer[len - 1] == '\n') { // remove trailing new lines.
- len--;
- }
- buffer[len] = '\0';
- CheckBuffer(buffer, len, value);
- }
- aResult.mReply = value;
- } else if (aOptions.mCmd.EqualsLiteral("hostapd_get_stations")) {
- aResult.mStatus = mWifiHotspotUtils->do_wifi_hostapd_get_stations();
- } else if (aOptions.mCmd.EqualsLiteral("connect_to_hostapd")) {
- aResult.mStatus = mWifiHotspotUtils->do_wifi_connect_to_hostapd();
- } else if (aOptions.mCmd.EqualsLiteral("close_hostapd_connection")) {
- aResult.mStatus = mWifiHotspotUtils->do_wifi_close_hostapd_connection();
-
- } else {
- NS_WARNING("WpaSupplicant::ExecuteCommand : Unknown command");
- printf_stderr("WpaSupplicant::ExecuteCommand : Unknown command: %s",
- NS_ConvertUTF16toUTF8(aOptions.mCmd).get());
- return false;
- }
-
- return true;
-}
-
-// Checks the buffer and do the utf processing.
-void
-WpaSupplicant::CheckBuffer(char* buffer, int32_t length,
- nsAString& aEvent)
-{
- if (length <= 0 || length >= (BUFFER_SIZE - 1)) {
- NS_WARNING("WpaSupplicant::CheckBuffer: Invalid buffer length");
- return;
- }
-
- if (mSdkVersion < 18) {
- buffer[length] = 0;
- LossyConvertUTF8toUTF16(buffer, length, aEvent);
- return;
- }
-
- // After Android JB4.3, the SSIDs have been converted into printable form.
- // In most of cases, SSIDs do not use unprintable characters, but IEEE 802.11
- // standard does not limit the used character set, so anything could be used
- // in an SSID. Convert it to raw data form here.
- char bytesBuffer[BUFFER_SIZE];
- uint32_t bytes = convertToBytes(bytesBuffer, length, buffer);
- if (bytes <= 0 || bytes >= BUFFER_SIZE) {
- NS_WARNING("WpaSupplicant::CheckBuffer: Invalid bytesbuffer length");
- return;
- }
- bytesBuffer[bytes] = 0;
- LossyConvertUTF8toUTF16(bytesBuffer, bytes, aEvent);
-}
diff --git a/dom/wifi/WifiUtils.h b/dom/wifi/WifiUtils.h
deleted file mode 100644
index a83ba9c15..000000000
--- a/dom/wifi/WifiUtils.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Abstraction on top of the wifi support from libhardware_legacy that we
- * use to talk to the wpa_supplicant.
- */
-
-#ifndef WifiUtils_h
-#define WifiUtils_h
-
-#include "nsString.h"
-#include "mozilla/dom/WifiOptionsBinding.h"
-#include "mozilla/UniquePtr.h"
-#include "WifiHotspotUtils.h"
-
-// Needed to add a copy constructor to WifiCommandOptions.
-struct CommandOptions
-{
-public:
- CommandOptions(const mozilla::dom::WifiCommandOptions& aOther) {
-
-#define COPY_OPT_FIELD(prop, defaultValue) \
- if (aOther.prop.WasPassed()) { \
- prop = aOther.prop.Value(); \
- } else { \
- prop = defaultValue; \
- }
-
-#define COPY_FIELD(prop) prop = aOther.prop;
- COPY_FIELD(mId)
- COPY_FIELD(mCmd)
- COPY_OPT_FIELD(mRequest, EmptyString())
-
-#undef COPY_OPT_FIELD
-#undef COPY_FIELD
- }
-
- // All the fields, not Optional<> anymore to get copy constructors.
- nsString mCmd;
- int32_t mId;
- nsString mRequest;
-};
-
-// Abstract class that exposes libhardware_legacy functions we need for
-// wifi management.
-// We use the ICS signatures here since they are likely more future-proof.
-class WpaSupplicantImpl
-{
-public:
- // Suppress warning from |UniquePtr|
- virtual ~WpaSupplicantImpl() {}
-
- virtual int32_t
- do_wifi_wait_for_event(const char *iface, char *buf, size_t len) = 0; // KK == ICS != JB
-
- virtual int32_t
- do_wifi_command(const char* iface, const char* cmd, char* buff, size_t* len) = 0; // KK == ICS != JB
-
- virtual int32_t
- do_wifi_load_driver() = 0;
-
- virtual int32_t
- do_wifi_unload_driver() = 0;
-
- virtual int32_t
- do_wifi_start_supplicant(int32_t) = 0; // ICS != JB == KK
-
- virtual int32_t
- do_wifi_stop_supplicant(int32_t) = 0; //ICS != JB == KK
-
- virtual int32_t
- do_wifi_connect_to_supplicant(const char* iface) = 0; // KK == ICS != JB
-
- virtual void
- do_wifi_close_supplicant_connection(const char* iface) = 0; // KK == ICS != JB
-};
-
-// Concrete class to use to access the wpa supplicant.
-class WpaSupplicant final
-{
-public:
- WpaSupplicant();
-
- // Use nsCString as the type of aInterface to guarantee it's
- // null-terminated so that we can pass it to c API without
- // conversion
- void WaitForEvent(nsAString& aEvent, const nsCString& aInterface);
- bool ExecuteCommand(CommandOptions aOptions,
- mozilla::dom::WifiResultOptions& result,
- const nsCString& aInterface);
-
-private:
- UniquePtr<WpaSupplicantImpl> mImpl;
- UniquePtr<WifiHotspotUtils> mWifiHotspotUtils;
-
- uint32_t mSdkVersion;
-
-protected:
- void CheckBuffer(char* buffer, int32_t length, nsAString& aEvent);
- uint32_t MakeMask(uint32_t len);
-};
-
-#endif // WifiUtils_h
diff --git a/dom/wifi/WifiWorker.h b/dom/wifi/WifiWorker.h
deleted file mode 100644
index 2cd89c3e7..000000000
--- a/dom/wifi/WifiWorker.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#define NS_WIFIWORKER_CID \
-{ 0xA14E8977, 0xD259, 0x433A, \
- { 0xA8, 0x8D, 0x58, 0xDD, 0x44, 0x65, 0x7E, 0x5B } }
diff --git a/dom/wifi/WifiWorker.js b/dom/wifi/WifiWorker.js
deleted file mode 100644
index 243ba8b97..000000000
--- a/dom/wifi/WifiWorker.js
+++ /dev/null
@@ -1,3928 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/WifiCommand.jsm");
-Cu.import("resource://gre/modules/WifiNetUtil.jsm");
-Cu.import("resource://gre/modules/WifiP2pManager.jsm");
-Cu.import("resource://gre/modules/WifiP2pWorkerObserver.jsm");
-
-var DEBUG = false; // set to true to show debug messages.
-
-const WIFIWORKER_CONTRACTID = "@mozilla.org/wifi/worker;1";
-const WIFIWORKER_CID = Components.ID("{a14e8977-d259-433a-a88d-58dd44657e5b}");
-
-const WIFIWORKER_WORKER = "resource://gre/modules/wifi_worker.js";
-
-const kMozSettingsChangedObserverTopic = "mozsettings-changed";
-
-const MAX_RETRIES_ON_AUTHENTICATION_FAILURE = 2;
-const MAX_SUPPLICANT_LOOP_ITERATIONS = 4;
-const MAX_RETRIES_ON_DHCP_FAILURE = 2;
-
-// Settings DB path for wifi
-const SETTINGS_WIFI_ENABLED = "wifi.enabled";
-const SETTINGS_WIFI_DEBUG_ENABLED = "wifi.debugging.enabled";
-// Settings DB path for Wifi tethering.
-const SETTINGS_WIFI_TETHERING_ENABLED = "tethering.wifi.enabled";
-const SETTINGS_WIFI_SSID = "tethering.wifi.ssid";
-const SETTINGS_WIFI_SECURITY_TYPE = "tethering.wifi.security.type";
-const SETTINGS_WIFI_SECURITY_PASSWORD = "tethering.wifi.security.password";
-const SETTINGS_WIFI_IP = "tethering.wifi.ip";
-const SETTINGS_WIFI_PREFIX = "tethering.wifi.prefix";
-const SETTINGS_WIFI_DHCPSERVER_STARTIP = "tethering.wifi.dhcpserver.startip";
-const SETTINGS_WIFI_DHCPSERVER_ENDIP = "tethering.wifi.dhcpserver.endip";
-const SETTINGS_WIFI_DNS1 = "tethering.wifi.dns1";
-const SETTINGS_WIFI_DNS2 = "tethering.wifi.dns2";
-
-// Settings DB path for USB tethering.
-const SETTINGS_USB_DHCPSERVER_STARTIP = "tethering.usb.dhcpserver.startip";
-const SETTINGS_USB_DHCPSERVER_ENDIP = "tethering.usb.dhcpserver.endip";
-
-// Default value for WIFI tethering.
-const DEFAULT_WIFI_IP = "192.168.1.1";
-const DEFAULT_WIFI_PREFIX = "24";
-const DEFAULT_WIFI_DHCPSERVER_STARTIP = "192.168.1.10";
-const DEFAULT_WIFI_DHCPSERVER_ENDIP = "192.168.1.30";
-const DEFAULT_WIFI_SSID = "FirefoxHotspot";
-const DEFAULT_WIFI_SECURITY_TYPE = "open";
-const DEFAULT_WIFI_SECURITY_PASSWORD = "1234567890";
-const DEFAULT_DNS1 = "8.8.8.8";
-const DEFAULT_DNS2 = "8.8.4.4";
-
-// Default value for USB tethering.
-const DEFAULT_USB_DHCPSERVER_STARTIP = "192.168.0.10";
-const DEFAULT_USB_DHCPSERVER_ENDIP = "192.168.0.30";
-
-const WIFI_FIRMWARE_AP = "AP";
-const WIFI_FIRMWARE_STATION = "STA";
-const WIFI_SECURITY_TYPE_NONE = "open";
-const WIFI_SECURITY_TYPE_WPA_PSK = "wpa-psk";
-const WIFI_SECURITY_TYPE_WPA2_PSK = "wpa2-psk";
-
-const NETWORK_INTERFACE_UP = "up";
-const NETWORK_INTERFACE_DOWN = "down";
-
-const DEFAULT_WLAN_INTERFACE = "wlan0";
-
-const DRIVER_READY_WAIT = 2000;
-
-const SUPP_PROP = "init.svc.wpa_supplicant";
-const WPA_SUPPLICANT = "wpa_supplicant";
-const DHCP_PROP = "init.svc.dhcpcd";
-const DHCP = "dhcpcd";
-
-const MODE_ESS = 0;
-const MODE_IBSS = 1;
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gTetheringService",
- "@mozilla.org/tethering/service;1",
- "nsITetheringService");
-
-// A note about errors and error handling in this file:
-// The libraries that we use in this file are intended for C code. For
-// C code, it is natural to return -1 for errors and 0 for success.
-// Therefore, the code that interacts directly with the worker uses this
-// convention (note: command functions do get boolean results since the
-// command always succeeds and we do a string/boolean check for the
-// expected results).
-var WifiManager = (function() {
- var manager = {};
-
- function getStartupPrefs() {
- return {
- sdkVersion: parseInt(libcutils.property_get("ro.build.version.sdk"), 10),
- unloadDriverEnabled: libcutils.property_get("ro.moz.wifi.unloaddriver") === "1",
- schedScanRecovery: libcutils.property_get("ro.moz.wifi.sched_scan_recover") === "false" ? false : true,
- driverDelay: libcutils.property_get("ro.moz.wifi.driverDelay"),
- p2pSupported: libcutils.property_get("ro.moz.wifi.p2p_supported") === "1",
- eapSimSupported: libcutils.property_get("ro.moz.wifi.eapsim_supported") === "1",
- ibssSupported: libcutils.property_get("ro.moz.wifi.ibss_supported", "true") === "true",
- ifname: libcutils.property_get("wifi.interface")
- };
- }
-
- let {sdkVersion, unloadDriverEnabled, schedScanRecovery,
- driverDelay, p2pSupported, eapSimSupported, ibssSupported, ifname} = getStartupPrefs();
-
- let capabilities = {
- security: ["OPEN", "WEP", "WPA-PSK", "WPA-EAP"],
- eapMethod: ["PEAP", "TTLS", "TLS"],
- eapPhase2: ["MSCHAPV2"],
- certificate: ["SERVER"],
- mode: [MODE_ESS]
- };
- if (eapSimSupported) {
- capabilities.eapMethod.unshift("SIM");
- }
- if (ibssSupported) {
- capabilities.mode.push(MODE_IBSS);
- }
-
- let wifiListener = {
- onWaitEvent: function(event, iface) {
- if (manager.ifname === iface && handleEvent(event)) {
- waitForEvent(iface);
- } else if (p2pSupported) {
- // Please refer to
- // http://androidxref.com/4.4.2_r1/xref/frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java#519
- // for interface event mux/demux rules. In short words, both
- // 'p2p0' and 'p2p-' should go to Wifi P2P state machine.
- if (WifiP2pManager.INTERFACE_NAME === iface || -1 !== iface.indexOf('p2p-')) {
- // If the connection is closed, wifi.c::wifi_wait_for_event()
- // will still return 'CTRL-EVENT-TERMINATING - connection closed'
- // rather than blocking. So when we see this special event string,
- // just return immediately.
- const TERMINATED_EVENT = 'CTRL-EVENT-TERMINATING - connection closed';
- if (-1 !== event.indexOf(TERMINATED_EVENT)) {
- return;
- }
- p2pManager.handleEvent(event);
- waitForEvent(iface);
- }
- }
- },
-
- onCommand: function(event, iface) {
- onmessageresult(event, iface);
- }
- }
-
- manager.ifname = ifname;
- manager.connectToSupplicant = false;
- // Emulator build runs to here.
- // The debug() should only be used after WifiManager.
- if (!ifname) {
- manager.ifname = DEFAULT_WLAN_INTERFACE;
- }
- manager.schedScanRecovery = schedScanRecovery;
- manager.driverDelay = driverDelay ? parseInt(driverDelay, 10) : DRIVER_READY_WAIT;
-
- // Regular Wifi stuff.
- var netUtil = WifiNetUtil(controlMessage);
- var wifiCommand = WifiCommand(controlMessage, manager.ifname, sdkVersion);
-
- // Wifi P2P stuff
- var p2pManager;
- if (p2pSupported) {
- let p2pCommand = WifiCommand(controlMessage, WifiP2pManager.INTERFACE_NAME, sdkVersion);
- p2pManager = WifiP2pManager(p2pCommand, netUtil);
- }
-
- let wifiService = Cc["@mozilla.org/wifi/service;1"];
- if (wifiService) {
- wifiService = wifiService.getService(Ci.nsIWifiProxyService);
- let interfaces = [manager.ifname];
- if (p2pSupported) {
- interfaces.push(WifiP2pManager.INTERFACE_NAME);
- }
- wifiService.start(wifiListener, interfaces, interfaces.length);
- } else {
- debug("No wifi service component available!");
- }
-
- // Callbacks to invoke when a reply arrives from the wifi service.
- var controlCallbacks = Object.create(null);
- var idgen = 0;
-
- function controlMessage(obj, callback) {
- var id = idgen++;
- obj.id = id;
- if (callback) {
- controlCallbacks[id] = callback;
- }
- wifiService.sendCommand(obj, obj.iface);
- }
-
- let onmessageresult = function(data, iface) {
- var id = data.id;
- var callback = controlCallbacks[id];
- if (callback) {
- callback(data);
- delete controlCallbacks[id];
- }
- }
-
- // Polling the status worker
- var recvErrors = 0;
-
- function waitForEvent(iface) {
- wifiService.waitForEvent(iface);
- }
-
- // Commands to the control worker.
-
- var driverLoaded = false;
-
- function loadDriver(callback) {
- if (driverLoaded) {
- callback(0);
- return;
- }
-
- wifiCommand.loadDriver(function (status) {
- driverLoaded = (status >= 0);
- callback(status)
- });
- }
-
- function unloadDriver(type, callback) {
- if (!unloadDriverEnabled) {
- // Unloading drivers is generally unnecessary and
- // can trigger bugs in some drivers.
- // On properly written drivers, bringing the interface
- // down powers down the interface.
- if (type === WIFI_FIRMWARE_STATION) {
- notify("supplicantlost", { success: true });
- }
- callback(0);
- return;
- }
-
- wifiCommand.unloadDriver(function(status) {
- driverLoaded = (status < 0);
- if (type === WIFI_FIRMWARE_STATION) {
- notify("supplicantlost", { success: true });
- }
- callback(status);
- });
- }
-
- // A note about background scanning:
- // Normally, background scanning shouldn't be necessary as wpa_supplicant
- // has the capability to automatically schedule its own scans at appropriate
- // intervals. However, with some drivers, this appears to get stuck after
- // three scans, so we enable the driver's background scanning to work around
- // that when we're not connected to any network. This ensures that we'll
- // automatically reconnect to networks if one falls out of range.
- var reEnableBackgroundScan = false;
-
- // NB: This is part of the internal API.
- manager.backgroundScanEnabled = false;
- function setBackgroundScan(enable, callback) {
- var doEnable = (enable === "ON");
- if (doEnable === manager.backgroundScanEnabled) {
- callback(false, true);
- return;
- }
-
- manager.backgroundScanEnabled = doEnable;
- wifiCommand.setBackgroundScan(manager.backgroundScanEnabled, callback);
- }
-
- var scanModeActive = false;
-
- function scan(forceActive, callback) {
- if (forceActive && !scanModeActive) {
- // Note: we ignore errors from doSetScanMode.
- wifiCommand.doSetScanMode(true, function(ignore) {
- setBackgroundScan("OFF", function(turned, ignore) {
- reEnableBackgroundScan = turned;
- manager.handlePreWifiScan();
- wifiCommand.scan(function(ok) {
- wifiCommand.doSetScanMode(false, function(ignore) {
- // The result of scanCommand is the result of the actual SCAN
- // request.
- callback(ok);
- });
- });
- });
- });
- return;
- }
- manager.handlePreWifiScan();
- wifiCommand.scan(callback);
- }
-
- var debugEnabled = false;
-
- function syncDebug() {
- if (debugEnabled !== DEBUG) {
- let wanted = DEBUG;
- wifiCommand.setLogLevel(wanted ? "DEBUG" : "INFO", function(ok) {
- if (ok)
- debugEnabled = wanted;
- });
- if (p2pSupported && p2pManager) {
- p2pManager.setDebug(DEBUG);
- }
- }
- }
-
- function getDebugEnabled(callback) {
- wifiCommand.getLogLevel(function(level) {
- if (level === null) {
- debug("Unable to get wpa_supplicant's log level");
- callback(false);
- return;
- }
-
- var lines = level.split("\n");
- for (let i = 0; i < lines.length; ++i) {
- let match = /Current level: (.*)/.exec(lines[i]);
- if (match) {
- debugEnabled = match[1].toLowerCase() === "debug";
- callback(true);
- return;
- }
- }
-
- // If we're here, we didn't get the current level.
- callback(false);
- });
- }
-
- function setScanMode(setActive, callback) {
- scanModeActive = setActive;
- wifiCommand.doSetScanMode(setActive, callback);
- }
-
- var httpProxyConfig = Object.create(null);
-
- /**
- * Given a network, configure http proxy when using wifi.
- * @param network A network object to update http proxy
- * @param info Info should have following field:
- * - httpProxyHost ip address of http proxy.
- * - httpProxyPort port of http proxy, set 0 to use default port 8080.
- * @param callback callback function.
- */
- function configureHttpProxy(network, info, callback) {
- if (!network)
- return;
-
- let networkKey = getNetworkKey(network);
-
- if (!info || info.httpProxyHost === "") {
- delete httpProxyConfig[networkKey];
- } else {
- httpProxyConfig[networkKey] = network;
- httpProxyConfig[networkKey].httpProxyHost = info.httpProxyHost;
- httpProxyConfig[networkKey].httpProxyPort = info.httpProxyPort;
- }
-
- callback(true);
- }
-
- function getHttpProxyNetwork(network) {
- if (!network)
- return null;
-
- let networkKey = getNetworkKey(network);
- return httpProxyConfig[networkKey];
- }
-
- function setHttpProxy(network) {
- if (!network)
- return;
-
- // If we got here, arg network must be the currentNetwork, so we just update
- // WifiNetworkInterface correspondingly and notify NetworkManager.
- WifiNetworkInterface.httpProxyHost = network.httpProxyHost;
- WifiNetworkInterface.httpProxyPort = network.httpProxyPort;
-
- if (WifiNetworkInterface.info.state ==
- Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- gNetworkManager.updateNetworkInterface(WifiNetworkInterface);
- }
- }
-
- var staticIpConfig = Object.create(null);
- function setStaticIpMode(network, info, callback) {
- let setNetworkKey = getNetworkKey(network);
- let curNetworkKey = null;
- let currentNetwork = Object.create(null);
- currentNetwork.netId = manager.connectionInfo.id;
-
- manager.getNetworkConfiguration(currentNetwork, function () {
- curNetworkKey = getNetworkKey(currentNetwork);
-
- // Add additional information to static ip configuration
- // It is used to compatiable with information dhcp callback.
- info.ipaddr = netHelpers.stringToIP(info.ipaddr_str);
- info.gateway = netHelpers.stringToIP(info.gateway_str);
- info.mask_str = netHelpers.ipToString(netHelpers.makeMask(info.maskLength));
-
- // Optional
- info.dns1 = netHelpers.stringToIP(info.dns1_str);
- info.dns2 = netHelpers.stringToIP(info.dns2_str);
- info.proxy = netHelpers.stringToIP(info.proxy_str);
-
- staticIpConfig[setNetworkKey] = info;
-
- // If the ssid of current connection is the same as configured ssid
- // It means we need update current connection to use static IP address.
- if (setNetworkKey == curNetworkKey) {
- // Use configureInterface directly doesn't work, the network interface
- // and routing table is changed but still cannot connect to network
- // so the workaround here is disable interface the enable again to
- // trigger network reconnect with static ip.
- gNetworkService.disableInterface(manager.ifname, function (ok) {
- gNetworkService.enableInterface(manager.ifname, function (ok) {
- callback(ok);
- });
- });
- return;
- }
-
- callback(true);
- });
- }
-
- var dhcpInfo = null;
-
- function runStaticIp(ifname, key) {
- debug("Run static ip");
-
- // Read static ip information from settings.
- let staticIpInfo;
-
- if (!(key in staticIpConfig))
- return;
-
- staticIpInfo = staticIpConfig[key];
-
- // Stop dhcpd when use static IP
- if (dhcpInfo != null) {
- netUtil.stopDhcp(manager.ifname, function() {});
- }
-
- // Set ip, mask length, gateway, dns to network interface
- gNetworkService.configureInterface( { ifname: ifname,
- ipaddr: staticIpInfo.ipaddr,
- mask: staticIpInfo.maskLength,
- gateway: staticIpInfo.gateway,
- dns1: staticIpInfo.dns1,
- dns2: staticIpInfo.dns2 }, function (data) {
- netUtil.runIpConfig(ifname, staticIpInfo, function(data) {
- dhcpInfo = data.info;
- notify("networkconnected", data);
- });
- });
- }
-
- var suppressEvents = false;
- function notify(eventName, eventObject) {
- if (suppressEvents)
- return;
- var handler = manager["on" + eventName];
- if (handler) {
- if (!eventObject)
- eventObject = ({});
- handler.call(eventObject);
- }
- }
-
- function notifyStateChange(fields) {
- // If we're already in the COMPLETED state, we might receive events from
- // the supplicant that tell us that we're re-authenticating or reminding
- // us that we're associated to a network. In those cases, we don't need to
- // do anything, so just ignore them.
- if (manager.state === "COMPLETED" &&
- fields.state !== "DISCONNECTED" &&
- fields.state !== "INTERFACE_DISABLED" &&
- fields.state !== "INACTIVE" &&
- fields.state !== "SCANNING") {
- return false;
- }
-
- // Stop background scanning if we're trying to connect to a network.
- if (manager.backgroundScanEnabled &&
- (fields.state === "ASSOCIATING" ||
- fields.state === "ASSOCIATED" ||
- fields.state === "FOUR_WAY_HANDSHAKE" ||
- fields.state === "GROUP_HANDSHAKE" ||
- fields.state === "COMPLETED")) {
- setBackgroundScan("OFF", function() {});
- }
-
- fields.prevState = manager.state;
- // Detect wpa_supplicant's loop iterations.
- manager.supplicantLoopDetection(fields.prevState, fields.state);
- notify("statechange", fields);
-
- // Don't update state when and after disabling.
- if (manager.state === "DISABLING" ||
- manager.state === "UNINITIALIZED") {
- return false;
- }
-
- manager.state = fields.state;
- return true;
- }
-
- function parseStatus(status) {
- if (status === null) {
- debug("Unable to get wpa supplicant's status");
- return;
- }
-
- var ssid;
- var bssid;
- var state;
- var ip_address;
- var id;
-
- var lines = status.split("\n");
- for (let i = 0; i < lines.length; ++i) {
- let [key, value] = lines[i].split("=");
- switch (key) {
- case "wpa_state":
- state = value;
- break;
- case "ssid":
- ssid = value;
- break;
- case "bssid":
- bssid = value;
- break;
- case "ip_address":
- ip_address = value;
- break;
- case "id":
- id = value;
- break;
- }
- }
-
- if (bssid && ssid) {
- manager.connectionInfo.bssid = bssid;
- manager.connectionInfo.ssid = ssid;
- manager.connectionInfo.id = id;
- }
-
- if (ip_address)
- dhcpInfo = { ip_address: ip_address };
-
- notifyStateChange({ state: state, fromStatus: true });
-
- // If we parse the status and the supplicant has already entered the
- // COMPLETED state, then we need to set up DHCP right away.
- if (state === "COMPLETED")
- onconnected();
- }
-
- // try to connect to the supplicant
- var connectTries = 0;
- var retryTimer = null;
- function connectCallback(ok) {
- if (ok === 0) {
- // Tell the event worker to start waiting for events.
- retryTimer = null;
- connectTries = 0;
- recvErrors = 0;
- manager.connectToSupplicant = true;
- didConnectSupplicant(function(){});
- return;
- }
- if (connectTries++ < 5) {
- // Try again in 1 seconds.
- if (!retryTimer)
- retryTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- retryTimer.initWithCallback(function(timer) {
- wifiCommand.connectToSupplicant(connectCallback);
- }, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
- return;
- }
-
- retryTimer = null;
- connectTries = 0;
- notify("supplicantlost", { success: false });
- }
-
- manager.connectionDropped = function(callback) {
- // Reset network interface when connection drop
- gNetworkService.configureInterface( { ifname: manager.ifname,
- ipaddr: 0,
- mask: 0,
- gateway: 0,
- dns1: 0,
- dns2: 0 }, function (data) {
- });
-
- // If we got disconnected, kill the DHCP client in preparation for
- // reconnection.
- gNetworkService.resetConnections(manager.ifname, function() {
- netUtil.stopDhcp(manager.ifname, function() {
- callback();
- });
- });
- }
-
- manager.start = function() {
- debug("detected SDK version " + sdkVersion);
- wifiCommand.connectToSupplicant(connectCallback);
- }
-
- let dhcpRequestGen = 0;
-
- function onconnected() {
- // For now we do our own DHCP. In the future, this should be handed
- // off to the Network Manager.
- let currentNetwork = Object.create(null);
- currentNetwork.netId = manager.connectionInfo.id;
-
- manager.getNetworkConfiguration(currentNetwork, function (){
- let key = getNetworkKey(currentNetwork);
- if (staticIpConfig &&
- (key in staticIpConfig) &&
- staticIpConfig[key].enabled) {
- debug("Run static ip");
- runStaticIp(manager.ifname, key);
- return;
- }
- netUtil.runDhcp(manager.ifname, dhcpRequestGen++, function(data, gen) {
- dhcpInfo = data.info;
- debug('dhcpRequestGen: ' + dhcpRequestGen + ', gen: ' + gen);
- if (!dhcpInfo) {
- if (gen + 1 < dhcpRequestGen) {
- debug('Do not bother younger DHCP request.');
- return;
- }
- if (++manager.dhcpFailuresCount >= MAX_RETRIES_ON_DHCP_FAILURE) {
- manager.dhcpFailuresCount = 0;
- notify("disconnected", {connectionInfo: manager.connectionInfo});
- return;
- }
- // NB: We have to call disconnect first. Otherwise, we only reauth with
- // the existing AP and don't retrigger DHCP.
- manager.disconnect(function() {
- manager.reassociate(function(){});
- });
- return;
- }
-
- manager.dhcpFailuresCount = 0;
- notify("networkconnected", data);
- });
- });
- }
-
- var supplicantStatesMap = (sdkVersion >= 15) ?
- ["DISCONNECTED", "INTERFACE_DISABLED", "INACTIVE", "SCANNING",
- "AUTHENTICATING", "ASSOCIATING", "ASSOCIATED", "FOUR_WAY_HANDSHAKE",
- "GROUP_HANDSHAKE", "COMPLETED"]
- :
- ["DISCONNECTED", "INACTIVE", "SCANNING", "ASSOCIATING",
- "ASSOCIATED", "FOUR_WAY_HANDSHAKE", "GROUP_HANDSHAKE",
- "COMPLETED", "DORMANT", "UNINITIALIZED"];
-
- var driverEventMap = { STOPPED: "driverstopped", STARTED: "driverstarted", HANGED: "driverhung" };
-
- manager.getNetworkId = function (ssid, callback) {
- manager.getConfiguredNetworks(function(networks) {
- if (!networks) {
- debug("Unable to get configured networks");
- return callback(null);
- }
- for (let net in networks) {
- let network = networks[net];
- // Trying to get netId from
- // 1. network matching SSID if SSID is provided.
- // 2. current network if no SSID is provided, it's not guaranteed that
- // current network matches requested SSID.
- if ((!ssid && network.status === "CURRENT") ||
- (ssid && network.ssid && ssid === dequote(network.ssid))) {
- return callback(net);
- }
- }
- callback(null);
- });
- }
-
- function handleWpaEapEvents(event) {
- if (event.indexOf("CTRL-EVENT-EAP-FAILURE") !== -1) {
- if (event.indexOf("EAP authentication failed") !== -1) {
- notify("passwordmaybeincorrect");
- if (manager.authenticationFailuresCount > MAX_RETRIES_ON_AUTHENTICATION_FAILURE) {
- manager.authenticationFailuresCount = 0;
- notify("disconnected", {connectionInfo: manager.connectionInfo});
- }
- }
- return true;
- }
- if (event.indexOf("CTRL-EVENT-EAP-TLS-CERT-ERROR") !== -1) {
- // Cert Error
- notify("passwordmaybeincorrect");
- if (manager.authenticationFailuresCount > MAX_RETRIES_ON_AUTHENTICATION_FAILURE) {
- manager.authenticationFailuresCount = 0;
- notify("disconnected", {connectionInfo: manager.connectionInfo});
- }
- return true;
- }
- if (event.indexOf("CTRL-EVENT-EAP-STARTED") !== -1) {
- notifyStateChange({ state: "AUTHENTICATING" });
- return true;
- }
- return true;
- }
-
- // Handle events sent to us by the event worker.
- function handleEvent(event) {
- debug("Event coming in: " + event);
- if (event.indexOf("CTRL-EVENT-") !== 0 && event.indexOf("WPS") !== 0) {
- // Handle connection fail exception on WEP-128, while password length
- // is not 5 nor 13 bytes.
- if (event.indexOf("Association request to the driver failed") !== -1) {
- notify("passwordmaybeincorrect");
- if (manager.authenticationFailuresCount > MAX_RETRIES_ON_AUTHENTICATION_FAILURE) {
- manager.authenticationFailuresCount = 0;
- notify("disconnected", {connectionInfo: manager.connectionInfo});
- }
- return true;
- }
-
- if (event.indexOf("WPA:") == 0 &&
- event.indexOf("pre-shared key may be incorrect") != -1) {
- notify("passwordmaybeincorrect");
- }
-
- // This is ugly, but we need to grab the SSID here. BSSID is not guaranteed
- // to be provided, so don't grab BSSID here.
- var match = /Trying to associate with.*SSID[ =]'(.*)'/.exec(event);
- if (match) {
- debug("Matched: " + match[1] + "\n");
- manager.connectionInfo.ssid = match[1];
- }
- return true;
- }
-
- var space = event.indexOf(" ");
- var eventData = event.substr(0, space + 1);
- if (eventData.indexOf("CTRL-EVENT-STATE-CHANGE") === 0) {
- // Parse the event data.
- var fields = {};
- var tokens = event.substr(space + 1).split(" ");
- for (var n = 0; n < tokens.length; ++n) {
- var kv = tokens[n].split("=");
- if (kv.length === 2)
- fields[kv[0]] = kv[1];
- }
- if (!("state" in fields))
- return true;
- fields.state = supplicantStatesMap[fields.state];
-
- // The BSSID field is only valid in the ASSOCIATING and ASSOCIATED
- // states, except when we "reauth", except this seems to depend on the
- // driver, so simply check to make sure that we don't have a null BSSID.
- if (fields.BSSID !== "00:00:00:00:00:00")
- manager.connectionInfo.bssid = fields.BSSID;
-
- if (notifyStateChange(fields) && fields.state === "COMPLETED") {
- onconnected();
- }
- return true;
- }
- if (eventData.indexOf("CTRL-EVENT-DRIVER-STATE") === 0) {
- var handlerName = driverEventMap[eventData];
- if (handlerName)
- notify(handlerName);
- return true;
- }
- if (eventData.indexOf("CTRL-EVENT-TERMINATING") === 0) {
- // As long the monitor socket is not closed and we haven't seen too many
- // recv errors yet, we will keep going for a bit longer.
- if (event.indexOf("connection closed") === -1 &&
- event.indexOf("recv error") !== -1 && ++recvErrors < 10)
- return true;
-
- notifyStateChange({ state: "DISCONNECTED", BSSID: null, id: -1 });
-
- // If the supplicant is terminated as commanded, the supplicant lost
- // notification will be sent after driver unloaded. In such case, the
- // manager state will be "DISABLING" or "UNINITIALIZED".
- // So if supplicant terminated with incorrect manager state, implying
- // unexpected condition, we should notify supplicant lost here.
- if (manager.state !== "DISABLING" && manager.state !== "UNINITIALIZED") {
- notify("supplicantlost", { success: true });
- }
-
- if (manager.stopSupplicantCallback) {
- cancelWaitForTerminateEventTimer();
- // It's possible that the terminating event triggered by timer comes
- // earlier than the event from wpa_supplicant. Since
- // stopSupplicantCallback contains async. callbacks, swap it to local
- // to prevent calling the callback twice.
- let stopSupplicantCallback = manager.stopSupplicantCallback.bind(manager);
- manager.stopSupplicantCallback = null;
- stopSupplicantCallback();
- stopSupplicantCallback = null;
- }
- return false;
- }
- if (eventData.indexOf("CTRL-EVENT-DISCONNECTED") === 0) {
- var token = event.split(" ")[1];
- var bssid = token.split("=")[1];
- if (manager.authenticationFailuresCount > MAX_RETRIES_ON_AUTHENTICATION_FAILURE) {
- manager.authenticationFailuresCount = 0;
- notify("disconnected", {connectionInfo: manager.connectionInfo});
- }
- manager.connectionInfo.bssid = null;
- manager.connectionInfo.ssid = null;
- manager.connectionInfo.id = -1;
- return true;
- }
- if (eventData.indexOf("CTRL-EVENT-CONNECTED") === 0) {
- // Format: CTRL-EVENT-CONNECTED - Connection to 00:1e:58:ec:d5:6d completed (reauth) [id=1 id_str=]
- var bssid = event.split(" ")[4];
-
- var keyword = "id=";
- var id = event.substr(event.indexOf(keyword) + keyword.length).split(" ")[0];
- // Read current BSSID here, it will always being provided.
- manager.connectionInfo.id = id;
- manager.connectionInfo.bssid = bssid;
- return true;
- }
- if (eventData.indexOf("CTRL-EVENT-SCAN-RESULTS") === 0) {
- debug("Notifying of scan results available");
- if (reEnableBackgroundScan) {
- reEnableBackgroundScan = false;
- setBackgroundScan("ON", function() {});
- }
- manager.handlePostWifiScan();
- notify("scanresultsavailable");
- return true;
- }
- if (eventData.indexOf("CTRL-EVENT-EAP") === 0) {
- return handleWpaEapEvents(event);
- }
- if (eventData.indexOf("CTRL-EVENT-ASSOC-REJECT") === 0) {
- debug("CTRL-EVENT-ASSOC-REJECT: network error");
- notify("passwordmaybeincorrect");
- if (manager.authenticationFailuresCount > MAX_RETRIES_ON_AUTHENTICATION_FAILURE) {
- manager.authenticationFailuresCount = 0;
- debug("CTRL-EVENT-ASSOC-REJECT: disconnect network");
- notify("disconnected", {connectionInfo: manager.connectionInfo});
- }
- return true;
- }
- if (eventData.indexOf("WPS-TIMEOUT") === 0) {
- notifyStateChange({ state: "WPS_TIMEOUT", BSSID: null, id: -1 });
- return true;
- }
- if (eventData.indexOf("WPS-FAIL") === 0) {
- notifyStateChange({ state: "WPS_FAIL", BSSID: null, id: -1 });
- return true;
- }
- if (eventData.indexOf("WPS-OVERLAP-DETECTED") === 0) {
- notifyStateChange({ state: "WPS_OVERLAP_DETECTED", BSSID: null, id: -1 });
- return true;
- }
- // Unknown event.
- return true;
- }
-
- function setPowerSavingMode(enabled) {
- let mode = enabled ? "AUTO" : "ACTIVE";
- // Some wifi drivers may not implement this command. Set power mode
- // even if suspend optimization command failed.
- manager.setSuspendOptimizations(enabled, function(ok) {
- manager.setPowerMode(mode, function() {});
- });
- }
-
- function didConnectSupplicant(callback) {
- waitForEvent(manager.ifname);
-
- // Load up the supplicant state.
- getDebugEnabled(function(ok) {
- syncDebug();
- });
- wifiCommand.status(function(status) {
- parseStatus(status);
- notify("supplicantconnection");
- callback();
- });
- // WPA supplicant already connected.
- manager.setPowerSavingMode(true);
- if (p2pSupported) {
- manager.enableP2p(function(success) {});
- }
- }
-
- function prepareForStartup(callback) {
- let status = libcutils.property_get(DHCP_PROP + "_" + manager.ifname);
- if (status !== "running") {
- tryStopSupplicant();
- return;
- }
- manager.connectionDropped(function() {
- tryStopSupplicant();
- });
-
- // Ignore any errors and kill any currently-running supplicants. On some
- // phones, stopSupplicant won't work for a supplicant that we didn't
- // start, so we hand-roll it here.
- function tryStopSupplicant () {
- let status = libcutils.property_get(SUPP_PROP);
- if (status !== "running") {
- callback();
- return;
- }
- suppressEvents = true;
- wifiCommand.killSupplicant(function() {
- gNetworkService.disableInterface(manager.ifname, function (ok) {
- suppressEvents = false;
- callback();
- });
- });
- }
- }
-
- // Initial state.
- manager.state = "UNINITIALIZED";
- manager.tetheringState = "UNINITIALIZED";
- manager.supplicantStarted = false;
- manager.connectionInfo = { ssid: null, bssid: null, id: -1 };
- manager.authenticationFailuresCount = 0;
- manager.loopDetectionCount = 0;
- manager.dhcpFailuresCount = 0;
- manager.stopSupplicantCallback = null;
-
- manager.__defineGetter__("enabled", function() {
- switch (manager.state) {
- case "UNINITIALIZED":
- case "INITIALIZING":
- case "DISABLING":
- return false;
- default:
- return true;
- }
- });
-
- var waitForTerminateEventTimer = null;
- function cancelWaitForTerminateEventTimer() {
- if (waitForTerminateEventTimer) {
- waitForTerminateEventTimer.cancel();
- waitForTerminateEventTimer = null;
- }
- };
- function createWaitForTerminateEventTimer(onTimeout) {
- if (waitForTerminateEventTimer) {
- return;
- }
- waitForTerminateEventTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- waitForTerminateEventTimer.initWithCallback(onTimeout,
- 4000,
- Ci.nsITimer.TYPE_ONE_SHOT);
- };
-
- var waitForDriverReadyTimer = null;
- function cancelWaitForDriverReadyTimer() {
- if (waitForDriverReadyTimer) {
- waitForDriverReadyTimer.cancel();
- waitForDriverReadyTimer = null;
- }
- };
- function createWaitForDriverReadyTimer(onTimeout) {
- waitForDriverReadyTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- waitForDriverReadyTimer.initWithCallback(onTimeout,
- manager.driverDelay,
- Ci.nsITimer.TYPE_ONE_SHOT);
- };
-
- // Public interface of the wifi service.
- manager.setWifiEnabled = function(enabled, callback) {
- if (enabled === manager.isWifiEnabled(manager.state)) {
- callback("no change");
- return;
- }
-
- if (enabled) {
- manager.state = "INITIALIZING";
- // Register as network interface.
- WifiNetworkInterface.info.name = manager.ifname;
- if (!WifiNetworkInterface.registered) {
- gNetworkManager.registerNetworkInterface(WifiNetworkInterface);
- WifiNetworkInterface.registered = true;
- }
- WifiNetworkInterface.info.state =
- Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
- WifiNetworkInterface.info.ips = [];
- WifiNetworkInterface.info.prefixLengths = [];
- WifiNetworkInterface.info.gateways = [];
- WifiNetworkInterface.info.dnses = [];
- gNetworkManager.updateNetworkInterface(WifiNetworkInterface);
-
- prepareForStartup(function() {
- loadDriver(function (status) {
- if (status < 0) {
- callback(status);
- manager.state = "UNINITIALIZED";
- return;
- }
- // This command is mandatory for Nexus 4. But some devices like
- // Galaxy S2 don't support it. Continue to start wpa_supplicant
- // even if we fail to set wifi operation mode to station.
- gNetworkService.setWifiOperationMode(manager.ifname,
- WIFI_FIRMWARE_STATION,
- function (status) {
-
- function startSupplicantInternal() {
- wifiCommand.startSupplicant(function (status) {
- if (status < 0) {
- unloadDriver(WIFI_FIRMWARE_STATION, function() {
- callback(status);
- });
- manager.state = "UNINITIALIZED";
- return;
- }
-
- manager.supplicantStarted = true;
- gNetworkService.enableInterface(manager.ifname, function (ok) {
- callback(ok ? 0 : -1);
- });
- });
- }
-
- function doStartSupplicant() {
- cancelWaitForDriverReadyTimer();
-
- if (!manager.connectToSupplicant) {
- startSupplicantInternal();
- return;
- }
- wifiCommand.closeSupplicantConnection(function () {
- manager.connectToSupplicant = false;
- // closeSupplicantConnection() will trigger onsupplicantlost
- // and set manager.state to "UNINITIALIZED", we have to
- // restore it here.
- manager.state = "INITIALIZING";
- startSupplicantInternal();
- });
- }
- // Driver startup on certain platforms takes longer than it takes for us
- // to return from loadDriver, so wait 2 seconds before starting
- // the supplicant to give it a chance to start.
- if (manager.driverDelay > 0) {
- createWaitForDriverReadyTimer(doStartSupplicant);
- } else {
- doStartSupplicant();
- }
- });
- });
- });
- } else {
- manager.state = "DISABLING";
- // Note these following calls ignore errors. If we fail to kill the
- // supplicant gracefully, then we need to continue telling it to die
- // until it does.
- let doDisableWifi = function() {
- manager.stopSupplicantCallback = (function () {
- wifiCommand.stopSupplicant(function (status) {
- wifiCommand.closeSupplicantConnection(function() {
- manager.connectToSupplicant = false;
- manager.state = "UNINITIALIZED";
- gNetworkService.disableInterface(manager.ifname, function (ok) {
- unloadDriver(WIFI_FIRMWARE_STATION, callback);
- });
- });
- });
- }).bind(this);
-
- let terminateEventCallback = (function() {
- handleEvent("CTRL-EVENT-TERMINATING");
- }).bind(this);
- createWaitForTerminateEventTimer(terminateEventCallback);
-
- // We are going to terminate the connection between wpa_supplicant.
- // Stop the polling timer immediately to prevent connection info update
- // command blocking in control thread until socket timeout.
- notify("stopconnectioninfotimer");
-
- wifiCommand.terminateSupplicant(function (ok) {
- manager.connectionDropped(function () {
- });
- });
- }
-
- if (p2pSupported) {
- p2pManager.setEnabled(false, { onDisabled: doDisableWifi });
- } else {
- doDisableWifi();
- }
- }
- }
-
- var wifiHotspotStatusTimer = null;
- function cancelWifiHotspotStatusTimer() {
- if (wifiHotspotStatusTimer) {
- wifiHotspotStatusTimer.cancel();
- wifiHotspotStatusTimer = null;
- }
- }
-
- function createWifiHotspotStatusTimer(onTimeout) {
- wifiHotspotStatusTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- wifiHotspotStatusTimer.init(onTimeout, 5000, Ci.nsITimer.TYPE_REPEATING_SLACK);
- }
-
- // Get wifi interface and load wifi driver when enable Ap mode.
- manager.setWifiApEnabled = function(enabled, configuration, callback) {
- if (enabled === manager.isWifiTetheringEnabled(manager.tetheringState)) {
- callback("no change");
- return;
- }
-
- if (enabled) {
- manager.tetheringState = "INITIALIZING";
- loadDriver(function (status) {
- if (status < 0) {
- callback();
- manager.tetheringState = "UNINITIALIZED";
- if (wifiHotspotStatusTimer) {
- cancelWifiHotspotStatusTimer();
- wifiCommand.closeHostapdConnection(function(result) {
- });
- }
- return;
- }
-
- function getWifiHotspotStatus() {
- wifiCommand.hostapdGetStations(function(result) {
- notify("stationinfoupdate", {station: result});
- });
- }
-
- function doStartWifiTethering() {
- cancelWaitForDriverReadyTimer();
- WifiNetworkInterface.info.name =
- libcutils.property_get("wifi.tethering.interface", manager.ifname);
- gTetheringService.setWifiTethering(enabled,
- WifiNetworkInterface.info.name,
- configuration, function(result) {
- if (result) {
- manager.tetheringState = "UNINITIALIZED";
- } else {
- manager.tetheringState = "COMPLETED";
- wifiCommand.connectToHostapd(function(result) {
- if (result) {
- return;
- }
- // Create a timer to track the connection status.
- createWifiHotspotStatusTimer(getWifiHotspotStatus);
- });
- }
- // Pop out current request.
- callback();
- // Should we fire a dom event if we fail to set wifi tethering ?
- debug("Enable Wifi tethering result: " + (result ? result : "successfully"));
- });
- }
-
- // Driver startup on certain platforms takes longer than it takes
- // for us to return from loadDriver, so wait 2 seconds before
- // turning on Wifi tethering.
- createWaitForDriverReadyTimer(doStartWifiTethering);
- });
- } else {
- cancelWifiHotspotStatusTimer();
- gTetheringService.setWifiTethering(enabled, WifiNetworkInterface,
- configuration, function(result) {
- // Should we fire a dom event if we fail to set wifi tethering ?
- debug("Disable Wifi tethering result: " + (result ? result : "successfully"));
- // Unload wifi driver even if we fail to control wifi tethering.
- unloadDriver(WIFI_FIRMWARE_AP, function(status) {
- if (status < 0) {
- debug("Fail to unload wifi driver");
- }
- manager.tetheringState = "UNINITIALIZED";
- callback();
- });
- });
- }
- }
-
- manager.disconnect = wifiCommand.disconnect;
- manager.reconnect = wifiCommand.reconnect;
- manager.reassociate = wifiCommand.reassociate;
-
- var networkConfigurationFields = [
- {name: "ssid", type: "string"},
- {name: "bssid", type: "string"},
- {name: "psk", type: "string"},
- {name: "wep_key0", type: "string"},
- {name: "wep_key1", type: "string"},
- {name: "wep_key2", type: "string"},
- {name: "wep_key3", type: "string"},
- {name: "wep_tx_keyidx", type: "integer"},
- {name: "priority", type: "integer"},
- {name: "key_mgmt", type: "string"},
- {name: "scan_ssid", type: "string"},
- {name: "disabled", type: "integer"},
- {name: "identity", type: "string"},
- {name: "password", type: "string"},
- {name: "auth_alg", type: "string"},
- {name: "phase1", type: "string"},
- {name: "phase2", type: "string"},
- {name: "eap", type: "string"},
- {name: "pin", type: "string"},
- {name: "pcsc", type: "string"},
- {name: "ca_cert", type: "string"},
- {name: "subject_match", type: "string"},
- {name: "client_cert", type: "string"},
- {name: "private_key", type: "stirng"},
- {name: "engine", type: "integer"},
- {name: "engine_id", type: "string"},
- {name: "key_id", type: "string"},
- {name: "frequency", type: "integer"},
- {name: "mode", type: "integer"}
- ];
- // These fields are only handled in IBSS (aka ad-hoc) mode
- var ibssNetworkConfigurationFields = [
- "frequency", "mode"
- ];
-
- manager.getNetworkConfiguration = function(config, callback) {
- var netId = config.netId;
- var done = 0;
- for (var n = 0; n < networkConfigurationFields.length; ++n) {
- let fieldName = networkConfigurationFields[n].name;
- let fieldType = networkConfigurationFields[n].type;
- wifiCommand.getNetworkVariable(netId, fieldName, function(value) {
- if (value !== null) {
- if (fieldType === "integer") {
- config[fieldName] = parseInt(value, 10);
- } else if ( fieldName == "ssid" && value[0] != '"' ) {
- // SET_NETWORK will set a quoted ssid to wpa_supplicant.
- // But if ssid contains non-ascii char, it will be converted into utf-8.
- // For example: "Test的wifi" --> 54657374e79a8477696669
- // When GET_NETWORK receive a un-quoted utf-8 ssid, it must be decoded and quoted.
- config[fieldName] = quote(decodeURIComponent(value.replace(/[0-9a-f]{2}/g, '%$&')));
- } else {
- // value is string type by default.
- config[fieldName] = value;
- }
- }
- if (++done == networkConfigurationFields.length)
- callback(config);
- });
- }
- }
- manager.setNetworkConfiguration = function(config, callback) {
- var netId = config.netId;
- var done = 0;
- var errors = 0;
-
- function hasValidProperty(name) {
- return ((name in config) &&
- config[name] != null &&
- (["password", "wep_key0", "psk"].indexOf(name) === -1 ||
- config[name] !== '*'));
- }
-
- function getModeFromConfig() {
- /* we use the mode from the config, or ESS as default */
- return hasValidProperty("mode") ? config["mode"] : MODE_ESS;
- }
-
- var mode = getModeFromConfig();
-
- function validForMode(name, mode) {
- /* all fields are valid for IBSS */
- return (mode == MODE_IBSS) ||
- /* IBSS fields are not valid for ESS */
- ((mode == MODE_ESS) && !(name in ibssNetworkConfigurationFields));
- }
-
- for (var n = 0; n < networkConfigurationFields.length; ++n) {
- let fieldName = networkConfigurationFields[n].name;
- if (!hasValidProperty(fieldName) || !validForMode(fieldName, mode)) {
- ++done;
- } else {
- wifiCommand.setNetworkVariable(netId, fieldName, config[fieldName], function(ok) {
- if (!ok)
- ++errors;
- if (++done == networkConfigurationFields.length)
- callback(errors == 0);
- });
- }
- }
- // If config didn't contain any of the fields we want, don't lose the error callback.
- if (done == networkConfigurationFields.length)
- callback(false);
- }
- manager.getConfiguredNetworks = function(callback) {
- wifiCommand.listNetworks(function (reply) {
- var networks = Object.create(null);
- var lines = reply ? reply.split("\n") : 0;
- if (lines.length <= 1) {
- // We need to make sure we call the callback even if there are no
- // configured networks.
- callback(networks);
- return;
- }
-
- var done = 0;
- var errors = 0;
- for (var n = 1; n < lines.length; ++n) {
- var result = lines[n].split("\t");
- var netId = parseInt(result[0], 10);
- var config = networks[netId] = { netId: netId };
- switch (result[3]) {
- case "[CURRENT]":
- config.status = "CURRENT";
- break;
- case "[DISABLED]":
- config.status = "DISABLED";
- break;
- default:
- config.status = "ENABLED";
- break;
- }
- manager.getNetworkConfiguration(config, function (ok) {
- if (!ok)
- ++errors;
- if (++done == lines.length - 1) {
- if (errors) {
- // If an error occured, delete the new netId.
- wifiCommand.removeNetwork(netId, function() {
- callback(null);
- });
- } else {
- callback(networks);
- }
- }
- });
- }
- });
- }
- manager.addNetwork = function(config, callback) {
- wifiCommand.addNetwork(function (netId) {
- config.netId = netId;
- manager.setNetworkConfiguration(config, function (ok) {
- if (!ok) {
- wifiCommand.removeNetwork(netId, function() { callback(false); });
- return;
- }
-
- callback(ok);
- });
- });
- }
- manager.updateNetwork = function(config, callback) {
- manager.setNetworkConfiguration(config, callback);
- }
- manager.removeNetwork = function(netId, callback) {
- wifiCommand.removeNetwork(netId, callback);
- }
-
- manager.saveConfig = function(callback) {
- wifiCommand.saveConfig(callback);
- }
- manager.enableNetwork = function(netId, disableOthers, callback) {
- if (p2pSupported) {
- // We have to stop wifi direct scan before associating to an AP.
- // Otherwise we will get a "REJECT" wpa supplicant event.
- p2pManager.setScanEnabled(false, function(success) {});
- }
- wifiCommand.enableNetwork(netId, disableOthers, callback);
- }
- manager.disableNetwork = function(netId, callback) {
- wifiCommand.disableNetwork(netId, callback);
- }
- manager.getMacAddress = wifiCommand.getMacAddress;
- manager.getScanResults = wifiCommand.scanResults;
- manager.setScanMode = function(mode, callback) {
- setScanMode(mode === "active", callback); // Use our own version.
- }
- manager.setBackgroundScan = setBackgroundScan; // Use our own version.
- manager.scan = scan; // Use our own version.
- manager.wpsPbc = wifiCommand.wpsPbc;
- manager.wpsPin = wifiCommand.wpsPin;
- manager.wpsCancel = wifiCommand.wpsCancel;
- manager.setPowerMode = (sdkVersion >= 16)
- ? wifiCommand.setPowerModeJB
- : wifiCommand.setPowerModeICS;
- manager.setPowerSavingMode = setPowerSavingMode;
- manager.getHttpProxyNetwork = getHttpProxyNetwork;
- manager.setHttpProxy = setHttpProxy;
- manager.configureHttpProxy = configureHttpProxy;
- manager.setSuspendOptimizations = (sdkVersion >= 16)
- ? wifiCommand.setSuspendOptimizationsJB
- : wifiCommand.setSuspendOptimizationsICS;
- manager.setStaticIpMode = setStaticIpMode;
- manager.getRssiApprox = wifiCommand.getRssiApprox;
- manager.getLinkSpeed = wifiCommand.getLinkSpeed;
- manager.getDhcpInfo = function() { return dhcpInfo; }
- manager.getConnectionInfo = (sdkVersion >= 15)
- ? wifiCommand.getConnectionInfoICS
- : wifiCommand.getConnectionInfoGB;
-
- manager.ensureSupplicantDetached = aCallback => {
- if (!manager.enabled) {
- aCallback();
- return;
- }
- wifiCommand.closeSupplicantConnection(aCallback);
- };
-
- manager.isHandShakeState = function(state) {
- switch (state) {
- case "AUTHENTICATING":
- case "ASSOCIATING":
- case "ASSOCIATED":
- case "FOUR_WAY_HANDSHAKE":
- case "GROUP_HANDSHAKE":
- return true;
- case "DORMANT":
- case "COMPLETED":
- case "DISCONNECTED":
- case "INTERFACE_DISABLED":
- case "INACTIVE":
- case "SCANNING":
- case "UNINITIALIZED":
- case "INVALID":
- case "CONNECTED":
- default:
- return false;
- }
- }
-
- manager.isWifiEnabled = function(state) {
- switch (state) {
- case "UNINITIALIZED":
- case "DISABLING":
- return false;
- default:
- return true;
- }
- }
-
- manager.isWifiTetheringEnabled = function(state) {
- switch (state) {
- case "UNINITIALIZED":
- return false;
- default:
- return true;
- }
- }
-
- manager.syncDebug = syncDebug;
- manager.stateOrdinal = function(state) {
- return supplicantStatesMap.indexOf(state);
- }
- manager.supplicantLoopDetection = function(prevState, state) {
- var isPrevStateInHandShake = manager.isHandShakeState(prevState);
- var isStateInHandShake = manager.isHandShakeState(state);
-
- if (isPrevStateInHandShake) {
- if (isStateInHandShake) {
- // Increase the count only if we are in the loop.
- if (manager.stateOrdinal(state) > manager.stateOrdinal(prevState)) {
- manager.loopDetectionCount++;
- }
- if (manager.loopDetectionCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
- notify("disconnected", {connectionInfo: manager.connectionInfo});
- manager.loopDetectionCount = 0;
- }
- }
- } else {
- // From others state to HandShake state. Reset the count.
- if (isStateInHandShake) {
- manager.loopDetectionCount = 0;
- }
- }
- }
-
- manager.handlePreWifiScan = function() {
- if (p2pSupported) {
- // Before doing regular wifi scan, we have to disable wifi direct
- // scan first. Otherwise we will never get the scan result.
- p2pManager.blockScan();
- }
- };
-
- manager.handlePostWifiScan = function() {
- if (p2pSupported) {
- // After regular wifi scanning, we should restore the restricted
- // wifi direct scan.
- p2pManager.unblockScan();
- }
- };
-
- //
- // Public APIs for P2P.
- //
-
- manager.p2pSupported = function() {
- return p2pSupported;
- };
-
- manager.getP2pManager = function() {
- return p2pManager;
- };
-
- manager.enableP2p = function(callback) {
- p2pManager.setEnabled(true, {
- onSupplicantConnected: function() {
- waitForEvent(WifiP2pManager.INTERFACE_NAME);
- },
-
- onEnabled: function(success) {
- callback(success);
- }
- });
- };
-
- manager.getCapabilities = function() {
- return capabilities;
- }
-
- // Cert Services
- let wifiCertService = Cc["@mozilla.org/wifi/certservice;1"];
- if (wifiCertService) {
- wifiCertService = wifiCertService.getService(Ci.nsIWifiCertService);
- wifiCertService.start(wifiListener);
- } else {
- debug("No wifi CA service component available");
- }
-
- manager.importCert = function(caInfo, callback) {
- var id = idgen++;
- if (callback) {
- controlCallbacks[id] = callback;
- }
-
- wifiCertService.importCert(id, caInfo.certBlob, caInfo.certPassword,
- caInfo.certNickname);
- }
-
- manager.deleteCert = function(caInfo, callback) {
- var id = idgen++;
- if (callback) {
- controlCallbacks[id] = callback;
- }
-
- wifiCertService.deleteCert(id, caInfo.certNickname);
- }
-
- manager.sdkVersion = function() {
- return sdkVersion;
- }
-
- return manager;
-})();
-
-// Get unique key for a network, now the key is created by escape(SSID)+Security.
-// So networks of same SSID but different security mode can be identified.
-function getNetworkKey(network)
-{
- var ssid = "",
- encryption = "OPEN";
-
- if ("security" in network) {
- // manager network object, represents an AP
- // object structure
- // {
- // .ssid : SSID of AP
- // .security[] : "WPA-PSK" for WPA-PSK
- // "WPA-EAP" for WPA-EAP
- // "WEP" for WEP
- // "" for OPEN
- // other keys
- // }
-
- var security = network.security;
- ssid = network.ssid;
-
- for (let j = 0; j < security.length; j++) {
- if (security[j] === "WPA-PSK") {
- encryption = "WPA-PSK";
- break;
- } else if (security[j] === "WPA-EAP") {
- encryption = "WPA-EAP";
- break;
- } else if (security[j] === "WEP") {
- encryption = "WEP";
- break;
- }
- }
- } else if ("key_mgmt" in network) {
- // configure network object, represents a network
- // object structure
- // {
- // .ssid : SSID of network, quoted
- // .key_mgmt : Encryption type
- // "WPA-PSK" for WPA-PSK
- // "WPA-EAP" for WPA-EAP
- // "NONE" for WEP/OPEN
- // .auth_alg : Encryption algorithm(WEP mode only)
- // "OPEN_SHARED" for WEP
- // other keys
- // }
- var key_mgmt = network.key_mgmt,
- auth_alg = network.auth_alg;
- ssid = dequote(network.ssid);
-
- if (key_mgmt == "WPA-PSK") {
- encryption = "WPA-PSK";
- } else if (key_mgmt.indexOf("WPA-EAP") != -1) {
- encryption = "WPA-EAP";
- } else if (key_mgmt == "NONE" && auth_alg === "OPEN SHARED") {
- encryption = "WEP";
- }
- }
-
- // ssid here must be dequoted, and it's safer to esacpe it.
- // encryption won't be empty and always be assigned one of the followings :
- // "OPEN"/"WEP"/"WPA-PSK"/"WPA-EAP".
- // So for a invalid network object, the returned key will be "OPEN".
- return escape(ssid) + encryption;
-}
-
-function getMode(flags) {
- if (/\[IBSS/.test(flags))
- return MODE_IBSS;
-
- return MODE_ESS;
-}
-
-function getKeyManagement(flags) {
- var types = [];
- if (!flags)
- return types;
-
- if (/\[WPA2?-PSK/.test(flags))
- types.push("WPA-PSK");
- if (/\[WPA2?-EAP/.test(flags))
- types.push("WPA-EAP");
- if (/\[WEP/.test(flags))
- types.push("WEP");
- return types;
-}
-
-function getCapabilities(flags) {
- var types = [];
- if (!flags)
- return types;
-
- if (/\[WPS/.test(flags))
- types.push("WPS");
- return types;
-}
-
-// These constants shamelessly ripped from WifiManager.java
-// strength is the value returned by scan_results. It is nominally in dB. We
-// transform it into a percentage for clients looking to simply show a
-// relative indication of the strength of a network.
-const MIN_RSSI = -100;
-const MAX_RSSI = -55;
-
-function calculateSignal(strength) {
- // Some wifi drivers represent their signal strengths as 8-bit integers, so
- // in order to avoid negative numbers, they add 256 to the actual values.
- // While we don't *know* that this is the case here, we make an educated
- // guess.
- if (strength > 0)
- strength -= 256;
-
- if (strength <= MIN_RSSI)
- return 0;
- if (strength >= MAX_RSSI)
- return 100;
- return Math.floor(((strength - MIN_RSSI) / (MAX_RSSI - MIN_RSSI)) * 100);
-}
-
-function Network(ssid, mode, frequency, security, password, capabilities) {
- this.ssid = ssid;
- this.mode = mode;
- this.frequency = frequency;
- this.security = security;
-
- if (typeof password !== "undefined")
- this.password = password;
- if (capabilities !== undefined)
- this.capabilities = capabilities;
- // TODO connected here as well?
-
- this.__exposedProps__ = Network.api;
-}
-
-Network.api = {
- ssid: "r",
- mode: "r",
- frequency: "r",
- security: "r",
- capabilities: "r",
- known: "r",
-
- password: "rw",
- keyManagement: "rw",
- psk: "rw",
- identity: "rw",
- wep: "rw",
- hidden: "rw",
- eap: "rw",
- pin: "rw",
- phase1: "rw",
- phase2: "rw",
- serverCertificate: "rw",
- userCertificate: "rw"
-};
-
-// Note: We never use ScanResult.prototype, so the fact that it's unrelated to
-// Network.prototype is OK.
-function ScanResult(ssid, bssid, frequency, flags, signal) {
- Network.call(this, ssid, getMode(flags), frequency,
- getKeyManagement(flags), undefined, getCapabilities(flags));
- this.bssid = bssid;
- this.signalStrength = signal;
- this.relSignalStrength = calculateSignal(Number(signal));
-
- this.__exposedProps__ = ScanResult.api;
-}
-
-// XXX This should probably live in the DOM-facing side, but it's hard to do
-// there, so we stick this here.
-ScanResult.api = {
- bssid: "r",
- signalStrength: "r",
- relSignalStrength: "r",
- connected: "r"
-};
-
-for (let i in Network.api) {
- ScanResult.api[i] = Network.api[i];
-}
-
-function quote(s) {
- return '"' + s + '"';
-}
-
-function dequote(s) {
- if (s[0] != '"' || s[s.length - 1] != '"')
- throw "Invalid argument, not a quoted string: " + s;
- return s.substr(1, s.length - 2);
-}
-
-function isWepHexKey(s) {
- if (s.length != 10 && s.length != 26 && s.length != 58)
- return false;
- return !/[^a-fA-F0-9]/.test(s);
-}
-
-
-var WifiNetworkInterface = {
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
-
- registered: false,
-
- // nsINetworkInterface
-
- NETWORK_STATE_UNKNOWN: Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN,
- NETWORK_STATE_CONNECTING: Ci.nsINetworkInfo.CONNECTING,
- NETWORK_STATE_CONNECTED: Ci.nsINetworkInfo.CONNECTED,
- NETWORK_STATE_DISCONNECTING: Ci.nsINetworkInfo.DISCONNECTING,
- NETWORK_STATE_DISCONNECTED: Ci.nsINetworkInfo.DISCONNECTED,
-
- NETWORK_TYPE_WIFI: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI,
- NETWORK_TYPE_MOBILE: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE,
- NETWORK_TYPE_MOBILE_MMS: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS,
- NETWORK_TYPE_MOBILE_SUPL: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL,
-
- info: {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]),
-
- state: Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN,
-
- type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI,
-
- name: null,
-
- ips: [],
-
- prefixLengths: [],
-
- dnses: [],
-
- gateways: [],
-
- getAddresses: function (ips, prefixLengths) {
- ips.value = this.ips.slice();
- prefixLengths.value = this.prefixLengths.slice();
-
- return this.ips.length;
- },
-
- getGateways: function (count) {
- if (count) {
- count.value = this.gateways.length;
- }
- return this.gateways.slice();
- },
-
- getDnses: function (count) {
- if (count) {
- count.value = this.dnses.length;
- }
- return this.dnses.slice();
- }
- },
-
- httpProxyHost: null,
-
- httpProxyPort: null
-};
-
-function WifiScanResult() {}
-
-// TODO Make the difference between a DOM-based network object and our
-// networks objects much clearer.
-var netToDOM;
-var netFromDOM;
-
-function WifiWorker() {
- var self = this;
-
- this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
- .getService(Ci.nsIMessageListenerManager);
- const messages = ["WifiManager:getNetworks", "WifiManager:getKnownNetworks",
- "WifiManager:associate", "WifiManager:forget",
- "WifiManager:wps", "WifiManager:getState",
- "WifiManager:setPowerSavingMode",
- "WifiManager:setHttpProxy",
- "WifiManager:setStaticIpMode",
- "WifiManager:importCert",
- "WifiManager:getImportedCerts",
- "WifiManager:deleteCert",
- "WifiManager:setWifiEnabled",
- "WifiManager:setWifiTethering",
- "child-process-shutdown"];
-
- messages.forEach((function(msgName) {
- this._mm.addMessageListener(msgName, this);
- }).bind(this));
-
- Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
- Services.obs.addObserver(this, "xpcom-shutdown", false);
-
- this.wantScanResults = [];
-
- this._needToEnableNetworks = false;
- this._highestPriority = -1;
-
- // Networks is a map from SSID -> a scan result.
- this.networks = Object.create(null);
-
- // ConfiguredNetworks is a map from SSID -> our view of a network. It only
- // lists networks known to the wpa_supplicant. The SSID field (and other
- // fields) are quoted for ease of use with WifiManager commands.
- // Note that we don't have to worry about escaping embedded quotes since in
- // all cases, the supplicant will take the last quotation that we pass it as
- // the end of the string.
- this.configuredNetworks = Object.create(null);
- this._addingNetworks = Object.create(null);
-
- this.currentNetwork = null;
- this.ipAddress = "";
- this.macAddress = null;
-
- this._lastConnectionInfo = null;
- this._connectionInfoTimer = null;
- this._reconnectOnDisconnect = false;
-
- // Create p2pObserver and assign to p2pManager.
- if (WifiManager.p2pSupported()) {
- this._p2pObserver = WifiP2pWorkerObserver(WifiManager.getP2pManager());
- WifiManager.getP2pManager().setObserver(this._p2pObserver);
-
- // Add DOM message observerd by p2pObserver to the message listener as well.
- this._p2pObserver.getObservedDOMMessages().forEach((function(msgName) {
- this._mm.addMessageListener(msgName, this);
- }).bind(this));
- }
-
- // Users of instances of nsITimer should keep a reference to the timer until
- // it is no longer needed in order to assure the timer is fired.
- this._callbackTimer = null;
-
- // XXX On some phones (Otoro and Unagi) the wifi driver doesn't play nicely
- // with the automatic scans that wpa_supplicant does (it appears that the
- // driver forgets that it's returned scan results and then refuses to try to
- // rescan. In order to detect this case we start a timer when we enter the
- // SCANNING state and reset it whenever we either get scan results or leave
- // the SCANNING state. If the timer fires, we assume that we are stuck and
- // forceably try to unstick the supplican, also turning on background
- // scanning to avoid having to constantly poke the supplicant.
-
- // How long we wait is controlled by the SCAN_STUCK_WAIT constant.
- const SCAN_STUCK_WAIT = 12000;
- this._scanStuckTimer = null;
- this._turnOnBackgroundScan = false;
-
- function startScanStuckTimer() {
- if (WifiManager.schedScanRecovery) {
- self._scanStuckTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- self._scanStuckTimer.initWithCallback(scanIsStuck, SCAN_STUCK_WAIT,
- Ci.nsITimer.TYPE_ONE_SHOT);
- }
- }
-
- function scanIsStuck() {
- // Uh-oh, we've waited too long for scan results. Disconnect (which
- // guarantees that we leave the SCANNING state and tells wpa_supplicant to
- // wait for our next command) ensure that background scanning is on and
- // then try again.
- debug("Determined that scanning is stuck, turning on background scanning!");
- WifiManager.handlePostWifiScan();
- WifiManager.disconnect(function(ok) {});
- self._turnOnBackgroundScan = true;
- }
-
- // A list of requests to turn wifi on or off.
- this._stateRequests = [];
-
- // Given a connection status network, takes a network from
- // self.configuredNetworks and prepares it for the DOM.
- netToDOM = function(net) {
- if (!net) {
- return null;
- }
- var ssid = dequote(net.ssid);
- var mode = net.mode;
- var frequency = net.frequency;
- var security = (net.key_mgmt === "NONE" && net.wep_key0) ? ["WEP"] :
- (net.key_mgmt && net.key_mgmt !== "NONE") ? [net.key_mgmt.split(" ")[0]] :
- [];
- var password;
- if (("psk" in net && net.psk) ||
- ("password" in net && net.password) ||
- ("wep_key0" in net && net.wep_key0)) {
- password = "*";
- }
-
- var pub = new Network(ssid, mode, frequency, security, password);
- if (net.identity)
- pub.identity = dequote(net.identity);
- if ("netId" in net)
- pub.known = true;
- if (net.scan_ssid === 1)
- pub.hidden = true;
- if ("ca_cert" in net && net.ca_cert &&
- net.ca_cert.indexOf("keystore://WIFI_SERVERCERT_" === 0)) {
- pub.serverCertificate = net.ca_cert.substr(27);
- }
- if(net.subject_match) {
- pub.subjectMatch = net.subject_match;
- }
- if ("client_cert" in net && net.client_cert &&
- net.client_cert.indexOf("keystore://WIFI_USERCERT_" === 0)) {
- pub.userCertificate = net.client_cert.substr(25);
- }
- return pub;
- };
-
- netFromDOM = function(net, configured) {
- // Takes a network from the DOM and makes it suitable for insertion into
- // self.configuredNetworks (that is calling addNetwork will do the right
- // thing).
- // NB: Modifies net in place: safe since we don't share objects between
- // the dom and the chrome code.
-
- // Things that are useful for the UI but not to us.
- delete net.bssid;
- delete net.signalStrength;
- delete net.relSignalStrength;
- delete net.security;
- delete net.capabilities;
-
- if (!configured)
- configured = {};
-
- net.ssid = quote(net.ssid);
-
- let wep = false;
- if ("keyManagement" in net) {
- if (net.keyManagement === "WEP") {
- wep = true;
- net.keyManagement = "NONE";
- } else if (net.keyManagement === "WPA-EAP") {
- net.keyManagement += " IEEE8021X";
- }
-
- configured.key_mgmt = net.key_mgmt = net.keyManagement; // WPA2-PSK, WPA-PSK, etc.
- delete net.keyManagement;
- } else {
- configured.key_mgmt = net.key_mgmt = "NONE";
- }
-
- if (net.hidden) {
- configured.scan_ssid = net.scan_ssid = 1;
- delete net.hidden;
- }
-
- function checkAssign(name, checkStar) {
- if (name in net) {
- let value = net[name];
- if (!value || (checkStar && value === '*')) {
- if (name in configured)
- net[name] = configured[name];
- else
- delete net[name];
- } else {
- configured[name] = net[name] = quote(value);
- }
- }
- }
-
- checkAssign("psk", true);
- checkAssign("identity", false);
- checkAssign("password", true);
- if (wep && net.wep && net.wep != '*') {
- configured.wep_key0 = net.wep_key0 = isWepHexKey(net.wep) ? net.wep : quote(net.wep);
- configured.auth_alg = net.auth_alg = "OPEN SHARED";
- }
-
- function hasValidProperty(name) {
- return ((name in net) && net[name] != null);
- }
-
- if (hasValidProperty("eap")) {
- if (hasValidProperty("pin")) {
- net.pin = quote(net.pin);
- }
-
- if (hasValidProperty("phase1"))
- net.phase1 = quote(net.phase1);
-
- if (hasValidProperty("phase2")) {
- if (net.phase2 === "TLS") {
- net.phase2 = quote("autheap=" + net.phase2);
- } else { // PAP, MSCHAPV2, etc.
- net.phase2 = quote("auth=" + net.phase2);
- }
- }
-
- if (hasValidProperty("serverCertificate"))
- net.ca_cert = quote("keystore://WIFI_SERVERCERT_" + net.serverCertificate);
-
- if (hasValidProperty("subjectMatch"))
- net.subject_match = quote(net.subjectMatch);
-
- if (hasValidProperty("userCertificate")) {
- let userCertName = "WIFI_USERCERT_" + net.userCertificate;
- net.client_cert = quote("keystore://" + userCertName);
-
- let wifiCertService = Cc["@mozilla.org/wifi/certservice;1"].
- getService(Ci.nsIWifiCertService);
- if (wifiCertService.hasPrivateKey(userCertName)) {
- if (WifiManager.sdkVersion() >= 19) {
- // Use openssol engine instead of keystore protocol after Kitkat.
- net.engine = 1;
- net.engine_id = quote("keystore");
- net.key_id = quote("WIFI_USERKEY_" + net.userCertificate);
- } else {
- net.private_key = quote("keystore://WIFI_USERKEY_" + net.userCertificate);
- }
- }
- }
- }
-
- return net;
- };
-
- WifiManager.onsupplicantconnection = function() {
- debug("Connected to supplicant");
- // Give it a state other than UNINITIALIZED, INITIALIZING or DISABLING
- // defined in getter function of WifiManager.enabled. It implies that
- // we are ready to accept dom request from applications.
- WifiManager.state = "DISCONNECTED";
- self._reloadConfiguredNetworks(function(ok) {
- // Prime this.networks.
- if (!ok)
- return;
-
- // The select network command we used in associate() disables others networks.
- // Enable them here to make sure wpa_supplicant helps to connect to known
- // network automatically.
- self._enableAllNetworks();
- WifiManager.saveConfig(function() {})
- });
-
- // Notify everybody, even if they didn't ask us to come up.
- WifiManager.getMacAddress(function (mac) {
- self.macAddress = mac;
- debug("Got mac: " + mac);
- self._fireEvent("wifiUp", { macAddress: mac });
- self.requestDone();
- });
-
- if (WifiManager.state === "SCANNING")
- startScanStuckTimer();
- };
-
- WifiManager.onsupplicantlost = function() {
- WifiManager.supplicantStarted = false;
- WifiManager.state = "UNINITIALIZED";
- debug("Supplicant died!");
-
- // Notify everybody, even if they didn't ask us to come up.
- self._fireEvent("wifiDown", {});
- self.requestDone();
- };
-
- WifiManager.onpasswordmaybeincorrect = function() {
- WifiManager.authenticationFailuresCount++;
- };
-
- WifiManager.ondisconnected = function() {
- // We may fail to establish the connection, re-enable the
- // rest of our networks.
- if (self._needToEnableNetworks) {
- self._enableAllNetworks();
- self._needToEnableNetworks = false;
- }
-
- let connectionInfo = this.connectionInfo;
- WifiManager.getNetworkId(connectionInfo.ssid, function(netId) {
- // Trying to get netId from current network.
- if (!netId &&
- self.currentNetwork && self.currentNetwork.ssid &&
- dequote(self.currentNetwork.ssid) == connectionInfo.ssid &&
- typeof self.currentNetwork.netId !== "undefined") {
- netId = self.currentNetwork.netId;
- }
- if (netId) {
- WifiManager.disableNetwork(netId, function() {});
- }
- });
- self._fireEvent("onconnectingfailed", {network: netToDOM(self.currentNetwork)});
- }
-
- WifiManager.onstatechange = function() {
- debug("State change: " + this.prevState + " -> " + this.state);
-
- if (self._connectionInfoTimer &&
- this.state !== "CONNECTED" &&
- this.state !== "COMPLETED") {
- self._stopConnectionInfoTimer();
- }
-
- if (this.state !== "SCANNING" &&
- self._scanStuckTimer) {
- self._scanStuckTimer.cancel();
- self._scanStuckTimer = null;
- }
-
- switch (this.state) {
- case "DORMANT":
- // The dormant state is a bad state to be in since we won't
- // automatically connect. Try to knock us out of it. We only
- // hit this state when we've failed to run DHCP, so trying
- // again isn't the worst thing we can do. Eventually, we'll
- // need to detect if we're looping in this state and bail out.
- WifiManager.reconnect(function(){});
- break;
- case "ASSOCIATING":
- // id has not yet been filled in, so we can only report the ssid and
- // bssid. mode and frequency are simply made up.
- self.currentNetwork =
- { bssid: WifiManager.connectionInfo.bssid,
- ssid: quote(WifiManager.connectionInfo.ssid),
- mode: MODE_ESS,
- frequency: 0};
- WifiManager.getNetworkConfiguration(self.currentNetwork, function (){
- // Notify again because we get complete network information.
- self._fireEvent("onconnecting", { network: netToDOM(self.currentNetwork) });
- });
- break;
- case "ASSOCIATED":
- // set to full power mode when ready to do 4 way handsharke.
- WifiManager.setPowerSavingMode(false);
- if (!self.currentNetwork) {
- self.currentNetwork =
- { bssid: WifiManager.connectionInfo.bssid,
- ssid: quote(WifiManager.connectionInfo.ssid) };
- }
- self.currentNetwork.netId = this.id;
- WifiManager.getNetworkConfiguration(self.currentNetwork, function (){
- // Notify again because we get complete network information.
- self._fireEvent("onconnecting", { network: netToDOM(self.currentNetwork) });
- });
- break;
- case "COMPLETED":
- // Now that we've successfully completed the connection, re-enable the
- // rest of our networks.
- // XXX Need to do this eventually if the user entered an incorrect
- // password. For now, we require user interaction to break the loop and
- // select a better network!
- if (self._needToEnableNetworks) {
- self._enableAllNetworks();
- self._needToEnableNetworks = false;
- }
-
- var _oncompleted = function() {
- // The full authentication process is completed, reset the count.
- WifiManager.authenticationFailuresCount = 0;
- WifiManager.loopDetectionCount = 0;
- self._startConnectionInfoTimer();
- self._fireEvent("onassociate", { network: netToDOM(self.currentNetwork) });
- };
-
- // We get the ASSOCIATED event when we've associated but not connected, so
- // wait until the handshake is complete.
- if (this.fromStatus || !self.currentNetwork) {
- // In this case, we connected to an already-connected wpa_supplicant,
- // because of that we need to gather information about the current
- // network here.
- self.currentNetwork = { bssid: WifiManager.connectionInfo.bssid,
- ssid: quote(WifiManager.connectionInfo.ssid),
- netId: WifiManager.connectionInfo.id };
- WifiManager.getNetworkConfiguration(self.currentNetwork, _oncompleted);
- } else {
- _oncompleted();
- }
- break;
- case "CONNECTED":
- // wifi connection complete, turn on the power saving mode.
- WifiManager.setPowerSavingMode(true);
- // BSSID is read after connected, update it.
- self.currentNetwork.bssid = WifiManager.connectionInfo.bssid;
- break;
- case "DISCONNECTED":
- // wpa_supplicant may give us a "DISCONNECTED" event even if
- // we are already in "DISCONNECTED" state.
- if ((WifiNetworkInterface.info.state ===
- Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED) &&
- (this.prevState === "INITIALIZING" ||
- this.prevState === "DISCONNECTED" ||
- this.prevState === "INTERFACE_DISABLED" ||
- this.prevState === "INACTIVE" ||
- this.prevState === "UNINITIALIZED")) {
- // When in disconnected mode, need to turn on wifi power saving mode.
- WifiManager.setPowerSavingMode(true);
- return;
- }
-
- self._fireEvent("ondisconnect", {network: netToDOM(self.currentNetwork)});
-
- self.currentNetwork = null;
- self.ipAddress = "";
-
- if (self._turnOnBackgroundScan) {
- self._turnOnBackgroundScan = false;
- WifiManager.setBackgroundScan("ON", function(did_something, ok) {
- WifiManager.reassociate(function() {});
- });
- }
-
- WifiManager.connectionDropped(function() {
- // We've disconnected from a network because of a call to forgetNetwork.
- // Reconnect to the next available network (if any).
- if (self._reconnectOnDisconnect) {
- self._reconnectOnDisconnect = false;
- WifiManager.reconnect(function(){});
- }
- });
-
- WifiNetworkInterface.info.state =
- Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
-
- // Update network infterface first then clear properties.
- gNetworkManager.updateNetworkInterface(WifiNetworkInterface);
- WifiNetworkInterface.info.ips = [];
- WifiNetworkInterface.info.prefixLengths = [];
- WifiNetworkInterface.info.gateways = [];
- WifiNetworkInterface.info.dnses = [];
-
-
- break;
- case "WPS_TIMEOUT":
- self._fireEvent("onwpstimeout", {});
- break;
- case "WPS_FAIL":
- self._fireEvent("onwpsfail", {});
- break;
- case "WPS_OVERLAP_DETECTED":
- self._fireEvent("onwpsoverlap", {});
- break;
- case "AUTHENTICATING":
- self._fireEvent("onauthenticating", {network: netToDOM(self.currentNetwork)});
- break;
- case "SCANNING":
- // If we're already scanning in the background, we don't need to worry
- // about getting stuck while scanning.
- if (!WifiManager.backgroundScanEnabled && WifiManager.enabled)
- startScanStuckTimer();
- break;
- }
- };
-
- WifiManager.onnetworkconnected = function() {
- if (!this.info || !this.info.ipaddr_str) {
- debug("Network information is invalid.");
- return;
- }
-
- let maskLength =
- netHelpers.getMaskLength(netHelpers.stringToIP(this.info.mask_str));
- if (!maskLength) {
- maskLength = 32; // max prefix for IPv4.
- }
-
- let netConnect = WifiManager.getHttpProxyNetwork(self.currentNetwork);
- if (netConnect) {
- WifiNetworkInterface.httpProxyHost = netConnect.httpProxyHost;
- WifiNetworkInterface.httpProxyPort = netConnect.httpProxyPort;
- }
-
- WifiNetworkInterface.info.state =
- Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
- WifiNetworkInterface.info.ips = [this.info.ipaddr_str];
- WifiNetworkInterface.info.prefixLengths = [maskLength];
- WifiNetworkInterface.info.gateways = [this.info.gateway_str];
- if (typeof this.info.dns1_str == "string" &&
- this.info.dns1_str.length) {
- WifiNetworkInterface.info.dnses.push(this.info.dns1_str);
- }
- if (typeof this.info.dns2_str == "string" &&
- this.info.dns2_str.length) {
- WifiNetworkInterface.info.dnses.push(this.info.dns2_str);
- }
- gNetworkManager.updateNetworkInterface(WifiNetworkInterface);
-
- self.ipAddress = this.info.ipaddr_str;
-
- // We start the connection information timer when we associate, but
- // don't have our IP address until here. Make sure that we fire a new
- // connectionInformation event with the IP address the next time the
- // timer fires.
- self._lastConnectionInfo = null;
- self._fireEvent("onconnect", { network: netToDOM(self.currentNetwork) });
- };
-
- WifiManager.onscanresultsavailable = function() {
- if (self._scanStuckTimer) {
- // We got scan results! We must not be stuck for now, try again.
- self._scanStuckTimer.cancel();
- self._scanStuckTimer.initWithCallback(scanIsStuck, SCAN_STUCK_WAIT,
- Ci.nsITimer.TYPE_ONE_SHOT);
- }
-
- if (self.wantScanResults.length === 0) {
- debug("Scan results available, but we don't need them");
- return;
- }
-
- debug("Scan results are available! Asking for them.");
- WifiManager.getScanResults(function(r) {
- // Failure.
- if (!r) {
- self.wantScanResults.forEach(function(callback) { callback(null) });
- self.wantScanResults = [];
- return;
- }
-
- let capabilities = WifiManager.getCapabilities();
-
- // Now that we have scan results, there's no more need to continue
- // scanning. Ignore any errors from this command.
- WifiManager.setScanMode("inactive", function() {});
- let lines = r.split("\n");
- // NB: Skip the header line.
- self.networksArray = [];
- for (let i = 1; i < lines.length; ++i) {
- // bssid / frequency / signal level / flags / ssid
- var match = /([\S]+)\s+([\S]+)\s+([\S]+)\s+(\[[\S]+\])?\s(.*)/.exec(lines[i]);
-
- if (match && match[5]) {
- let ssid = match[5],
- bssid = match[1],
- frequency = match[2],
- signalLevel = match[3],
- flags = match[4];
-
- /* Skip networks with unknown or unsupported modes. */
- if (capabilities.mode.indexOf(getMode(flags)) == -1)
- continue;
-
- // If this is the first time that we've seen this SSID in the scan
- // results, add it to the list along with any other information.
- // Also, we use the highest signal strength that we see.
- let network = new ScanResult(ssid, bssid, frequency, flags, signalLevel);
-
- let networkKey = getNetworkKey(network);
- let eapIndex = -1;
- if (networkKey in self.configuredNetworks) {
- let known = self.configuredNetworks[networkKey];
- network.known = true;
-
- if ("identity" in known && known.identity)
- network.identity = dequote(known.identity);
-
- // Note: we don't hand out passwords here! The * marks that there
- // is a password that we're hiding.
- if (("psk" in known && known.psk) ||
- ("password" in known && known.password) ||
- ("wep_key0" in known && known.wep_key0)) {
- network.password = "*";
- }
- }
-
- self.networksArray.push(network);
- if (network.bssid === WifiManager.connectionInfo.bssid)
- network.connected = true;
-
- let signal = calculateSignal(Number(match[3]));
- if (signal > network.relSignalStrength)
- network.relSignalStrength = signal;
- } else if (!match) {
- debug("Match didn't find anything for: " + lines[i]);
- }
- }
-
- self.wantScanResults.forEach(function(callback) { callback(self.networksArray) });
- self.wantScanResults = [];
- });
- };
-
- WifiManager.onstationinfoupdate = function() {
- self._fireEvent("stationinfoupdate", { station: this.station });
- };
-
- WifiManager.onstopconnectioninfotimer = function() {
- self._stopConnectionInfoTimer();
- };
-
- // Read the 'wifi.enabled' setting in order to start with a known
- // value at boot time. The handle() will be called after reading.
- //
- // nsISettingsServiceCallback implementation.
- var initWifiEnabledCb = {
- handle: function handle(aName, aResult) {
- if (aName !== SETTINGS_WIFI_ENABLED)
- return;
- if (aResult === null)
- aResult = true;
- self.handleWifiEnabled(aResult);
- },
- handleError: function handleError(aErrorMessage) {
- debug("Error reading the 'wifi.enabled' setting. Default to wifi on.");
- self.handleWifiEnabled(true);
- }
- };
-
- var initWifiDebuggingEnabledCb = {
- handle: function handle(aName, aResult) {
- if (aName !== SETTINGS_WIFI_DEBUG_ENABLED)
- return;
- if (aResult === null)
- aResult = false;
- DEBUG = aResult;
- updateDebug();
- },
- handleError: function handleError(aErrorMessage) {
- debug("Error reading the 'wifi.debugging.enabled' setting. Default to debugging off.");
- DEBUG = false;
- updateDebug();
- }
- };
-
- this.initTetheringSettings();
-
- let lock = gSettingsService.createLock();
- lock.get(SETTINGS_WIFI_ENABLED, initWifiEnabledCb);
- lock.get(SETTINGS_WIFI_DEBUG_ENABLED, initWifiDebuggingEnabledCb);
-
- lock.get(SETTINGS_WIFI_SSID, this);
- lock.get(SETTINGS_WIFI_SECURITY_TYPE, this);
- lock.get(SETTINGS_WIFI_SECURITY_PASSWORD, this);
- lock.get(SETTINGS_WIFI_IP, this);
- lock.get(SETTINGS_WIFI_PREFIX, this);
- lock.get(SETTINGS_WIFI_DHCPSERVER_STARTIP, this);
- lock.get(SETTINGS_WIFI_DHCPSERVER_ENDIP, this);
- lock.get(SETTINGS_WIFI_DNS1, this);
- lock.get(SETTINGS_WIFI_DNS2, this);
- lock.get(SETTINGS_WIFI_TETHERING_ENABLED, this);
-
- lock.get(SETTINGS_USB_DHCPSERVER_STARTIP, this);
- lock.get(SETTINGS_USB_DHCPSERVER_ENDIP, this);
-
- this._wifiTetheringSettingsToRead = [SETTINGS_WIFI_SSID,
- SETTINGS_WIFI_SECURITY_TYPE,
- SETTINGS_WIFI_SECURITY_PASSWORD,
- SETTINGS_WIFI_IP,
- SETTINGS_WIFI_PREFIX,
- SETTINGS_WIFI_DHCPSERVER_STARTIP,
- SETTINGS_WIFI_DHCPSERVER_ENDIP,
- SETTINGS_WIFI_DNS1,
- SETTINGS_WIFI_DNS2,
- SETTINGS_WIFI_TETHERING_ENABLED,
- SETTINGS_USB_DHCPSERVER_STARTIP,
- SETTINGS_USB_DHCPSERVER_ENDIP];
-}
-
-function translateState(state) {
- switch (state) {
- case "INTERFACE_DISABLED":
- case "INACTIVE":
- case "SCANNING":
- case "DISCONNECTED":
- default:
- return "disconnected";
-
- case "AUTHENTICATING":
- case "ASSOCIATING":
- case "ASSOCIATED":
- case "FOUR_WAY_HANDSHAKE":
- case "GROUP_HANDSHAKE":
- return "connecting";
-
- case "COMPLETED":
- return WifiManager.getDhcpInfo() ? "connected" : "associated";
- }
-}
-
-WifiWorker.prototype = {
- classID: WIFIWORKER_CID,
- classInfo: XPCOMUtils.generateCI({classID: WIFIWORKER_CID,
- contractID: WIFIWORKER_CONTRACTID,
- classDescription: "WifiWorker",
- interfaces: [Ci.nsIWorkerHolder,
- Ci.nsIWifi,
- Ci.nsIObserver]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder,
- Ci.nsIWifi,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- disconnectedByWifi: false,
-
- disconnectedByWifiTethering: false,
-
- _wifiTetheringSettingsToRead: [],
-
- _oldWifiTetheringEnabledState: null,
-
- tetheringSettings: {},
-
- initTetheringSettings: function initTetheringSettings() {
- this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED] = null;
- this.tetheringSettings[SETTINGS_WIFI_SSID] = DEFAULT_WIFI_SSID;
- this.tetheringSettings[SETTINGS_WIFI_SECURITY_TYPE] = DEFAULT_WIFI_SECURITY_TYPE;
- this.tetheringSettings[SETTINGS_WIFI_SECURITY_PASSWORD] = DEFAULT_WIFI_SECURITY_PASSWORD;
- this.tetheringSettings[SETTINGS_WIFI_IP] = DEFAULT_WIFI_IP;
- this.tetheringSettings[SETTINGS_WIFI_PREFIX] = DEFAULT_WIFI_PREFIX;
- this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP] = DEFAULT_WIFI_DHCPSERVER_STARTIP;
- this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP] = DEFAULT_WIFI_DHCPSERVER_ENDIP;
- this.tetheringSettings[SETTINGS_WIFI_DNS1] = DEFAULT_DNS1;
- this.tetheringSettings[SETTINGS_WIFI_DNS2] = DEFAULT_DNS2;
-
- this.tetheringSettings[SETTINGS_USB_DHCPSERVER_STARTIP] = DEFAULT_USB_DHCPSERVER_STARTIP;
- this.tetheringSettings[SETTINGS_USB_DHCPSERVER_ENDIP] = DEFAULT_USB_DHCPSERVER_ENDIP;
- },
-
- // Internal methods.
- waitForScan: function(callback) {
- this.wantScanResults.push(callback);
- },
-
- // In order to select a specific network, we disable the rest of the
- // networks known to us. However, in general, we want the supplicant to
- // connect to which ever network it thinks is best, so when we select the
- // proper network (or fail to), we need to re-enable the rest.
- _enableAllNetworks: function() {
- for (let key in this.configuredNetworks) {
- let net = this.configuredNetworks[key];
- WifiManager.enableNetwork(net.netId, false, function(ok) {
- net.disabled = ok ? 1 : 0;
- });
- }
- },
-
- _startConnectionInfoTimer: function() {
- if (this._connectionInfoTimer)
- return;
-
- var self = this;
- function getConnectionInformation() {
- WifiManager.getConnectionInfo(function(connInfo) {
- // See comments in calculateSignal for information about this.
- if (!connInfo) {
- self._lastConnectionInfo = null;
- return;
- }
-
- let { rssi, linkspeed } = connInfo;
- if (rssi > 0)
- rssi -= 256;
- if (rssi <= MIN_RSSI)
- rssi = MIN_RSSI;
- else if (rssi >= MAX_RSSI)
- rssi = MAX_RSSI;
-
- let info = { signalStrength: rssi,
- relSignalStrength: calculateSignal(rssi),
- linkSpeed: linkspeed,
- ipAddress: self.ipAddress };
- let last = self._lastConnectionInfo;
-
- // Only fire the event if the link speed changed or the signal
- // strength changed by more than 10%.
- function tensPlace(percent) {
- return (percent / 10) | 0;
- }
-
- if (last && last.linkSpeed === info.linkSpeed &&
- last.ipAddress === info.ipAddress &&
- tensPlace(last.relSignalStrength) === tensPlace(info.relSignalStrength)) {
- return;
- }
-
- self._lastConnectionInfo = info;
- debug("Firing connectioninfoupdate: " + uneval(info));
- self._fireEvent("connectioninfoupdate", info);
- });
- }
-
- // Prime our _lastConnectionInfo immediately and fire the event at the
- // same time.
- getConnectionInformation();
-
- // Now, set up the timer for regular updates.
- this._connectionInfoTimer =
- Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- this._connectionInfoTimer.init(getConnectionInformation, 5000,
- Ci.nsITimer.TYPE_REPEATING_SLACK);
- },
-
- _stopConnectionInfoTimer: function() {
- if (!this._connectionInfoTimer)
- return;
-
- this._connectionInfoTimer.cancel();
- this._connectionInfoTimer = null;
- this._lastConnectionInfo = null;
- },
-
- _reloadConfiguredNetworks: function(callback) {
- WifiManager.getConfiguredNetworks((function(networks) {
- if (!networks) {
- debug("Unable to get configured networks");
- callback(false);
- return;
- }
-
- this._highestPriority = -1;
-
- // Convert between netId-based and ssid-based indexing.
- for (let net in networks) {
- let network = networks[net];
- delete networks[net];
-
- if (!network.ssid) {
- WifiManager.removeNetwork(network.netId, function() {});
- continue;
- }
-
- if (network.hasOwnProperty("priority") &&
- network.priority > this._highestPriority) {
- this._highestPriority = network.priority;
- }
-
- let networkKey = getNetworkKey(network);
- // Accept latest config of same network(same SSID and same security).
- if (networks[networkKey]) {
- WifiManager.removeNetwork(networks[networkKey].netId, function() {});
- }
- networks[networkKey] = network;
- }
-
- this.configuredNetworks = networks;
- callback(true);
- }).bind(this));
- },
-
- // Important side effect: calls WifiManager.saveConfig.
- _reprioritizeNetworks: function(callback) {
- // First, sort the networks in orer of their priority.
- var ordered = Object.getOwnPropertyNames(this.configuredNetworks);
- let self = this;
- ordered.sort(function(a, b) {
- var neta = self.configuredNetworks[a],
- netb = self.configuredNetworks[b];
-
- // Sort unsorted networks to the end of the list.
- if (isNaN(neta.priority))
- return isNaN(netb.priority) ? 0 : 1;
- if (isNaN(netb.priority))
- return -1;
- return netb.priority - neta.priority;
- });
-
- // Skip unsorted networks.
- let newPriority = 0, i;
- for (i = ordered.length - 1; i >= 0; --i) {
- if (!isNaN(this.configuredNetworks[ordered[i]].priority))
- break;
- }
-
- // No networks we care about?
- if (i < 0) {
- WifiManager.saveConfig(callback);
- return;
- }
-
- // Now assign priorities from 0 to length, starting with the smallest
- // priority and heading towards the highest (note the dependency between
- // total and i here).
- let done = 0, errors = 0, total = i + 1;
- for (; i >= 0; --i) {
- let network = this.configuredNetworks[ordered[i]];
- network.priority = newPriority++;
-
- // Note: networkUpdated declared below since it happens logically after
- // this loop.
- WifiManager.updateNetwork(network, networkUpdated);
- }
-
- function networkUpdated(ok) {
- if (!ok)
- ++errors;
- if (++done === total) {
- if (errors > 0) {
- callback(false);
- return;
- }
-
- WifiManager.saveConfig(function(ok) {
- if (!ok) {
- callback(false);
- return;
- }
-
- self._reloadConfiguredNetworks(function(ok) {
- callback(ok);
- });
- });
- }
- }
- },
-
- // nsIWifi
-
- _domManagers: [],
- _fireEvent: function(message, data) {
- this._domManagers.forEach(function(manager) {
- // Note: We should never have a dead message manager here because we
- // observe our child message managers shutting down, below.
- manager.sendAsyncMessage("WifiManager:" + message, data);
- });
- },
-
- _sendMessage: function(message, success, data, msg) {
- try {
- msg.manager.sendAsyncMessage(message + (success ? ":OK" : ":NO"),
- { data: data, rid: msg.rid, mid: msg.mid });
- } catch (e) {
- debug("sendAsyncMessage error : " + e);
- }
- this._splicePendingRequest(msg);
- },
-
- _domRequest: [],
-
- _splicePendingRequest: function(msg) {
- for (let i = 0; i < this._domRequest.length; i++) {
- if (this._domRequest[i].msg === msg) {
- this._domRequest.splice(i, 1);
- return;
- }
- }
- },
-
- _clearPendingRequest: function() {
- if (this._domRequest.length === 0) return;
- this._domRequest.forEach((function(req) {
- this._sendMessage(req.name + ":Return", false, "Wifi is disabled", req.msg);
- }).bind(this));
- },
-
- receiveMessage: function MessageManager_receiveMessage(aMessage) {
- let msg = aMessage.data || {};
- msg.manager = aMessage.target;
-
- if (WifiManager.p2pSupported()) {
- // If p2pObserver returns something truthy, return it!
- // Otherwise, continue to do the rest of tasks.
- var p2pRet = this._p2pObserver.onDOMMessage(aMessage);
- if (p2pRet) {
- return p2pRet;
- }
- }
-
- // Note: By the time we receive child-process-shutdown, the child process
- // has already forgotten its permissions so we do this before the
- // permissions check.
- if (aMessage.name === "child-process-shutdown") {
- let i;
- if ((i = this._domManagers.indexOf(msg.manager)) != -1) {
- this._domManagers.splice(i, 1);
- }
- for (i = this._domRequest.length - 1; i >= 0; i--) {
- if (this._domRequest[i].msg.manager === msg.manager) {
- this._domRequest.splice(i, 1);
- }
- }
- return;
- }
-
- if (!aMessage.target.assertPermission("wifi-manage")) {
- return;
- }
-
- // We are interested in DOMRequests only.
- if (aMessage.name != "WifiManager:getState") {
- this._domRequest.push({name: aMessage.name, msg:msg});
- }
-
- switch (aMessage.name) {
- case "WifiManager:setWifiEnabled":
- this.setWifiEnabled(msg);
- break;
- case "WifiManager:getNetworks":
- this.getNetworks(msg);
- break;
- case "WifiManager:getKnownNetworks":
- this.getKnownNetworks(msg);
- break;
- case "WifiManager:associate":
- this.associate(msg);
- break;
- case "WifiManager:forget":
- this.forget(msg);
- break;
- case "WifiManager:wps":
- this.wps(msg);
- break;
- case "WifiManager:setPowerSavingMode":
- this.setPowerSavingMode(msg);
- break;
- case "WifiManager:setHttpProxy":
- this.setHttpProxy(msg);
- break;
- case "WifiManager:setStaticIpMode":
- this.setStaticIpMode(msg);
- break;
- case "WifiManager:importCert":
- this.importCert(msg);
- break;
- case "WifiManager:getImportedCerts":
- this.getImportedCerts(msg);
- break;
- case "WifiManager:deleteCert":
- this.deleteCert(msg);
- break;
- case "WifiManager:setWifiTethering":
- this.setWifiTethering(msg);
- break;
- case "WifiManager:getState": {
- let i;
- if ((i = this._domManagers.indexOf(msg.manager)) === -1) {
- this._domManagers.push(msg.manager);
- }
-
- let net = this.currentNetwork ? netToDOM(this.currentNetwork) : null;
- return { network: net,
- connectionInfo: this._lastConnectionInfo,
- enabled: WifiManager.enabled,
- status: translateState(WifiManager.state),
- macAddress: this.macAddress,
- capabilities: WifiManager.getCapabilities()};
- }
- }
- },
-
- getNetworks: function(msg) {
- const message = "WifiManager:getNetworks:Return";
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- let sent = false;
- let callback = (function (networks) {
- if (sent)
- return;
- sent = true;
- this._sendMessage(message, networks !== null, networks, msg);
- }).bind(this);
- this.waitForScan(callback);
-
- WifiManager.scan(true, (function(ok) {
- // If the scan command succeeded, we're done.
- if (ok)
- return;
-
- // Avoid sending multiple responses.
- if (sent)
- return;
-
- // Otherwise, let the client know that it failed, it's responsible for
- // trying again in a few seconds.
- sent = true;
- this._sendMessage(message, false, "ScanFailed", msg);
- }).bind(this));
- },
-
- getWifiScanResults: function(callback) {
- var count = 0;
- var timer = null;
- var self = this;
-
- if (!WifiManager.enabled) {
- callback.onfailure();
- return;
- }
-
- self.waitForScan(waitForScanCallback);
- doScan();
- function doScan() {
- WifiManager.scan(true, (function (ok) {
- if (!ok) {
- if (!timer) {
- count = 0;
- timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- }
-
- if (count++ >= 3) {
- timer = null;
- self.wantScanResults.splice(self.wantScanResults.indexOf(waitForScanCallback), 1);
- callback.onfailure();
- return;
- }
-
- // Else it's still running, continue waiting.
- timer.initWithCallback(doScan, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
- return;
- }
- }).bind(this));
- }
-
- function waitForScanCallback(networks) {
- if (networks === null) {
- callback.onfailure();
- return;
- }
-
- var wifiScanResults = new Array();
- var net;
- for (let net in networks) {
- let value = networks[net];
- wifiScanResults.push(transformResult(value));
- }
- callback.onready(wifiScanResults.length, wifiScanResults);
- }
-
- function transformResult(element) {
- var result = new WifiScanResult();
- result.connected = false;
- for (let id in element) {
- if (id === "__exposedProps__") {
- continue;
- }
- if (id === "security") {
- result[id] = 0;
- var security = element[id];
- for (let j = 0; j < security.length; j++) {
- if (security[j] === "WPA-PSK") {
- result[id] |= Ci.nsIWifiScanResult.WPA_PSK;
- } else if (security[j] === "WPA-EAP") {
- result[id] |= Ci.nsIWifiScanResult.WPA_EAP;
- } else if (security[j] === "WEP") {
- result[id] |= Ci.nsIWifiScanResult.WEP;
- } else {
- result[id] = 0;
- }
- }
- } else {
- result[id] = element[id];
- }
- }
- return result;
- }
- },
-
- getKnownNetworks: function(msg) {
- const message = "WifiManager:getKnownNetworks:Return";
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- this._reloadConfiguredNetworks((function(ok) {
- if (!ok) {
- this._sendMessage(message, false, "Failed", msg);
- return;
- }
-
- var networks = [];
- for (let networkKey in this.configuredNetworks) {
- networks.push(netToDOM(this.configuredNetworks[networkKey]));
- }
-
- this._sendMessage(message, true, networks, msg);
- }).bind(this));
- },
-
- _setWifiEnabledCallback: function(status) {
- if (status !== 0) {
- this.requestDone();
- return;
- }
-
- // If we're enabling ourselves, then wait until we've connected to the
- // supplicant to notify. If we're disabling, we take care of this in
- // supplicantlost.
- if (WifiManager.supplicantStarted)
- WifiManager.start();
- },
-
- /**
- * Compatibility flags for detecting if Gaia is controlling wifi by settings
- * or API, once API is called, gecko will no longer accept wifi enable
- * control from settings.
- * This is used to deal with compatibility issue while Gaia adopted to use
- * API but gecko doesn't remove the settings code in time.
- * TODO: Remove this flag in Bug 1050147
- */
- ignoreWifiEnabledFromSettings: false,
- setWifiEnabled: function(msg) {
- const message = "WifiManager:setWifiEnabled:Return";
- let self = this;
- let enabled = msg.data;
-
- self.ignoreWifiEnabledFromSettings = true;
- // No change.
- if (enabled === WifiManager.enabled) {
- this._sendMessage(message, true, true, msg);
- return;
- }
-
- // Can't enable wifi while hotspot mode is enabled.
- if (enabled && (this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED] ||
- WifiManager.isWifiTetheringEnabled(WifiManager.tetheringState))) {
- self._sendMessage(message, false, "Can't enable Wifi while hotspot mode is enabled", msg);
- return;
- }
-
- WifiManager.setWifiEnabled(enabled, function(ok) {
- if (ok === 0 || ok === "no change") {
- self._sendMessage(message, true, true, msg);
-
- // Reply error to pending requests.
- if (!enabled) {
- self._clearPendingRequest();
- } else {
- WifiManager.start();
- }
- } else {
- self._sendMessage(message, false, "Set wifi enabled failed", msg);
- }
- });
- },
-
- _setWifiEnabled: function(enabled, callback) {
- // Reply error to pending requests.
- if (!enabled) {
- this._clearPendingRequest();
- }
-
- WifiManager.setWifiEnabled(enabled, callback);
- },
-
- // requestDone() must be called to before callback complete(or error)
- // so next queue in the request quene can be executed.
- // TODO: Remove command queue in Bug 1050147
- queueRequest: function(data, callback) {
- if (!callback) {
- throw "Try to enqueue a request without callback";
- }
-
- let optimizeCommandList = ["setWifiEnabled", "setWifiApEnabled"];
- if (optimizeCommandList.indexOf(data.command) != -1) {
- this._stateRequests = this._stateRequests.filter(function(element) {
- return element.data.command !== data.command;
- });
- }
-
- this._stateRequests.push({
- data: data,
- callback: callback
- });
-
- this.nextRequest();
- },
-
- getWifiTetheringParameters: function getWifiTetheringParameters(enable) {
- if (this.useTetheringAPI) {
- return this.getWifiTetheringConfiguration(enable);
- } else {
- return this.getWifiTetheringParametersBySetting(enable);
- }
- },
-
- getWifiTetheringConfiguration: function getWifiTetheringConfiguration(enable) {
- let config = {};
- let params = this.tetheringConfig;
-
- let check = function(field, _default) {
- config[field] = field in params ? params[field] : _default;
- };
-
- check("ssid", DEFAULT_WIFI_SSID);
- check("security", DEFAULT_WIFI_SECURITY_TYPE);
- check("key", DEFAULT_WIFI_SECURITY_PASSWORD);
- check("ip", DEFAULT_WIFI_IP);
- check("prefix", DEFAULT_WIFI_PREFIX);
- check("wifiStartIp", DEFAULT_WIFI_DHCPSERVER_STARTIP);
- check("wifiEndIp", DEFAULT_WIFI_DHCPSERVER_ENDIP);
- check("usbStartIp", DEFAULT_USB_DHCPSERVER_STARTIP);
- check("usbEndIp", DEFAULT_USB_DHCPSERVER_ENDIP);
- check("dns1", DEFAULT_DNS1);
- check("dns2", DEFAULT_DNS2);
-
- config.enable = enable;
- config.mode = enable ? WIFI_FIRMWARE_AP : WIFI_FIRMWARE_STATION;
- config.link = enable ? NETWORK_INTERFACE_UP : NETWORK_INTERFACE_DOWN;
-
- // Check the format to prevent netd from crash.
- if (enable && (!config.ssid || config.ssid == "")) {
- debug("Invalid SSID value.");
- return null;
- }
-
- if (enable && (config.security != WIFI_SECURITY_TYPE_NONE && !config.key)) {
- debug("Invalid security password.");
- return null;
- }
-
- // Using the default values here until application supports these settings.
- if (config.ip == "" || config.prefix == "" ||
- config.wifiStartIp == "" || config.wifiEndIp == "" ||
- config.usbStartIp == "" || config.usbEndIp == "") {
- debug("Invalid subnet information.");
- return null;
- }
-
- return config;
- },
-
- getWifiTetheringParametersBySetting: function getWifiTetheringParametersBySetting(enable) {
- let ssid;
- let securityType;
- let securityId;
- let interfaceIp;
- let prefix;
- let wifiDhcpStartIp;
- let wifiDhcpEndIp;
- let usbDhcpStartIp;
- let usbDhcpEndIp;
- let dns1;
- let dns2;
-
- ssid = this.tetheringSettings[SETTINGS_WIFI_SSID];
- securityType = this.tetheringSettings[SETTINGS_WIFI_SECURITY_TYPE];
- securityId = this.tetheringSettings[SETTINGS_WIFI_SECURITY_PASSWORD];
- interfaceIp = this.tetheringSettings[SETTINGS_WIFI_IP];
- prefix = this.tetheringSettings[SETTINGS_WIFI_PREFIX];
- wifiDhcpStartIp = this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP];
- wifiDhcpEndIp = this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP];
- usbDhcpStartIp = this.tetheringSettings[SETTINGS_USB_DHCPSERVER_STARTIP];
- usbDhcpEndIp = this.tetheringSettings[SETTINGS_USB_DHCPSERVER_ENDIP];
- dns1 = this.tetheringSettings[SETTINGS_WIFI_DNS1];
- dns2 = this.tetheringSettings[SETTINGS_WIFI_DNS2];
-
- // Check the format to prevent netd from crash.
- if (!ssid || ssid == "") {
- debug("Invalid SSID value.");
- return null;
- }
- // Truncate ssid if its length of encoded to utf8 is longer than 32.
- while (unescape(encodeURIComponent(ssid)).length > 32)
- {
- ssid = ssid.substring(0, ssid.length-1);
- }
-
- if (securityType != WIFI_SECURITY_TYPE_NONE &&
- securityType != WIFI_SECURITY_TYPE_WPA_PSK &&
- securityType != WIFI_SECURITY_TYPE_WPA2_PSK) {
-
- debug("Invalid security type.");
- return null;
- }
- if (securityType != WIFI_SECURITY_TYPE_NONE && !securityId) {
- debug("Invalid security password.");
- return null;
- }
- // Using the default values here until application supports these settings.
- if (interfaceIp == "" || prefix == "" ||
- wifiDhcpStartIp == "" || wifiDhcpEndIp == "" ||
- usbDhcpStartIp == "" || usbDhcpEndIp == "") {
- debug("Invalid subnet information.");
- return null;
- }
-
- return {
- ssid: ssid,
- security: securityType,
- key: securityId,
- ip: interfaceIp,
- prefix: prefix,
- wifiStartIp: wifiDhcpStartIp,
- wifiEndIp: wifiDhcpEndIp,
- usbStartIp: usbDhcpStartIp,
- usbEndIp: usbDhcpEndIp,
- dns1: dns1,
- dns2: dns2,
- enable: enable,
- mode: enable ? WIFI_FIRMWARE_AP : WIFI_FIRMWARE_STATION,
- link: enable ? NETWORK_INTERFACE_UP : NETWORK_INTERFACE_DOWN
- };
- },
-
- setWifiApEnabled: function(enabled, callback) {
- let configuration = this.getWifiTetheringParameters(enabled);
-
- if (!configuration) {
- this.requestDone();
- debug("Invalid Wifi Tethering configuration.");
- return;
- }
-
- WifiManager.setWifiApEnabled(enabled, configuration, callback);
- },
-
- associate: function(msg) {
- const MAX_PRIORITY = 9999;
- const message = "WifiManager:associate:Return";
- let network = msg.data;
-
- let privnet = network;
- let dontConnect = privnet.dontConnect;
- delete privnet.dontConnect;
-
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- let self = this;
- function networkReady() {
- // saveConfig now before we disable most of the other networks.
- function selectAndConnect() {
- WifiManager.enableNetwork(privnet.netId, true, function (ok) {
- if (ok)
- self._needToEnableNetworks = true;
- if (WifiManager.state === "DISCONNECTED" ||
- WifiManager.state === "SCANNING") {
- WifiManager.reconnect(function (ok) {
- self._sendMessage(message, ok, ok, msg);
- });
- } else {
- self._sendMessage(message, ok, ok, msg);
- }
- });
- }
-
- var selectAndConnectOrReturn = dontConnect ?
- function() {
- self._sendMessage(message, true, "Wifi has been recorded", msg);
- } : selectAndConnect;
- if (self._highestPriority >= MAX_PRIORITY) {
- self._reprioritizeNetworks(selectAndConnectOrReturn);
- } else {
- WifiManager.saveConfig(selectAndConnectOrReturn);
- }
- }
-
- function connectToNetwork() {
- WifiManager.updateNetwork(privnet, (function(ok) {
- if (!ok) {
- self._sendMessage(message, false, "Network is misconfigured", msg);
- return;
- }
-
- networkReady();
- }));
- }
-
- let ssid = privnet.ssid;
- let networkKey = getNetworkKey(privnet);
- let configured;
-
- if (networkKey in this._addingNetworks) {
- this._sendMessage(message, false, "Racing associates");
- return;
- }
-
- if (networkKey in this.configuredNetworks)
- configured = this.configuredNetworks[networkKey];
-
- netFromDOM(privnet, configured);
-
- privnet.priority = ++this._highestPriority;
- if (configured) {
- privnet.netId = configured.netId;
- // Sync priority back to configured so if priority reaches MAX_PRIORITY,
- // it can be sorted correctly in _reprioritizeNetworks() because the
- // function sort network based on priority in configure list.
- configured.priority = privnet.priority;
-
- // When investigating Bug 1123680, we observed that gaia may unexpectedly
- // request to associate with incorrect password before successfully
- // forgetting the network. It would cause the network unable to connect
- // subsequently. Aside from preventing the racing forget/associate, we
- // also try to disable network prior to updating the network.
- WifiManager.getNetworkId(dequote(configured.ssid), function(netId) {
- if (netId) {
- WifiManager.disableNetwork(netId, function() {
- connectToNetwork();
- });
- }
- else {
- connectToNetwork();
- }
- });
- } else {
- // networkReady, above, calls saveConfig. We want to remember the new
- // network as being enabled, which isn't the default, so we explicitly
- // set it to being "enabled" before we add it and save the
- // configuration.
- privnet.disabled = 0;
- this._addingNetworks[networkKey] = privnet;
- WifiManager.addNetwork(privnet, (function(ok) {
- delete this._addingNetworks[networkKey];
-
- if (!ok) {
- this._sendMessage(message, false, "Network is misconfigured", msg);
- return;
- }
-
- this.configuredNetworks[networkKey] = privnet;
- networkReady();
- }).bind(this));
- }
- },
-
- forget: function(msg) {
- const message = "WifiManager:forget:Return";
- let network = msg.data;
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- this._reloadConfiguredNetworks((function(ok) {
- // Give it a chance to remove the network even if reload is failed.
- if (!ok) {
- debug("Warning !!! Failed to reload the configured networks");
- }
-
- let ssid = network.ssid;
- let networkKey = getNetworkKey(network);
- if (!(networkKey in this.configuredNetworks)) {
- this._sendMessage(message, false, "Trying to forget an unknown network", msg);
- return;
- }
-
- let self = this;
- let configured = this.configuredNetworks[networkKey];
- this._reconnectOnDisconnect = (this.currentNetwork &&
- (this.currentNetwork.ssid === ssid));
- WifiManager.removeNetwork(configured.netId, function(ok) {
- if (self._needToEnableNetworks) {
- self._enableAllNetworks();
- self._needToEnableNetworks = false;
- }
-
- if (!ok) {
- self._sendMessage(message, false, "Unable to remove the network", msg);
- self._reconnectOnDisconnect = false;
- return;
- }
-
- WifiManager.saveConfig(function() {
- self._reloadConfiguredNetworks(function() {
- self._sendMessage(message, true, true, msg);
- });
- });
- });
- }).bind(this));
- },
-
- wps: function(msg) {
- const message = "WifiManager:wps:Return";
- let self = this;
- let detail = msg.data;
-
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- if (detail.method === "pbc") {
- WifiManager.wpsPbc(function(ok) {
- if (ok)
- self._sendMessage(message, true, true, msg);
- else
- self._sendMessage(message, false, "WPS PBC failed", msg);
- });
- } else if (detail.method === "pin") {
- WifiManager.wpsPin(detail, function(pin) {
- if (pin)
- self._sendMessage(message, true, pin, msg);
- else
- self._sendMessage(message, false, "WPS PIN failed", msg);
- });
- } else if (detail.method === "cancel") {
- WifiManager.wpsCancel(function(ok) {
- if (ok)
- self._sendMessage(message, true, true, msg);
- else
- self._sendMessage(message, false, "WPS Cancel failed", msg);
- });
- } else {
- self._sendMessage(message, false, "Invalid WPS method=" + detail.method,
- msg);
- }
- },
-
- setPowerSavingMode: function(msg) {
- const message = "WifiManager:setPowerSavingMode:Return";
- let self = this;
- let enabled = msg.data;
- let mode = enabled ? "AUTO" : "ACTIVE";
-
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- // Some wifi drivers may not implement this command. Set power mode
- // even if suspend optimization command failed.
- WifiManager.setSuspendOptimizations(enabled, function(ok) {
- WifiManager.setPowerMode(mode, function(ok) {
- if (ok) {
- self._sendMessage(message, true, true, msg);
- } else {
- self._sendMessage(message, false, "Set power saving mode failed", msg);
- }
- });
- });
- },
-
- setHttpProxy: function(msg) {
- const message = "WifiManager:setHttpProxy:Return";
- let self = this;
- let network = msg.data.network;
- let info = msg.data.info;
-
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- WifiManager.configureHttpProxy(network, info, function(ok) {
- if (ok) {
- // If configured network is current connected network
- // need update http proxy immediately.
- let setNetworkKey = getNetworkKey(network);
- let curNetworkKey = self.currentNetwork ? getNetworkKey(self.currentNetwork) : null;
- if (setNetworkKey === curNetworkKey)
- WifiManager.setHttpProxy(network);
-
- self._sendMessage(message, true, true, msg);
- } else {
- self._sendMessage(message, false, "Set http proxy failed", msg);
- }
- });
- },
-
- setStaticIpMode: function(msg) {
- const message = "WifiManager:setStaticIpMode:Return";
- let self = this;
- let network = msg.data.network;
- let info = msg.data.info;
-
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- // To compatiable with DHCP returned info structure, do translation here
- info.ipaddr_str = info.ipaddr;
- info.proxy_str = info.proxy;
- info.gateway_str = info.gateway;
- info.dns1_str = info.dns1;
- info.dns2_str = info.dns2;
-
- WifiManager.setStaticIpMode(network, info, function(ok) {
- if (ok) {
- self._sendMessage(message, true, true, msg);
- } else {
- self._sendMessage(message, false, "Set static ip mode failed", msg);
- }
- });
- },
-
- importCert: function importCert(msg) {
- const message = "WifiManager:importCert:Return";
- let self = this;
-
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- WifiManager.importCert(msg.data, function(data) {
- if (data.status === 0) {
- let usageString = ["ServerCert", "UserCert"];
- let usageArray = [];
- for (let i = 0; i < usageString.length; i++) {
- if (data.usageFlag & (0x01 << i)) {
- usageArray.push(usageString[i]);
- }
- }
-
- self._sendMessage(message, true, {
- nickname: data.nickname,
- usage: usageArray
- }, msg);
- } else {
- self._sendMessage(message, false, "Import Cert failed", msg);
- }
- });
- },
-
- getImportedCerts: function getImportedCerts(msg) {
- const message = "WifiManager:getImportedCerts:Return";
- let self = this;
-
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- let certDB = Cc["@mozilla.org/security/x509certdb;1"]
- .getService(Ci.nsIX509CertDB);
- if (!certDB) {
- self._sendMessage(message, false, "Failed to query NSS DB service", msg);
- }
-
- let certList = certDB.getCerts();
- if (!certList) {
- self._sendMessage(message, false, "Failed to get certificate List", msg);
- }
-
- let certListEnum = certList.getEnumerator();
- if (!certListEnum) {
- self._sendMessage(message, false, "Failed to get certificate List enumerator", msg);
- }
- let importedCerts = {
- ServerCert: [],
- UserCert: [],
- };
- let UsageMapping = {
- SERVERCERT: "ServerCert",
- USERCERT: "UserCert",
- };
-
- while (certListEnum.hasMoreElements()) {
- let certInfo = certListEnum.getNext().QueryInterface(Ci.nsIX509Cert);
- let certNicknameInfo = /WIFI\_([A-Z]*)\_(.*)/.exec(certInfo.nickname);
- if (!certNicknameInfo) {
- continue;
- }
- importedCerts[UsageMapping[certNicknameInfo[1]]].push(certNicknameInfo[2]);
- }
-
- self._sendMessage(message, true, importedCerts, msg);
- },
-
- deleteCert: function deleteCert(msg) {
- const message = "WifiManager:deleteCert:Return";
- let self = this;
-
- if (!WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is disabled", msg);
- return;
- }
-
- WifiManager.deleteCert(msg.data, function(data) {
- self._sendMessage(message, data.status === 0, "Delete Cert failed", msg);
- });
- },
-
- // TODO : These two variables should be removed once GAIA uses tethering API.
- useTetheringAPI : false,
- tetheringConfig : {},
-
- setWifiTethering: function setWifiTethering(msg) {
- const message = "WifiManager:setWifiTethering:Return";
- let self = this;
- let enabled = msg.data.enabled;
-
- this.useTetheringAPI = true;
- this.tetheringConfig = msg.data.config;
-
- if (WifiManager.enabled) {
- this._sendMessage(message, false, "Wifi is enabled", msg);
- return;
- }
-
- this.setWifiApEnabled(enabled, function() {
- if ((enabled && WifiManager.tetheringState == "COMPLETED") ||
- (!enabled && WifiManager.tetheringState == "UNINITIALIZED")) {
- self._sendMessage(message, true, msg.data, msg);
- } else {
- msg.data.reason = enabled ?
- "Enable WIFI tethering faild" : "Disable WIFI tethering faild";
- self._sendMessage(message, false, msg.data, msg);
- }
- });
- },
-
- // This is a bit ugly, but works. In particular, this depends on the fact
- // that RadioManager never actually tries to get the worker from us.
- get worker() { throw "Not implemented"; },
-
- shutdown: function() {
- debug("shutting down ...");
- this.queueRequest({command: "setWifiEnabled", value: false}, function(data) {
- this._setWifiEnabled(false, this._setWifiEnabledCallback.bind(this));
- }.bind(this));
- },
-
- // TODO: Remove command queue in Bug 1050147.
- requestProcessing: false, // Hold while dequeue and execution a request.
- // Released upon the request is fully executed,
- // i.e, mostly after callback is done.
- requestDone: function requestDone() {
- this.requestProcessing = false;
- this.nextRequest();
- },
-
- nextRequest: function nextRequest() {
- // No request to process
- if (this._stateRequests.length === 0) {
- return;
- }
-
- // Handling request, wait for it.
- if (this.requestProcessing) {
- return;
- }
-
- // Hold processing lock
- this.requestProcessing = true;
-
- // Find next valid request
- let request = this._stateRequests.shift();
-
- request.callback(request.data);
- },
-
- notifyTetheringOn: function notifyTetheringOn() {
- // It's really sad that we don't have an API to notify the wifi
- // hotspot status. Toggle settings to let gaia know that wifi hotspot
- // is enabled.
- let self = this;
- this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED] = true;
- this._oldWifiTetheringEnabledState = true;
- gSettingsService.createLock().set(
- SETTINGS_WIFI_TETHERING_ENABLED,
- true,
- {
- handle: function(aName, aResult) {
- self.requestDone();
- },
- handleError: function(aErrorMessage) {
- self.requestDone();
- }
- });
- },
-
- notifyTetheringOff: function notifyTetheringOff() {
- // It's really sad that we don't have an API to notify the wifi
- // hotspot status. Toggle settings to let gaia know that wifi hotspot
- // is disabled.
- let self = this;
- this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED] = false;
- this._oldWifiTetheringEnabledState = false;
- gSettingsService.createLock().set(
- SETTINGS_WIFI_TETHERING_ENABLED,
- false,
- {
- handle: function(aName, aResult) {
- self.requestDone();
- },
- handleError: function(aErrorMessage) {
- self.requestDone();
- }
- });
- },
-
- handleWifiEnabled: function(enabled) {
- if (this.ignoreWifiEnabledFromSettings) {
- return;
- }
-
- // Make sure Wifi hotspot is idle before switching to Wifi mode.
- if (enabled) {
- this.queueRequest({command: "setWifiApEnabled", value: false}, function(data) {
- if (this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED] ||
- WifiManager.isWifiTetheringEnabled(WifiManager.tetheringState)) {
- this.disconnectedByWifi = true;
- this.setWifiApEnabled(false, this.notifyTetheringOff.bind(this));
- } else {
- this.requestDone();
- }
- }.bind(this));
- }
-
- this.queueRequest({command: "setWifiEnabled", value: enabled}, function(data) {
- this._setWifiEnabled(enabled, this._setWifiEnabledCallback.bind(this));
- }.bind(this));
-
- if (!enabled) {
- this.queueRequest({command: "setWifiApEnabled", value: true}, function(data) {
- if (this.disconnectedByWifi) {
- this.setWifiApEnabled(true, this.notifyTetheringOn.bind(this));
- } else {
- this.requestDone();
- }
- this.disconnectedByWifi = false;
- }.bind(this));
- }
- },
-
- handleWifiTetheringEnabled: function(enabled) {
- // Make sure Wifi is idle before switching to Wifi hotspot mode.
- if (enabled) {
- this.queueRequest({command: "setWifiEnabled", value: false}, function(data) {
- if (WifiManager.isWifiEnabled(WifiManager.state)) {
- this.disconnectedByWifiTethering = true;
- this._setWifiEnabled(false, this._setWifiEnabledCallback.bind(this));
- } else {
- this.requestDone();
- }
- }.bind(this));
- }
-
- this.queueRequest({command: "setWifiApEnabled", value: enabled}, function(data) {
- this.setWifiApEnabled(enabled, this.requestDone.bind(this));
- }.bind(this));
-
- if (!enabled) {
- this.queueRequest({command: "setWifiEnabled", value: true}, function(data) {
- if (this.disconnectedByWifiTethering) {
- this._setWifiEnabled(true, this._setWifiEnabledCallback.bind(this));
- } else {
- this.requestDone();
- }
- this.disconnectedByWifiTethering = false;
- }.bind(this));
- }
- },
-
- // nsIObserver implementation
- observe: function observe(subject, topic, data) {
- switch (topic) {
- case kMozSettingsChangedObserverTopic:
- // To avoid WifiWorker setting the wifi again, don't need to deal with
- // the "mozsettings-changed" event fired from internal setting.
- if ("wrappedJSObject" in subject) {
- subject = subject.wrappedJSObject;
- }
- if (subject.isInternalChange) {
- return;
- }
-
- this.handle(subject.key, subject.value);
- break;
-
- case "xpcom-shutdown":
- // Ensure the supplicant is detached from B2G to avoid XPCOM shutdown
- // blocks forever.
- WifiManager.ensureSupplicantDetached(() => {
- let wifiService = Cc["@mozilla.org/wifi/service;1"].getService(Ci.nsIWifiProxyService);
- wifiService.shutdown();
- let wifiCertService = Cc["@mozilla.org/wifi/certservice;1"].getService(Ci.nsIWifiCertService);
- wifiCertService.shutdown();
- });
- break;
- }
- },
-
- handle: function handle(aName, aResult) {
- switch(aName) {
- // TODO: Remove function call in Bug 1050147.
- case SETTINGS_WIFI_ENABLED:
- this.handleWifiEnabled(aResult)
- break;
- case SETTINGS_WIFI_DEBUG_ENABLED:
- if (aResult === null)
- aResult = false;
- DEBUG = aResult;
- updateDebug();
- break;
- case SETTINGS_WIFI_TETHERING_ENABLED:
- this._oldWifiTetheringEnabledState = this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED];
- // Fall through!
- case SETTINGS_WIFI_SSID:
- case SETTINGS_WIFI_SECURITY_TYPE:
- case SETTINGS_WIFI_SECURITY_PASSWORD:
- case SETTINGS_WIFI_IP:
- case SETTINGS_WIFI_PREFIX:
- case SETTINGS_WIFI_DHCPSERVER_STARTIP:
- case SETTINGS_WIFI_DHCPSERVER_ENDIP:
- case SETTINGS_WIFI_DNS1:
- case SETTINGS_WIFI_DNS2:
- case SETTINGS_USB_DHCPSERVER_STARTIP:
- case SETTINGS_USB_DHCPSERVER_ENDIP:
- // TODO: code related to wifi-tethering setting should be removed after GAIA
- // use tethering API
- if (this.useTetheringAPI) {
- break;
- }
-
- if (aResult !== null) {
- this.tetheringSettings[aName] = aResult;
- }
- debug("'" + aName + "'" + " is now " + this.tetheringSettings[aName]);
- let index = this._wifiTetheringSettingsToRead.indexOf(aName);
-
- if (index != -1) {
- this._wifiTetheringSettingsToRead.splice(index, 1);
- }
-
- if (this._wifiTetheringSettingsToRead.length) {
- debug("We haven't read completely the wifi Tethering data from settings db.");
- break;
- }
-
- if (this._oldWifiTetheringEnabledState === this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED]) {
- debug("No changes for SETTINGS_WIFI_TETHERING_ENABLED flag. Nothing to do.");
- break;
- }
-
- if (this._oldWifiTetheringEnabledState === null &&
- !this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED]) {
- debug("Do nothing when initial settings for SETTINGS_WIFI_TETHERING_ENABLED flag is false.");
- break;
- }
-
- this._oldWifiTetheringEnabledState = this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED];
- this.handleWifiTetheringEnabled(aResult)
- break;
- };
- },
-
- handleError: function handleError(aErrorMessage) {
- debug("There was an error while reading Tethering settings.");
- this.tetheringSettings = {};
- this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED] = false;
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WifiWorker]);
-
-var debug;
-function updateDebug() {
- if (DEBUG) {
- debug = function (s) {
- dump("-*- WifiWorker component: " + s + "\n");
- };
- } else {
- debug = function (s) {};
- }
- WifiManager.syncDebug();
-}
-updateDebug();
diff --git a/dom/wifi/WifiWorker.manifest b/dom/wifi/WifiWorker.manifest
deleted file mode 100644
index e33d6401a..000000000
--- a/dom/wifi/WifiWorker.manifest
+++ /dev/null
@@ -1 +0,0 @@
-component {a14e8977-d259-433a-a88d-58dd44657e5b} WifiWorker.js
diff --git a/dom/wifi/moz.build b/dom/wifi/moz.build
deleted file mode 100644
index d769c649c..000000000
--- a/dom/wifi/moz.build
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += [
- 'nsIWifi.idl',
- 'nsIWifiCertService.idl',
- 'nsIWifiService.idl',
-]
-
-XPIDL_MODULE = 'dom_wifi'
-
-EXTRA_COMPONENTS += [
- 'DOMWifiManager.js',
- 'DOMWifiManager.manifest',
- 'DOMWifiP2pManager.js',
- 'DOMWifiP2pManager.manifest',
- 'WifiWorker.js',
- 'WifiWorker.manifest',
-]
-
-EXTRA_JS_MODULES += [
- 'StateMachine.jsm',
- 'WifiCommand.jsm',
- 'WifiNetUtil.jsm',
- 'WifiP2pManager.jsm',
- 'WifiP2pWorkerObserver.jsm',
-]
-
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- UNIFIED_SOURCES = [
- 'WifiCertService.cpp',
- 'WifiHotspotUtils.cpp',
- 'WifiProxyService.cpp',
- 'WifiUtils.cpp',
- ]
- DEFINES['CERT_AddTempCertToPerm'] = '__CERT_AddTempCertToPerm'
-
-FINAL_LIBRARY = 'xul'
diff --git a/dom/wifi/nsIWifi.idl b/dom/wifi/nsIWifi.idl
deleted file mode 100644
index 82ab9a75b..000000000
--- a/dom/wifi/nsIWifi.idl
+++ /dev/null
@@ -1,60 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsIDOMDOMRequest.idl"
-#include "nsIDOMEvent.idl"
-
-interface nsIVariant;
-
-[scriptable, uuid(cf1ac02b-1f39-446e-815b-651ac78d2233)]
-interface nsIWifiScanResult : nsISupports {
- readonly attribute DOMString ssid;
- readonly attribute DOMString bssid;
-
- const int32_t WPA_PSK = 0x01;
- const int32_t WPA_EAP = 0x02;
- const int32_t WEP = 0x04;
- readonly attribute uint32_t capabilities;
-
- /**
- * Strength of the signal to network.
- */
- readonly attribute uint32_t signalStrength;
-
- readonly attribute uint32_t relSignalStrength;
- readonly attribute boolean connected;
-};
-
-[scriptable, uuid(a6931ebf-8493-4014-90e2-99f406999982)]
-interface nsIWifiScanResultsReady : nsISupports {
-
- /**
- * Callback with list of networks.
- */
- void onready(in uint32_t count, [array, size_is(count)] in nsIWifiScanResult results);
-
- /**
- * Callback if scanning for networks failed after 3 retry attempts.
- */
- void onfailure();
-};
-
-[scriptable, uuid(08dfefed-5c5d-4468-8c5d-2c65c24692d9)]
-interface nsIWifi : nsISupports
-{
- /**
- * Shutdown the wifi system.
- */
- void shutdown();
-
- /**
- * Returns the list of currently available networks as well as the list of
- * currently configured networks.
- *
- * On success a callback is notified with the list of networks.
- * On failure after 3 scan retry attempts a callback is notified of failure.
- */
- void getWifiScanResults(in nsIWifiScanResultsReady callback);
-};
diff --git a/dom/wifi/nsIWifiCertService.idl b/dom/wifi/nsIWifiCertService.idl
deleted file mode 100644
index fce2dd719..000000000
--- a/dom/wifi/nsIWifiCertService.idl
+++ /dev/null
@@ -1,54 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMBlob;
-interface nsIWifiEventListener;
-
-[scriptable, uuid(5d0edcd3-c2f1-4946-aae5-06adcbdf0992)]
-interface nsIWifiCertService : nsISupports
-{
- const unsigned short WIFI_CERT_USAGE_FLAG_SERVER = 0x01;
- const unsigned short WIFI_CERT_USAGE_FLAG_USER = 0x02;
-
- void start(in nsIWifiEventListener listener);
- void shutdown();
-
- /**
- * Import a certificate file.
- *
- * @param id
- * Request ID.
- * @param certBlob
- * A Blob object containing raw data of certificate to be imported.
- * @param certPassword
- * Password of certificate.
- * @param certNickname
- * User assigned nickname for imported certificate.
- */
- void importCert(in long id,
- in nsIDOMBlob certBlob,
- in DOMString certPassword,
- in DOMString certNickname);
-
- /**
- * Delete an imported certificate file
- *
- * @param id
- * Request ID.
- * @param certNickname
- * Certificate nickname to delete.
- */
- void deleteCert(in long id,
- in DOMString certNickname);
-
- /**
- * Check if certificate has private key.
- *
- * @param certNickname
- * Certificate nickname to check for private key.
- */
- boolean hasPrivateKey(in DOMString certNickname);
-};
diff --git a/dom/wifi/nsIWifiService.idl b/dom/wifi/nsIWifiService.idl
deleted file mode 100644
index 0f320ddda..000000000
--- a/dom/wifi/nsIWifiService.idl
+++ /dev/null
@@ -1,22 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(4d4389e0-1547-11e3-8ffd-0800200c9a66)]
-interface nsIWifiEventListener : nsISupports {
- void onWaitEvent(in AString event, in ACString aInterface);
- void onCommand(in jsval result, in ACString aInterface);
-};
-
-[scriptable, uuid(5e2bd8c0-1547-11e3-8ffd-0800200c9a66)]
-interface nsIWifiProxyService : nsISupports {
- void start(in nsIWifiEventListener listener,
- [array, size_is(aNumOfInterface)] in string aInterfaces,
- in unsigned long aNumOfInterface);
- void shutdown();
- [implicit_jscontext]
- void sendCommand(in jsval parameters, in ACString aInterface);
- void waitForEvent(in ACString aInterface);
-};
diff --git a/dom/wifi/test/marionette/head.js b/dom/wifi/test/marionette/head.js
deleted file mode 100644
index f4a212b11..000000000
--- a/dom/wifi/test/marionette/head.js
+++ /dev/null
@@ -1,1486 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Emulate Promise.jsm semantics.
-Promise.defer = function() { return new Deferred(); }
-function Deferred() {
- this.promise = new Promise(function(resolve, reject) {
- this.resolve = resolve;
- this.reject = reject;
- }.bind(this));
- Object.freeze(this);
-}
-
-const STOCK_HOSTAPD_NAME = 'goldfish-hostapd';
-const HOSTAPD_CONFIG_PATH = '/data/misc/wifi/remote-hostapd/';
-
-const SETTINGS_RIL_DATA_ENABLED = 'ril.data.enabled';
-const SETTINGS_TETHERING_WIFI_ENABLED = 'tethering.wifi.enabled';
-const SETTINGS_TETHERING_WIFI_IP = 'tethering.wifi.ip';
-const SETTINGS_TETHERING_WIFI_SECURITY = 'tethering.wifi.security.type';
-
-const HOSTAPD_COMMON_CONFIG = {
- driver: 'test',
- ctrl_interface: '/data/misc/wifi/remote-hostapd',
- test_socket: 'DIR:/data/misc/wifi/sockets',
- hw_mode: 'b',
- channel: '2',
-};
-
-const HOSTAPD_CONFIG_LIST = [
- { ssid: 'ap0' },
-
- { ssid: 'ap1',
- wpa: 1,
- wpa_pairwise: 'TKIP CCMP',
- wpa_passphrase: '12345678'
- },
-
- { ssid: 'ap2',
- wpa: 2,
- rsn_pairwise: 'CCMP',
- wpa_passphrase: '12345678',
- },
-];
-
-var gTestSuite = (function() {
- let suite = {};
-
- // Private member variables of the returned object |suite|.
- let wifiManager;
- let wifiOrigEnabled;
- let pendingEmulatorShellCount = 0;
- let sdkVersion;
-
- /**
- * A wrapper function of "is".
- *
- * Calls the marionette function "is" as well as throws an exception
- * if the givens values are not equal.
- *
- * @param value1
- * Any type of value to compare.
- *
- * @param value2
- * Any type of value to compare.
- *
- * @param message
- * Debug message for this check.
- *
- */
- function isOrThrow(value1, value2, message) {
- is(value1, value2, message);
- if (value1 !== value2) {
- throw message;
- }
- }
-
- /**
- * Send emulator shell command with safe guard.
- *
- * We should only call |finish()| after all emulator command transactions
- * end, so here comes with the pending counter. Resolve when the emulator
- * gives positive response, and reject otherwise.
- *
- * Fulfill params:
- * result -- an array of emulator response lines.
- * Reject params:
- * result -- an array of emulator response lines.
- *
- * @param aCommand
- * A string command to be passed to emulator through its telnet console.
- *
- * @return A deferred promise.
- */
- function runEmulatorShellSafe(aCommand) {
- let deferred = Promise.defer();
-
- ++pendingEmulatorShellCount;
- runEmulatorShell(aCommand, function(aResult) {
- --pendingEmulatorShellCount;
-
- ok(true, "Emulator shell response: " + JSON.stringify(aResult));
- if (Array.isArray(aResult)) {
- deferred.resolve(aResult);
- } else {
- deferred.reject(aResult);
- }
- });
-
- return deferred.promise;
- }
-
- /**
- * Wait for one named MozWifiManager event.
- *
- * Resolve if that named event occurs. Never reject.
- *
- * Fulfill params: the DOMEvent passed.
- *
- * @param aEventName
- * A string event name.
- *
- * @return A deferred promise.
- */
- function waitForWifiManagerEventOnce(aEventName) {
- let deferred = Promise.defer();
-
- wifiManager.addEventListener(aEventName, function onevent(aEvent) {
- wifiManager.removeEventListener(aEventName, onevent);
-
- ok(true, "WifiManager event '" + aEventName + "' got.");
- deferred.resolve(aEvent);
- });
-
- return deferred.promise;
- }
-
- /**
- * Wait for one named MozMobileConnection event.
- *
- * Resolve if that named event occurs. Never reject.
- *
- * Fulfill params: the DOMEvent passed.
- *
- * @param aEventName
- * A string event name.
- *
- * @return A deferred promise.
- */
- function waitForMobileConnectionEventOnce(aEventName, aServiceId) {
- aServiceId = aServiceId || 0;
-
- let deferred = Promise.defer();
- let mobileconnection = navigator.mozMobileConnections[aServiceId];
-
- mobileconnection.addEventListener(aEventName, function onevent(aEvent) {
- mobileconnection.removeEventListener(aEventName, onevent);
-
- ok(true, "Mobile connection event '" + aEventName + "' got.");
- deferred.resolve(aEvent);
- });
-
- return deferred.promise;
- }
-
- /**
- * Get the detail of currently running processes containing the given name.
- *
- * Use shell command 'ps' to get the desired process's detail. Never reject.
- *
- * Fulfill params:
- * result -- an array of { pname, pid }
- *
- * @param aProcessName
- * The process to get the detail.
- *
- * @return A deferred promise.
- */
- function getProcessDetail(aProcessName) {
- return runEmulatorShellSafe(['ps'])
- .then(processes => {
- // Sample 'ps' output:
- //
- // USER PID PPID VSIZE RSS WCHAN PC NAME
- // root 1 0 284 204 c009e6c4 0000deb4 S /init
- // root 2 0 0 0 c0052c64 00000000 S kthreadd
- // root 3 2 0 0 c0044978 00000000 S ksoftirqd/0
- //
- let detail = [];
-
- processes.shift(); // Skip the first line.
- for (let i = 0; i < processes.length; i++) {
- let tokens = processes[i].split(/\s+/);
- let pname = tokens[tokens.length - 1];
- let pid = tokens[1];
- if (-1 !== pname.indexOf(aProcessName)) {
- detail.push({ pname: pname, pid: pid });
- }
- }
-
- return detail;
- });
- }
-
- /**
- * Add required permissions for wifi testing. Never reject.
- *
- * The permissions required for wifi testing are 'wifi-manage' and 'settings-write'.
- * Never reject.
- *
- * Fulfill params: (none)
- *
- * @return A deferred promise.
- */
- function addRequiredPermissions() {
- let deferred = Promise.defer();
-
- let permissions = [{ 'type': 'wifi-manage', 'allow': 1, 'context': window.document },
- { 'type': 'settings-write', 'allow': 1, 'context': window.document },
- { 'type': 'settings-read', 'allow': 1, 'context': window.document },
- { 'type': 'settings-api-write', 'allow': 1, 'context': window.document },
- { 'type': 'settings-api-read', 'allow': 1, 'context': window.document },
- { 'type': 'mobileconnection', 'allow': 1, 'context': window.document }];
-
- SpecialPowers.pushPermissions(permissions, function() {
- deferred.resolve();
- });
-
- return deferred.promise;
- }
-
- /**
- * Wrap DOMRequest onsuccess/onerror events to Promise resolve/reject.
- *
- * Fulfill params: A DOMEvent.
- * Reject params: A DOMEvent.
- *
- * @param aRequest
- * A DOMRequest instance.
- *
- * @return A deferred promise.
- */
- function wrapDomRequestAsPromise(aRequest) {
- let deferred = Promise.defer();
-
- ok(aRequest instanceof DOMRequest,
- "aRequest is instanceof " + aRequest.constructor);
-
- aRequest.addEventListener("success", function(aEvent) {
- deferred.resolve(aEvent);
- });
- aRequest.addEventListener("error", function(aEvent) {
- deferred.reject(aEvent);
- });
-
- return deferred.promise;
- }
-
- /**
- * Ensure wifi is enabled/disabled.
- *
- * Issue a wifi enable/disable request if wifi is not in the desired state;
- * return a resolved promise otherwise. Note that you cannot rely on this
- * function to test the correctness of enabling/disabling wifi.
- * (use requestWifiEnabled instead)
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return a resolved promise or deferred promise.
- */
- function ensureWifiEnabled(aEnabled, useAPI) {
- if (wifiManager.enabled === aEnabled) {
- log('Already ' + (aEnabled ? 'enabled' : 'disabled'));
- return Promise.resolve();
- }
- return requestWifiEnabled(aEnabled, useAPI);
- }
-
- /**
- * Issue a request to enable/disable wifi.
- *
- * This function will attempt to enable/disable wifi, by calling API or by
- * writing settings 'wifi.enabled' regardless of the wifi state, based on the
- * value of |userAPI| parameter.
- * Default is using settings.
- *
- * Note there's a limitation of co-existance of both method, per bug 930355,
- * that once enable/disable wifi by API, the settings method won't work until
- * reboot. So the test of wifi enable API should be executed last.
- * TODO: Remove settings method after enable/disable wifi by settings is
- * removed after bug 1050147.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function requestWifiEnabled(aEnabled, useAPI) {
- return Promise.all([
- waitForWifiManagerEventOnce(aEnabled ? 'enabled' : 'disabled'),
- useAPI ?
- wrapDomRequestAsPromise(wifiManager.setWifiEnabled(aEnabled)) :
- setSettings({ 'wifi.enabled': aEnabled }),
- ]);
- }
-
- /**
- * Wait for RIL data being connected.
- *
- * This function will check |MozMobileConnection.data.connected| on
- * every 'datachange' event. Resolve when |MozMobileConnection.data.connected|
- * becomes the expected state. Never reject.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aConnected
- * Boolean that indicates the desired data state.
- *
- * @param aServiceId [optional]
- * A numeric DSDS service id. Default: 0.
- *
- * @return A deferred promise.
- */
- function waitForRilDataConnected(aConnected, aServiceId) {
- aServiceId = aServiceId || 0;
- return waitForMobileConnectionEventOnce('datachange', aServiceId)
- .then(function () {
- let mobileconnection = navigator.mozMobileConnections[aServiceId];
- if (mobileconnection.data.connected !== aConnected) {
- return waitForRilDataConnected(aConnected, aServiceId);
- }
- });
- }
-
- /**
- * Request to enable/disable wifi tethering.
- *
- * Enable/disable wifi tethering by changing the settings value 'tethering.wifi.enabled'.
- * Resolve when the routing is verified to set up successfully in 20 seconds. The polling
- * period is 1 second.
- *
- * Fulfill params: (none)
- * Reject params: The error message.
- *
- * @param aEnabled
- * Boolean that indicates to enable or disable wifi tethering.
- *
- * @return A deferred promise.
- */
- function requestTetheringEnabled(aEnabled) {
- let RETRY_INTERVAL_MS = 1000;
- let retryCnt = 20;
-
- return setSettings1(SETTINGS_TETHERING_WIFI_ENABLED, aEnabled)
- .then(function waitForRoutingVerified() {
- return verifyTetheringRouting(aEnabled)
- .then(null, function onreject(aReason) {
-
- log('verifyTetheringRouting rejected due to ' + aReason +
- ' (' + retryCnt + ')');
-
- if (!retryCnt--) {
- throw aReason;
- }
-
- return waitForTimeout(RETRY_INTERVAL_MS).then(waitForRoutingVerified);
- });
- });
- }
-
- /**
- * Forget the given network.
- *
- * Resolve when we successfully forget the given network; reject when any error
- * occurs.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aNetwork
- * An object of MozWifiNetwork.
- *
- * @return A deferred promise.
- */
- function forgetNetwork(aNetwork) {
- let request = wifiManager.forget(aNetwork);
- return wrapDomRequestAsPromise(request)
- .then(event => event.target.result);
- }
-
- /**
- * Forget all known networks.
- *
- * Resolve when we successfully forget all the known network;
- * reject when any error occurs.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function forgetAllKnownNetworks() {
-
- function createForgetNetworkChain(aNetworks) {
- let chain = Promise.resolve();
-
- aNetworks.forEach(function (aNetwork) {
- chain = chain.then(() => forgetNetwork(aNetwork));
- });
-
- return chain;
- }
-
- return getKnownNetworks()
- .then(networks => createForgetNetworkChain(networks));
- }
-
- /**
- * Get all known networks.
- *
- * Resolve when we get all the known networks; reject when any error
- * occurs.
- *
- * Fulfill params: An array of MozWifiNetwork
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function getKnownNetworks() {
- let request = wifiManager.getKnownNetworks();
- return wrapDomRequestAsPromise(request)
- .then(event => event.target.result);
- }
-
- /**
- * Set the given network to static ip mode.
- *
- * Resolve when we set static ip mode successfully; reject when any error
- * occurs.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function setStaticIpMode(aNetwork, aConfig) {
- let request = wifiManager.setStaticIpMode(aNetwork, aConfig);
- return wrapDomRequestAsPromise(request)
- .then(event => event.target.result);
- }
-
- /**
- * Issue a request to scan all wifi available networks.
- *
- * Resolve when we get the scan result; reject when any error
- * occurs.
- *
- * Fulfill params: An array of MozWifiNetwork
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function requestWifiScan() {
- let request = wifiManager.getNetworks();
- return wrapDomRequestAsPromise(request)
- .then(event => event.target.result);
- }
-
- /**
- * Import a certificate with nickname and password.
- *
- * Resolve when we import certificate successfully; reject when any error
- * occurs.
- *
- * Fulfill params: An object of certificate information.
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function importCert(certBlob, password, nickname) {
- let request = wifiManager.importCert(certBlob, password, nickname);
- return wrapDomRequestAsPromise(request)
- .then(event => event.target.result);
- }
-
- /**
- * Delete certificate of nickname.
- *
- * Resolve when we delete certificate successfully; reject when any error
- * occurs.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function deleteCert(nickname) {
- let request = wifiManager.deleteCert(nickname);
- return wrapDomRequestAsPromise(request)
- .then(event => event.target.result);
- }
-
- /**
- * Get list of imported certificates.
- *
- * Resolve when we get certificate list successfully; reject when any error
- * occurs.
- *
- * Fulfill params: Nickname of imported certificate arranged by usage.
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function getImportedCerts() {
- let request = wifiManager.getImportedCerts();
- return wrapDomRequestAsPromise(request)
- .then(event => event.target.result);
- }
-
- /**
- * Request wifi scan and verify the scan result as well.
- *
- * Issue a wifi scan request and check if the result is expected.
- * Since the old APs may be cached and the newly added APs may be
- * still not scan-able, a couple of attempts are acceptable.
- * Resolve if we eventually get the expected scan result; reject otherwise.
- *
- * Fulfill params: The scan result, which is an array of MozWifiNetwork
- * Reject params: (none)
- *
- * @param aRetryCnt
- * The maxmimum number of attempts until we get the expected scan result.
- * @param aExpectedNetworks
- * An array of object, each of which contains at least the |ssid| property.
- *
- * @return A deferred promise.
- */
- function testWifiScanWithRetry(aRetryCnt, aExpectedNetworks) {
-
- // Check if every single ssid of each |aScanResult| exists in |aExpectedNetworks|
- // as well as the length of |aScanResult| equals to |aExpectedNetworks|.
- function isScanResultExpected(aScanResult) {
- if (aScanResult.length !== aExpectedNetworks.length) {
- return false;
- }
-
- for (let i = 0; i < aScanResult.length; i++) {
- if (-1 === getFirstIndexBySsid(aScanResult[i].ssid, aExpectedNetworks)) {
- return false;
- }
- }
- return true;
- }
-
- return requestWifiScan()
- .then(function (networks) {
- if (isScanResultExpected(networks, aExpectedNetworks)) {
- return networks;
- }
- if (aRetryCnt > 0) {
- return testWifiScanWithRetry(aRetryCnt - 1, aExpectedNetworks);
- }
- throw 'Unexpected scan result!';
- });
- }
-
- /**
- * Test wifi association.
- *
- * Associate with the given network object which is obtained by
- * MozWifiManager.getNetworks() (i.e. MozWifiNetwork).
- * Resolve when the 'connected' status change event is received.
- * Note that we might see other events like 'connecting'
- * before 'connected'. So we need to call |waitForWifiManagerEventOnce|
- * again whenever non 'connected' event is seen. Never reject.
- *
- * Fulfill params: (none)
- *
- * @param aNetwork
- * An object of MozWifiNetwork.
- *
- * @return A deferred promise.
- */
- function testAssociate(aNetwork) {
- setPasswordIfNeeded(aNetwork);
-
- let promises = [];
-
- // Register the event listerner to wait for 'connected' event first
- // to avoid racing issue.
- promises.push(waitForConnected(aNetwork));
-
- // Then we do the association.
- let request = wifiManager.associate(aNetwork);
- promises.push(wrapDomRequestAsPromise(request));
-
- return Promise.all(promises);
- }
-
- function waitForConnected(aExpectedNetwork) {
- return waitForWifiManagerEventOnce('statuschange')
- .then(function onstatuschange(event) {
- log("event.status: " + event.status);
- log("event.network.ssid: " + (event.network ? event.network.ssid : ''));
-
- if ("connected" === event.status &&
- event.network.ssid === aExpectedNetwork.ssid) {
- return; // Got expected 'connected' event from aNetwork.ssid.
- }
-
- log('Not expected "connected" statuschange event. Wait again!');
- return waitForConnected(aExpectedNetwork);
- });
- }
-
- /**
- * Set the password for associating the given network if needed.
- *
- * Set the password by looking up HOSTAPD_CONFIG_LIST. This function
- * will also set |keyManagement| properly.
- *
- * @param aNetwork
- * The MozWifiNetwork object.
- */
- function setPasswordIfNeeded(aNetwork) {
- let i = getFirstIndexBySsid(aNetwork.ssid, HOSTAPD_CONFIG_LIST);
- if (-1 === i) {
- log('unknown ssid: ' + aNetwork.ssid);
- return; // Unknown network. Assume insecure.
- }
-
- if (!aNetwork.security.length) {
- return; // No need to set password.
- }
-
- let security = aNetwork.security[0];
- if (/PSK$/.test(security)) {
- aNetwork.psk = HOSTAPD_CONFIG_LIST[i].wpa_passphrase;
- aNetwork.keyManagement = 'WPA-PSK';
- } else if (/WEP$/.test(security)) {
- aNetwork.wep = HOSTAPD_CONFIG_LIST[i].wpa_passphrase;
- aNetwork.keyManagement = 'WEP';
- }
- }
-
- /**
- * Set mozSettings values.
- *
- * Resolve if that mozSettings value is set successfully, reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aSettings
- * An object of format |{key1: value1, key2: value2, ...}|.
- * @param aAllowError [optional]
- * A boolean value. If set to true, an error response won't be treated
- * as test failure. Default: false.
- *
- * @return A deferred promise.
- */
- function setSettings(aSettings) {
- let lock = window.navigator.mozSettings.createLock();
- let request = lock.set(aSettings);
- let deferred = Promise.defer();
- lock.onsettingstransactionsuccess = function () {
- ok(true, "setSettings(" + JSON.stringify(aSettings) + ")");
- deferred.resolve();
- };
- lock.onsettingstransactionfailure = function (aEvent) {
- ok(false, "setSettings(" + JSON.stringify(aSettings) + ")");
- deferred.reject();
- throw aEvent.target.error;
- };
- return deferred.promise;
- }
-
- /**
- * Set mozSettings value with only one key.
- *
- * Resolve if that mozSettings value is set successfully, reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aKey
- * A string key.
- * @param aValue
- * An object value.
- * @param aAllowError [optional]
- * A boolean value. If set to true, an error response won't be treated
- * as test failure. Default: false.
- *
- * @return A deferred promise.
- */
- function setSettings1(aKey, aValue, aAllowError) {
- let settings = {};
- settings[aKey] = aValue;
- return setSettings(settings, aAllowError);
- }
-
- /**
- * Get mozSettings value specified by @aKey.
- *
- * Resolve if that mozSettings value is retrieved successfully, reject
- * otherwise.
- *
- * Fulfill params:
- * The corresponding mozSettings value of the key.
- * Reject params: (none)
- *
- * @param aKey
- * A string.
- * @param aAllowError [optional]
- * A boolean value. If set to true, an error response won't be treated
- * as test failure. Default: false.
- *
- * @return A deferred promise.
- */
- function getSettings(aKey, aAllowError) {
- let request =
- navigator.mozSettings.createLock().get(aKey);
- return wrapDomRequestAsPromise(request)
- .then(function resolve(aEvent) {
- ok(true, "getSettings(" + aKey + ") - success");
- return aEvent.target.result[aKey];
- }, function reject(aEvent) {
- ok(aAllowError, "getSettings(" + aKey + ") - error");
- });
- }
-
-
- /**
- * Start hostapd processes with given configuration list.
- *
- * For starting one hostapd, we need to generate a specific config file
- * then launch a hostapd process with the confg file path passed. The
- * config file is generated by two sources: one is the common
- * part (HOSTAPD_COMMON_CONFIG) and the other is from the given |aConfigList|.
- * Resolve when all the hostpads are requested to start. It is not guaranteed
- * that all the hostapds will be up and running successfully. Never reject.
- *
- * Fulfill params: (none)
- *
- * @param aConfigList
- * An array of config objects, each property in which will be
- * output to the confg file with the format: [key]=[value] in one line.
- * See http://hostap.epitest.fi/cgit/hostap/plain/hostapd/hostapd.conf
- * for more information.
- *
- * @return A deferred promise.
- */
- function startHostapds(aConfigList) {
-
- function createConfigFromCommon(aIndex) {
- // Create an copy of HOSTAPD_COMMON_CONFIG.
- let config = JSON.parse(JSON.stringify(HOSTAPD_COMMON_CONFIG));
-
- // Add user config.
- for (let key in aConfigList[aIndex]) {
- config[key] = aConfigList[aIndex][key];
- }
-
- // 'interface' is a required field but no need of being configurable
- // for a test case. So we initialize this field on our own.
- config.interface = 'AP-' + aIndex;
-
- return config;
- }
-
- function startOneHostapd(aIndex) {
- let configFileName = HOSTAPD_CONFIG_PATH + 'ap' + aIndex + '.conf';
- return writeHostapdConfFile(configFileName, createConfigFromCommon(aIndex))
- .then(() => runEmulatorShellSafe(['hostapd', '-B', configFileName]))
- .then(function (reply) {
- // It may fail at the first time due to the previous ungracefully terminated one.
- if (reply.length === 0) {
- // The hostapd starts successfully
- return;
- }
-
- if (reply[0].indexOf('bind(PF_UNIX): Address already in use') !== -1) {
- return startOneHostapd(aIndex);
- }
- });
- }
-
- return Promise.all(aConfigList.map(function(aConfig, aIndex) {
- return startOneHostapd(aIndex);
- }));
- }
-
- /**
- * Kill all the running hostapd processes.
- *
- * Use shell command 'kill -9' to kill all hostapds. Never reject.
- *
- * Fulfill params: (none)
- *
- * @return A deferred promise.
- */
- function killAllHostapd() {
- return getProcessDetail('hostapd')
- .then(function (runningHostapds) {
- let promises = runningHostapds.map(runningHostapd => {
- return runEmulatorShellSafe(['kill', '-9', runningHostapd.pid]);
- });
- return Promise.all(promises);
- });
- }
-
- /**
- * Write out the config file to the given path.
- *
- * For each key/value pair in |aConfig|,
- *
- * [key]=[value]
- *
- * will be output to one new line. Never reject.
- *
- * Fulfill params: (none)
- *
- * @param aFilePath
- * The file path that we desire the config file to be located.
- *
- * @param aConfig
- * The config object.
- *
- * @return A deferred promise.
- */
- function writeHostapdConfFile(aFilePath, aConfig) {
- let content = '';
- for (let key in aConfig) {
- if (aConfig.hasOwnProperty(key)) {
- content += (key + '=' + aConfig[key] + '\n');
- }
- }
- return writeFile(aFilePath, content);
- }
-
- /**
- * Write file to the given path filled with given content.
- *
- * For now it is implemented by shell command 'echo'. Also, if the
- * content contains whitespace, we need to quote the content to
- * avoid error. Never reject.
- *
- * Fulfill params: (none)
- *
- * @param aFilePath
- * The file path that we desire the file to be located.
- *
- * @param aContent
- * The content as string which should be written to the file.
- *
- * @return A deferred promise.
- */
- function writeFile(aFilePath, aContent) {
- const CONTENT_MAX_LENGTH = 900;
- var commands = [];
- for (var i = 0; i < aContent.length; i += CONTENT_MAX_LENGTH) {
- var content = aContent.substr(i, CONTENT_MAX_LENGTH);
- if (-1 === content.indexOf(' ')) {
- content = '"' + content + '"';
- }
- commands.push(['echo', '-n', content, i === 0 ? '>' : '>>', aFilePath]);
- }
-
- let chain = Promise.resolve();
- commands.forEach(function (command) {
- chain = chain.then(() => runEmulatorShellSafe(command));
- });
- return chain;
- }
-
- /**
- * Check if a init service is running or not.
- *
- * Check the android property 'init.svc.[aServiceName]' to determine if
- * a init service is running. Reject if the propery is neither 'running'
- * nor 'stopped'.
- *
- * Fulfill params:
- * result -- |true| if the init service is running; |false| otherwise.
- * Reject params: (none)
- *
- * @param aServiceName
- * The init service name.
- *
- * @return A deferred promise.
- */
- function isInitServiceRunning(aServiceName) {
- return runEmulatorShellSafe(['getprop', 'init.svc.' + aServiceName])
- .then(function (result) {
- if ('running' !== result[0] && 'stopped' !== result[0]) {
- throw 'Init service running state should be "running" or "stopped".';
- }
- return 'running' === result[0];
- });
- }
-
- /**
- * Wait for timeout.
- *
- * Resolve when the given duration elapsed. Never reject.
- *
- * Fulfill params: (none)
- *
- * @param aTimeoutMs
- * The duration after which the timeout event should occurs.
- *
- * @return A deferred promise.
- */
- function waitForTimeout(aTimeoutMs) {
- let deferred = Promise.defer();
-
- setTimeout(function() {
- deferred.resolve();
- }, aTimeoutMs);
-
- return deferred.promise;
- }
-
- /**
- * Start or stop an init service.
- *
- * Use shell command 'start'/'stop' to start/stop an init service.
- * The running state will also be checked after we start/stop the service.
- * Resolve if the service is successfully started/stopped; Reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aServiceName
- * The name of the service we want to start/stop.
- *
- * @param aStart
- * |true| for starting the init service. |false| for stopping.
- *
- * @return A deferred promise.
- */
- function startStopInitService(aServiceName, aStart) {
- let retryCnt = 5;
-
- return runEmulatorShellSafe([aStart ? 'start' : 'stop', aServiceName])
- .then(() => isInitServiceRunning(aServiceName))
- .then(function onIsServiceRunningResolved(aIsRunning) {
- if (aStart === aIsRunning) {
- return;
- }
-
- if (retryCnt-- > 0) {
- log('Failed to ' + (aStart ? 'start ' : 'stop ') + aServiceName +
- '. Retry: ' + retryCnt);
-
- return waitForTimeout(500)
- .then(() => isInitServiceRunning(aServiceName))
- .then(onIsServiceRunningResolved);
- }
-
- throw 'Failed to ' + (aStart ? 'start' : 'stop') + ' ' + aServiceName;
- });
- }
-
- /**
- * Start the stock hostapd.
- *
- * Since the stock hostapd is an init service, use |startStopInitService| to
- * start it. Note that we might fail to start the stock hostapd at the first time
- * for unknown reason so give it the second chance to start again.
- * Resolve when we are eventually successful to start the stock hostapd; Reject
- * otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function startStockHostapd() {
- return startStopInitService(STOCK_HOSTAPD_NAME, true)
- .then(null, function onreject() {
- log('Failed to restart goldfish-hostapd at the first time. Try again!');
- return startStopInitService((STOCK_HOSTAPD_NAME), true);
- });
- }
-
- /**
- * Stop the stock hostapd.
- *
- * Since the stock hostapd is an init service, use |startStopInitService| to
- * stop it.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function stopStockHostapd() {
- return startStopInitService(STOCK_HOSTAPD_NAME, false);
- }
-
- /**
- * Get the index of the first matching entry by |ssid|.
- *
- * Find the index of the first entry of |aArray| which property |ssid|
- * is same as |aSsid|.
- *
- * @param aSsid
- * The ssid that we want to match.
- * @param aArray
- * An array of objects, each of which should have the property |ssid|.
- *
- * @return The 0-based index of first matching entry if found; -1 otherwise.
- */
- function getFirstIndexBySsid(aSsid, aArray) {
- for (let i = 0; i < aArray.length; i++) {
- if (aArray[i].ssid === aSsid) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Count the number of running process and verify if the count is expected.
- *
- * Return a promise that resolves when the process has expected number
- * of running instances and rejects otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aOrigWifiEnabled
- * Boolean which indicates wifi was originally enabled.
- *
- * @return A deferred promise.
- */
- function verifyNumOfProcesses(aProcessName, aExpectedNum) {
- return getProcessDetail(aProcessName)
- .then(function (detail) {
- if (detail.length === aExpectedNum) {
- return;
- }
- throw 'Unexpected number of running processes:' + aProcessName +
- ', expected: ' + aExpectedNum + ', actual: ' + detail.length;
- });
- }
-
- /**
- * Execute 'netcfg' shell and parse the result.
- *
- * Resolve when the executing is successful and reject otherwise.
- *
- * Fulfill params: Command result object, each key of which is the interface
- * name and value is { ip(string), prefix(string) }.
- * Reject params: String that indicates the reason of rejection.
- *
- * @return A deferred promise.
- */
- function exeAndParseNetcfg() {
- return runEmulatorShellSafe(['netcfg'])
- .then(function (aLines) {
- // Sample output:
- //
- // lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
- // eth0 UP 10.0.2.15/24 0x00001043 52:54:00:12:34:56
- // rmnet1 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:58
- // rmnet2 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:59
- // rmnet3 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:5a
- // wlan0 UP 192.168.1.1/24 0x00001043 52:54:00:12:34:5b
- // sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
- // rmnet0 UP 10.0.2.100/24 0x00001043 52:54:00:12:34:57
- //
- let netcfgResult = {};
- aLines.forEach(function (aLine) {
- let tokens = aLine.split(/\s+/);
- if (tokens.length < 5) {
- return;
- }
- let ifname = tokens[0];
- let [ip, prefix] = tokens[2].split('/');
- netcfgResult[ifname] = { ip: ip, prefix: prefix };
- });
- log("netcfg result:" + JSON.stringify(netcfgResult));
-
- return netcfgResult;
- });
- }
-
- /**
- * Execute 'ip route' and parse the result.
- *
- * Resolve when the executing is successful and reject otherwise.
- *
- * Fulfill params: Command result object, each key of which is the interface
- * name and value is { src(string), gateway(string),
- * default(boolean) }.
- * Reject params: String that indicates the reason of rejection.
- *
- * @return A deferred promise.
- */
- function exeAndParseIpRoute() {
- return runEmulatorShellSafe(['ip', 'route'])
- .then(function (aLines) {
- // Sample output:
- //
- // 10.0.2.4 via 10.0.2.2 dev rmnet0
- // 10.0.2.3 via 10.0.2.2 dev rmnet0
- // 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.1
- // 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
- // 10.0.2.0/24 dev rmnet0 proto kernel scope link src 10.0.2.100
- // default via 10.0.2.2 dev rmnet0
- // default via 10.0.2.2 dev eth0 metric 2
- //
-
- let ipRouteResult = {};
-
- // Parse source ip for each interface.
- aLines.forEach(function (aLine) {
- let tokens = aLine.trim().split(/\s+/);
- let srcIndex = tokens.indexOf('src');
- if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
- return;
- }
- let ifname = tokens[2];
- let src = tokens[srcIndex + 1];
- ipRouteResult[ifname] = { src: src, default: false, gateway: null };
- });
-
- // Parse default interfaces.
- aLines.forEach(function (aLine) {
- let tokens = aLine.split(/\s+/);
- if (tokens.length < 2) {
- return;
- }
- if ('default' === tokens[0]) {
- let ifnameIndex = tokens.indexOf('dev');
- if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
- return;
- }
- let ifname = tokens[ifnameIndex + 1];
- if (!ipRouteResult[ifname]) {
- return;
- }
- ipRouteResult[ifname].default = true;
- let gwIndex = tokens.indexOf('via');
- if (gwIndex < 0 || gwIndex + 1 >= tokens.length) {
- return;
- }
- ipRouteResult[ifname].gateway = tokens[gwIndex + 1];
- return;
- }
- });
- log("ip route result:" + JSON.stringify(ipRouteResult));
-
- return ipRouteResult;
- });
- }
-
- /**
- * Verify everything about routing when the wifi tethering is either on or off.
- *
- * We use two unix commands to verify the routing: 'netcfg' and 'ip route'.
- * For now the following two things will be checked:
- * 1) The default route interface should be 'rmnet0'.
- * 2) wlan0 is up and its ip is set to a private subnet.
- *
- * We also verify iptables output as netd's NatController will execute
- * $ iptables -t nat -A POSTROUTING -o rmnet0 -j MASQUERADE
- *
- * Resolve when the verification is successful and reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: String that indicates the reason of rejection.
- *
- * @return A deferred promise.
- */
- function verifyTetheringRouting(aEnabled) {
- let netcfgResult;
- let ipRouteResult;
-
- // Find MASQUERADE in POSTROUTING section. 'MASQUERADE' should be found
- // when tethering is enabled. 'MASQUERADE' shouldn't be found when tethering
- // is disabled.
- function verifyIptables() {
- let MASQUERADE_checkSection = 'POSTROUTING';
- if (sdkVersion > 15) {
- // Check 'natctrl_nat_POSTROUTING' section after ICS.
- MASQUERADE_checkSection = 'natctrl_nat_POSTROUTING';
- }
-
- return runEmulatorShellSafe(['iptables', '-t', 'nat', '-L', MASQUERADE_checkSection])
- .then(function(aLines) {
- // $ iptables -t nat -L POSTROUTING
- //
- // Sample output (tethering on):
- //
- // Chain POSTROUTING (policy ACCEPT)
- // target prot opt source destination
- // MASQUERADE all -- anywhere anywhere
- //
- let found = (function find_MASQUERADE() {
- // Skip first two lines.
- for (let i = 2; i < aLines.length; i++) {
- if (-1 !== aLines[i].indexOf('MASQUERADE')) {
- return true;
- }
- }
- return false;
- })();
-
- if ((aEnabled && !found) || (!aEnabled && found)) {
- throw 'MASQUERADE' + (found ? '' : ' not') + ' found while tethering is ' +
- (aEnabled ? 'enabled' : 'disabled');
- }
- });
- }
-
- function verifyDefaultRouteAndIp(aExpectedWifiTetheringIp) {
- if (aEnabled) {
- isOrThrow(ipRouteResult['rmnet0'].src, netcfgResult['rmnet0'].ip, 'rmnet0.ip');
- isOrThrow(ipRouteResult['rmnet0'].default, true, 'rmnet0.default');
-
- isOrThrow(ipRouteResult['wlan0'].src, netcfgResult['wlan0'].ip, 'wlan0.ip');
- isOrThrow(ipRouteResult['wlan0'].src, aExpectedWifiTetheringIp, 'expected ip');
- isOrThrow(ipRouteResult['wlan0'].default, false, 'wlan0.default');
- }
- }
-
- return verifyIptables()
- .then(exeAndParseNetcfg)
- .then((aResult) => { netcfgResult = aResult; })
- .then(exeAndParseIpRoute)
- .then((aResult) => { ipRouteResult = aResult; })
- .then(() => getSettings(SETTINGS_TETHERING_WIFI_IP))
- .then(ip => verifyDefaultRouteAndIp(ip));
- }
-
- /**
- * Clean up all the allocated resources and running services for the test.
- *
- * After the test no matter success or failure, we should
- * 1) Restore to the wifi original state (enabled or disabled)
- * 2) Wait until all pending emulator shell commands are done.
- *
- * |finsih| will be called in the end.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @return A deferred promise.
- */
- function cleanUp() {
- waitFor(function() {
- return ensureWifiEnabled(true)
- .then(forgetAllKnownNetworks)
- .then(() => ensureWifiEnabled(wifiOrigEnabled))
- .then(finish);
- }, function() {
- return pendingEmulatorShellCount === 0;
- });
- }
-
- /**
- * Init the test environment.
- *
- * Mainly add the required permissions and initialize the wifiManager
- * and the orignal state of wifi. Reject if failing to create
- * window.navigator.mozWifiManager; resolve if all is well.
- *
- * |finsih| will be called in the end.
- *
- * Fulfill params: (none)
- * Reject params: The reject reason.
- *
- * @return A deferred promise.
- */
- function initTestEnvironment() {
- return addRequiredPermissions()
- .then(function() {
- wifiManager = window.navigator.mozWifiManager;
- if (!wifiManager) {
- throw 'window.navigator.mozWifiManager is NULL';
- }
- wifiOrigEnabled = wifiManager.enabled;
- })
- .then(() => runEmulatorShellSafe(['getprop', 'ro.build.version.sdk']))
- .then(aLines => {
- sdkVersion = parseInt(aLines[0]);
- });
- }
-
- //---------------------------------------------------
- // Public test suite functions
- //---------------------------------------------------
- suite.getWifiManager = (() => wifiManager);
- suite.ensureWifiEnabled = ensureWifiEnabled;
- suite.requestWifiEnabled = requestWifiEnabled;
- suite.startHostapds = startHostapds;
- suite.getProcessDetail = getProcessDetail;
- suite.killAllHostapd = killAllHostapd;
- suite.wrapDomRequestAsPromise = wrapDomRequestAsPromise;
- suite.waitForWifiManagerEventOnce = waitForWifiManagerEventOnce;
- suite.verifyNumOfProcesses = verifyNumOfProcesses;
- suite.testWifiScanWithRetry = testWifiScanWithRetry;
- suite.getFirstIndexBySsid = getFirstIndexBySsid;
- suite.testAssociate = testAssociate;
- suite.getKnownNetworks = getKnownNetworks;
- suite.setStaticIpMode = setStaticIpMode;
- suite.requestWifiScan = requestWifiScan;
- suite.waitForConnected = waitForConnected;
- suite.forgetNetwork = forgetNetwork;
- suite.waitForTimeout = waitForTimeout;
- suite.waitForRilDataConnected = waitForRilDataConnected;
- suite.requestTetheringEnabled = requestTetheringEnabled;
- suite.importCert = importCert;
- suite.getImportedCerts = getImportedCerts;
- suite.deleteCert = deleteCert;
- suite.writeFile = writeFile;
- suite.exeAndParseNetcfg = exeAndParseNetcfg;
- suite.exeAndParseIpRoute = exeAndParseIpRoute;
-
- /**
- * Common test routine.
- *
- * Start a test with the given test case chain. The test environment will be
- * settled down before the test. After the test, all the affected things will
- * be restored.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aTestCaseChain
- * The test case entry point, which can be a function or a promise.
- *
- * @return A deferred promise.
- */
- suite.doTest = function(aTestCaseChain) {
- return initTestEnvironment()
- .then(aTestCaseChain)
- .then(function onresolve() {
- cleanUp();
- }, function onreject(aReason) {
- ok(false, 'Promise rejects during test' + (aReason ? '(' + aReason + ')' : ''));
- cleanUp();
- });
- };
-
- /**
- * Common test routine without the presence of stock hostapd.
- *
- * Same as doTest except stopping the stock hostapd before test
- * and restarting it after test.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aTestCaseChain
- * The test case entry point, which can be a function or a promise.
- *
- * @return A deferred promise.
- */
- suite.doTestWithoutStockAp = function(aTestCaseChain) {
- return suite.doTest(function() {
- return stopStockHostapd()
- .then(aTestCaseChain)
- .then(startStockHostapd);
- });
- };
-
- /**
- * The common test routine for wifi tethering.
- *
- * Similar as doTest except that it will set 'ril.data.enabled' to true
- * before testing and restore it afterward. It will also verify 'ril.data.enabled'
- * and 'tethering.wifi.enabled' to be false in the beginning. Note that this routine
- * will NOT change the state of 'tethering.wifi.enabled' so the user should enable
- * than disable on his/her own. This routine will only check if tethering is turned
- * off after testing.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aTestCaseChain
- * The test case entry point, which can be a function or a promise.
- *
- * @return A deferred promise.
- */
- suite.doTestTethering = function(aTestCaseChain) {
-
- function verifyInitialState() {
- return getSettings(SETTINGS_RIL_DATA_ENABLED)
- .then(enabled => isOrThrow(enabled, false, SETTINGS_RIL_DATA_ENABLED))
- .then(() => getSettings(SETTINGS_TETHERING_WIFI_ENABLED))
- .then(enabled => isOrThrow(enabled, false, SETTINGS_TETHERING_WIFI_ENABLED));
- }
-
- function initTetheringTestEnvironment() {
- // Enable ril data.
- return Promise.all([waitForRilDataConnected(true),
- setSettings1(SETTINGS_RIL_DATA_ENABLED, true)])
- .then(setSettings1(SETTINGS_TETHERING_WIFI_SECURITY, 'open'));
- }
-
- function restoreToInitialState() {
- return setSettings1(SETTINGS_RIL_DATA_ENABLED, false)
- .then(() => getSettings(SETTINGS_TETHERING_WIFI_ENABLED))
- .then(enabled => is(enabled, false, 'Tethering should be turned off.'));
- }
-
- return suite.doTest(function() {
- return verifyInitialState()
- .then(initTetheringTestEnvironment)
- // Since stock hostapd is not reliable after ICS, we just
- // turn off potential stock hostapd during testing to avoid
- // interference.
- .then(stopStockHostapd)
- .then(aTestCaseChain)
- .then(startStockHostapd)
- .then(restoreToInitialState, function onreject(aReason) {
- return restoreToInitialState()
- .then(() => { throw aReason; }); // Re-throw the orignal reject reason.
- });
- });
- };
-
- /**
- * Run test with imported certificate.
- *
- * Certificate will be imported and confirmed before running test, and be
- * deleted after running test.
- *
- * Fulfill params: (none)
- *
- * @param certBlob
- * Certificate content as Blob.
- * @param password
- * Password for importing certificate, only used for importing PKCS#12.
- * @param nickanem
- * Nickname for imported certificate.
- * @param usage
- * Expected usage of imported certificate.
- * @param aTestCaseChain
- * The test case entry point, which can be a function or a promise.
- *
- * @return A deferred promise.
- */
- suite.doTestWithCertificate = function(certBlob, password, nickname, usage, aTestCaseChain) {
- return suite.doTestWithoutStockAp(function() {
- return ensureWifiEnabled(true)
- // Import test certificate.
- .then(() => importCert(certBlob, password, nickname))
- .then(function(info) {
- // Check import result.
- is(info.nickname, nickname, "Imported nickname");
- for (let i = 0; i < usage.length; i++) {
- isnot(info.usage.indexOf(usage[i]), -1, "Usage " + usage[i]);
- }
- })
- // Get imported certificate list.
- .then(getImportedCerts)
- // Check if certificate exists in imported certificate list.
- .then(function(list) {
- for (let i = 0; i < usage.length; i++) {
- isnot(list[usage[i]].indexOf(nickname), -1,
- "Certificate \"" + nickname + "\" of usage " + usage[i] + " is imported");
- }
- })
- // Run test case.
- .then(aTestCaseChain)
- // Delete imported certificates.
- .then(() => deleteCert(nickname))
- // Check if certificate doesn't exist in imported certificate list.
- .then(getImportedCerts)
- .then(function(list) {
- for (let i = 0; i < usage.length; i++) {
- is(list[usage[i]].indexOf(nickname), -1, "Certificate is deleted");
- }
- })
- });
- };
-
- return suite;
-})();
diff --git a/dom/wifi/test/marionette/manifest.ini b/dom/wifi/test/marionette/manifest.ini
deleted file mode 100644
index 5d719e4b6..000000000
--- a/dom/wifi/test/marionette/manifest.ini
+++ /dev/null
@@ -1,22 +0,0 @@
-[DEFAULT]
-run-if = buildapp == 'b2g'
-
-[test_wifi_enable.js]
-[test_wifi_scan.js]
-[test_wifi_associate.js]
-[test_wifi_associate_wo_connect.js]
-[test_wifi_auto_connect.js]
-[test_wifi_static_ip.js]
-[test_wifi_tethering_wifi_disabled.js]
-[test_wifi_tethering_wifi_inactive.js]
-[test_wifi_tethering_wifi_active.js]
-[test_wifi_manage_server_certificate.js]
-[test_wifi_manage_user_certificate.js]
-[test_wifi_manage_pkcs12_certificate.js]
-[test_wifi_associate_WPA_EAP_PEAP.js]
-skip-if = android_version < '16' # EAP test not working before KK.
-[test_wifi_associate_WPA_EAP_TTLS.js]
-skip-if = android_version < '16'
-[test_wifi_associate_WPA_EAP_TLS.js]
-skip-if = android_version < '16'
-[test_wifi_enable_api.js]
diff --git a/dom/wifi/test/marionette/test_wifi_associate.js b/dom/wifi/test/marionette/test_wifi_associate.js
deleted file mode 100644
index 0c00c583b..000000000
--- a/dom/wifi/test/marionette/test_wifi_associate.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const SCAN_RETRY_CNT = 5;
-
-/**
- * Convert the given MozWifiNetwork object array to testAssociate chain.
- *
- * @param aNetworks
- * An array of MozWifiNetwork which we want to convert.
- *
- * @return A promise chain which "then"s testAssociate accordingly.
- */
-function convertToTestAssociateChain(aNetworks) {
- let chain = Promise.resolve();
-
- aNetworks.forEach(function (aNetwork) {
- chain = chain.then(() => gTestSuite.testAssociate(aNetwork));
- });
-
- return chain;
-}
-
-gTestSuite.doTestWithoutStockAp(function() {
- return gTestSuite.ensureWifiEnabled(true)
- .then(() => gTestSuite.startHostapds(HOSTAPD_CONFIG_LIST))
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', HOSTAPD_CONFIG_LIST.length))
- .then(() => gTestSuite.testWifiScanWithRetry(SCAN_RETRY_CNT, HOSTAPD_CONFIG_LIST))
- .then(networks => convertToTestAssociateChain(networks))
- .then(gTestSuite.killAllHostapd)
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', 0));
-});
diff --git a/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_PEAP.js b/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_PEAP.js
deleted file mode 100644
index ce53da2d7..000000000
--- a/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_PEAP.js
+++ /dev/null
@@ -1,623 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const SCAN_RETRY_CNT = 5;
-
-const EAP_USERNAME = 'username';
-const EAP_PASSWORD = 'password';
-
-const SERVER_EAP_USER_CONF = {
- path: HOSTAPD_CONFIG_PATH + 'hostapd.eap_user',
- content: '* PEAP,TTLS,TLS\n' +
- '"' + EAP_USERNAME + '" MSCHAPV2,TTLS-MSCHAPV2 "' + EAP_PASSWORD + '" [2]\n'
-};
-const CA_CERT = {
- path: HOSTAPD_CONFIG_PATH + 'ca.pem',
- content: '-----BEGIN CERTIFICATE-----\n' +
- 'MIIDsTCCApmgAwIBAgIJAKxTf+8X8qngMA0GCSqGSIb3DQEBCwUAMG4xCzAJBgNV\n' +
- 'BAYTAlRXMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhjaHVja2xlZTER\n' +
- 'MA8GA1UEAwwIY2h1Y2tsZWUxJDAiBgkqhkiG9w0BCQEWFWNodWNrbGkwNzA2QGdt\n' +
- 'YWlsLmNvbTAgFw0xNDEyMjQxMTI4NTBaGA8yMjg4MTAwNzExMjg1MFowbjELMAkG\n' +
- 'A1UEBhMCVFcxEzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAoMCGNodWNrbGVl\n' +
- 'MREwDwYDVQQDDAhjaHVja2xlZTEkMCIGCSqGSIb3DQEJARYVY2h1Y2tsaTA3MDZA\n' +
- 'Z21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo3c2yFxY\n' +
- 'o6gGg0I83jy00ME+MAfzCd+4ShL45ZLqysQP93jRBfPzU9ZuZ29ysVwgWIdqkZao\n' +
- 'XTuV/NAW2GMGd8W1jQJ3J81fjb9wvhlny3rrACwvUn1N1S1BnM+BAAiDLGxEmvAQ\n' +
- 'onp2aaa6HsHsYS8ONX+d2Qh4LEA4vupeSGAqJychCZv/l+aq/ErFZhFYB3CPUQEt\n' +
- 'cClO24ucsIYP95lA0zhscnmAj06qplFD4Bv6IVrdDqujy1zNwCQwsJq/8OQdaTN/\n' +
- 'h3y9pWvNKMBMM2niOUAjtuNpqsSK/lTS1WAT3PdtVECX9fYBi0Bg+HM92xs/6gt6\n' +
- 'kh9jPV8keXHvSwIDAQABo1AwTjAdBgNVHQ4EFgQU7hBqhuG04xeCzrQ3ngx18ZJ3\n' +
- 'lUswHwYDVR0jBBgwFoAU7hBqhuG04xeCzrQ3ngx18ZJ3lUswDAYDVR0TBAUwAwEB\n' +
- '/zANBgkqhkiG9w0BAQsFAAOCAQEAFYX2iy680GAnBTttk0gyX6gk+8pYr3D22k/G\n' +
- '6rvcjefzS7ELQPRKr6mfmwXq3mMf/4jiS2zI5zmXsestPYzHYxf2viQ6t7vr9XiJ\n' +
- '3WfFjNw4ERlRisAvg0aqqTNNQq5v2VME4sdFZagy217f73C7azwCHl0bqOLH05rl\n' +
- '8RubOxiHEj7ZybJqnRciK/bht4D+rZkwf4bBBmoloqH7xT0+rFQclpYXDGGjNUQB\n' +
- 'LcHLF10xcr7g3ZVVu82fe6+d85gIGOIMR9+TKhdw6gO3CNcnDAj6gxksghgtcxmh\n' +
- 'OzOggCn7nlIwImtsg2sZkpWB4lEi9hdv4lkNuyFjOL3bnuc+NA==\n' +
- '-----END CERTIFICATE-----\n'
-};
-
-const SERVER_CERT = {
- path: HOSTAPD_CONFIG_PATH + 'server.pem',
- content: '-----BEGIN CERTIFICATE-----\n' +
- 'MIID1DCCArygAwIBAgIBADANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJUVzET\n' +
- 'MBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UECgwIY2h1Y2tsZWUxETAPBgNVBAMM\n' +
- 'CGNodWNrbGVlMSQwIgYJKoZIhvcNAQkBFhVjaHVja2xpMDcwNkBnbWFpbC5jb20w\n' +
- 'IBcNMTQxMjI0MTEyOTQ5WhgPMjI4ODEwMDcxMTI5NDlaMG4xCzAJBgNVBAYTAlRX\n' +
- 'MRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhjaHVja2xlZTERMA8GA1UE\n' +
- 'AwwIY2h1Y2tsZWUxJDAiBgkqhkiG9w0BCQEWFWNodWNrbGkwNzA2QGdtYWlsLmNv\n' +
- 'bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMdhQmKilTJbWZRxTiSV\n' +
- 'rqIU+LYW1RKghx5o+0JpNRJVLuz5kBMaNskbbfUSNuHbEq0QA9BDKAZWIc4LSotk\n' +
- 'lCo8TbcO9CJvJPQGGjGdHcohWX5vy6BE/OVE46CUteMFyZF6F8R2fNUww08iR/u1\n' +
- 'YZebL5pWO1j43sPpAzEy6Tij2ACPt6EZcFaZG3SF2mVJWkCQnBqrojP65WUvZQqp\n' +
- 'seUhW2YAS8Nu0Yrohgxz6VYk+cNDuDZVGs6qWRStZzJfYrfc76DtkHof5B14M+xp\n' +
- 'XJaBLxN+whvnYkDTfinaCxnW1O7eXUltr87fLc5zmeBkgwaiaQuIdcfZm7vDUiz8\n' +
- 'vnUCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH\n' +
- 'ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFKK4f9/YavTHOfEiAB83Deac\n' +
- '6gT5MB8GA1UdIwQYMBaAFO4QaobhtOMXgs60N54MdfGSd5VLMA0GCSqGSIb3DQEB\n' +
- 'CwUAA4IBAQBWnO9o9KSJIqjoz5Nwll63ULOdcvgGdOeJIw1fcKQ817Rsp+TVcjcH\n' +
- 'IrIADsT/QZGXRO/l6p1750e2iFtJEo1hsRaxtA1wWn2I9HO3+av2spQhr3jpYGPf\n' +
- 'zpsMTp4RNYV7Q8+q1kZIz9PY4V1T0p6lveK8+fUj2hSLnxSj0QiGSJJtnEC3w4Rv\n' +
- 'C9T6oUwIeToULmi+8FXQFdEqwKRU98DPq3eLzN28ZxUgoPE1C8+42D2UW8uyp/Gm\n' +
- 'tGOa/k7nzkCdVqZI7lX7f0AjEvQgjtAMQ/k7Mhxx7TzW2HO+1YPMoKji6Z4WkNwt\n' +
- 'JEj9ZUBSNt8B26UksJMBDkcvSegF3a7o\n' +
- '-----END CERTIFICATE-----\n'
-};
-
-const SERVER_KEY = {
- path: HOSTAPD_CONFIG_PATH + 'server.key',
- content: '-----BEGIN RSA PRIVATE KEY-----\n' +
- 'MIIEpAIBAAKCAQEAx2FCYqKVMltZlHFOJJWuohT4thbVEqCHHmj7Qmk1ElUu7PmQ\n' +
- 'Exo2yRtt9RI24dsSrRAD0EMoBlYhzgtKi2SUKjxNtw70Im8k9AYaMZ0dyiFZfm/L\n' +
- 'oET85UTjoJS14wXJkXoXxHZ81TDDTyJH+7Vhl5svmlY7WPjew+kDMTLpOKPYAI+3\n' +
- 'oRlwVpkbdIXaZUlaQJCcGquiM/rlZS9lCqmx5SFbZgBLw27RiuiGDHPpViT5w0O4\n' +
- 'NlUazqpZFK1nMl9it9zvoO2Qeh/kHXgz7GlcloEvE37CG+diQNN+KdoLGdbU7t5d\n' +
- 'SW2vzt8tznOZ4GSDBqJpC4h1x9mbu8NSLPy+dQIDAQABAoIBAASG4Mr8hgaurEoC\n' +
- 'iJOsElr7vunjetMBcg/uskW/vcS8ymP3Bp5oafYG+WgnEbfvEW18f5mq7K24JuxW\n' +
- 'tUqU7ghHdjxByqk9fMlNmiqmNpbwSufkAeuRpWxPNBvhRH/zEbCL5R5A0nTEtqqF\n' +
- 'TL0aUSzwCRSoAJD0lZo9ICVt0n3GsDyM9rqQg/uZmh1qsRdwPsRuYORND9g48rKq\n' +
- '6WN9leskSxhhsYE2D9ocOFd9bNt8Zxejh9ppVSnG/KsIdt18iBzcabatgAQ046fb\n' +
- 'Z3vprcZJLg93Sg2gSuVqlSTs3M2W8VQnm22/EBMb1y0M48MSRCgnbPLG/CcCLLfF\n' +
- 'LwxCOgECgYEA/eYt67xyJ6JeAdxdwOZuT1WWGbFpLiG9+2OgiHumyRQ5969XMTWo\n' +
- 'fIhMKchDdjoy9RR236\/\/EFCs7UEyB7+a7ODRzNiK2zCD8Smjp+21fUPSthEeQesk\n' +
- 'eiMYICIu5Ay35x9sxIX+XOUVvRhPOGcD29GVeRnKh1inTHOz2dje8LkCgYEAyQeY\n' +
- 'STi9jjCEcHkM1E/UeDiLfHHepLXi8wS41JNRHl5Jacp7XB5djAjKu/jf367/VpFy\n' +
- 'GDDMetE7n8eWkrnAvovxOwZ000YDMtL1sUYSjL+XtBS5s6VY1p4qaSAY9nUUGrJh\n' +
- 'JvtvsuI7SKTtL+60vjBOH7zDnvOdBgAp0utLhZ0CgYEAuLzzqrPKB8afShFSchn4\n' +
- 'J2dpuLYahsNsXW7HDqeR2nsKFosRETAusLXnXPtnAq4kB6jlOarwFqnsuRCX24Vx\n' +
- 'r2uBm9/vYL7zMdUPTA+s30ErHuhjsKjsOKYyVqcooSwT32pBFNk+E89nutfmRG7I\n' +
- 'IvhjHuNCNqqtx/Xj5d1jkZkCgYBQicppC2Jl5OoqZVTOem0U/RJk+PnJ41TZJ7sk\n' +
- '7yBAmmWvDH\/\/l+rCf4M5a6vFYcbKV9rt9h711X2dtciNX/3oWQh8LUoAmrwNUJc+\n' +
- 'PmSQHvIYI3WCk2vUD+nN1B4sHxu+1lg11eYaNKiroeeknG2tBI1ICcgVlmQCU25u\n' +
- 'IfZPwQKBgQCdO6QHhPLtcHUDNFA6FQ1jKL1iEd7G0JLVRz4Xkpkn1Vrr5MD6JFDa\n' +
- '5ccabADyl0lpFqDIVJQIzLku2hOD2i9aBNCY0pL391HeOS7CkZX+TdOY1tquoBq5\n' +
- 'MnmixZjDCVd2VcrVyTA6ntOBoharKFW0rH1PqU+qu7dZF7CBPbAdEw==\n' +
- '-----END RSA PRIVATE KEY-----\n'
-};
-
-const WPA_EAP_AP_LIST = [
- {
- ssid: 'WPA-EAP-PEAP',
- ieee8021x: 1,
- eapol_version: 1,
- eap_server: 1,
- eapol_key_index_workaround: 0,
- eap_user_file: SERVER_EAP_USER_CONF.path,
- ca_cert: CA_CERT.path,
- server_cert: SERVER_CERT.path,
- private_key: SERVER_KEY.path,
- wpa: 3,
- wpa_key_mgmt: 'WPA-EAP'
- }
-];
-
-const CLIENT_PKCS12_CERT = {
- nickname: 'client',
- password: 'password',
- usage: ['UserCert', 'ServerCert'],
- content: [0x30, 0x82, 0x0E, 0x01, 0x02, 0x01, 0x03, 0x30,
- 0x82, 0x0D, 0xC7, 0x06, 0x09, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82,
- 0x0D, 0xB8, 0x04, 0x82, 0x0D, 0xB4, 0x30, 0x82,
- 0x0D, 0xB0, 0x30, 0x82, 0x08, 0x67, 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07,
- 0x06, 0xA0, 0x82, 0x08, 0x58, 0x30, 0x82, 0x08,
- 0x54, 0x02, 0x01, 0x00, 0x30, 0x82, 0x08, 0x4D,
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x07, 0x01, 0x30, 0x1C, 0x06, 0x0A, 0x2A,
- 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01,
- 0x06, 0x30, 0x0E, 0x04, 0x08, 0x67, 0x7A, 0xF3,
- 0x61, 0xBE, 0xE0, 0x51, 0xC1, 0x02, 0x02, 0x08,
- 0x00, 0x80, 0x82, 0x08, 0x20, 0xFC, 0x6A, 0x79,
- 0xA1, 0x6C, 0xAF, 0xBE, 0xEE, 0x62, 0x45, 0x33,
- 0xB8, 0x48, 0xE1, 0x68, 0xA1, 0x15, 0x11, 0x4B,
- 0x95, 0xCB, 0x77, 0xC0, 0x5D, 0xA2, 0xCB, 0xDB,
- 0xD1, 0x83, 0x74, 0x60, 0xD7, 0xEC, 0x42, 0xA6,
- 0x3A, 0x23, 0xF7, 0x85, 0xEB, 0xC1, 0xFE, 0x6A,
- 0x57, 0x8E, 0xC1, 0x44, 0xF3, 0x1F, 0xFE, 0xB8,
- 0x2D, 0x8C, 0x4D, 0xC9, 0x5B, 0xAE, 0x21, 0x2E,
- 0x4C, 0x1A, 0xEB, 0x84, 0x09, 0xF3, 0x40, 0x92,
- 0x39, 0x7F, 0x56, 0x02, 0x46, 0x61, 0x16, 0xDE,
- 0x5C, 0x48, 0xB6, 0x0C, 0x1D, 0xD3, 0x5F, 0x10,
- 0x9A, 0x39, 0xB8, 0x66, 0x31, 0xFC, 0x39, 0x71,
- 0x87, 0x23, 0x46, 0x9D, 0xE8, 0x3C, 0x2B, 0xA1,
- 0x39, 0x8A, 0xD3, 0xFF, 0xD9, 0x43, 0xB6, 0x61,
- 0xC6, 0x67, 0x70, 0x40, 0xBD, 0xFE, 0xD3, 0xC1,
- 0x68, 0xF5, 0xF7, 0xC8, 0x89, 0xD8, 0x17, 0xC5,
- 0xE8, 0x3D, 0x29, 0xD5, 0x91, 0xDF, 0x1F, 0x56,
- 0x74, 0x5A, 0xC4, 0xA8, 0x14, 0xBA, 0xD4, 0xFA,
- 0x13, 0x49, 0x2A, 0x9F, 0x63, 0xF1, 0xB2, 0x45,
- 0xF1, 0xF0, 0x2A, 0xDD, 0x75, 0x66, 0x8A, 0xF7,
- 0xAB, 0x73, 0x86, 0x26, 0x9D, 0x1F, 0x07, 0xAD,
- 0xD3, 0xFE, 0xE0, 0xA3, 0xED, 0xA0, 0x96, 0x3E,
- 0x1E, 0x89, 0x86, 0x02, 0x4C, 0x28, 0xFD, 0x57,
- 0xA1, 0x67, 0x55, 0xF0, 0x82, 0x3B, 0x7F, 0xCC,
- 0x2A, 0x32, 0x01, 0x93, 0x1D, 0x8B, 0x66, 0x8A,
- 0x20, 0x52, 0x84, 0xDD, 0x2C, 0xFD, 0xEE, 0x72,
- 0xF3, 0x8C, 0x58, 0xB9, 0x99, 0xE5, 0xC1, 0x22,
- 0x63, 0x59, 0x00, 0xE2, 0x76, 0xC5, 0x3A, 0x17,
- 0x7F, 0x93, 0xE9, 0x67, 0x61, 0xAA, 0x10, 0xC3,
- 0xD9, 0xC8, 0x24, 0x46, 0x5B, 0xBE, 0x8C, 0x1F,
- 0x2D, 0x66, 0x48, 0xD2, 0x02, 0x11, 0xFB, 0x74,
- 0x14, 0x76, 0x76, 0x5A, 0x98, 0x54, 0x35, 0xA7,
- 0x85, 0x66, 0x20, 0x26, 0x8B, 0x13, 0x6F, 0x68,
- 0xE3, 0xC9, 0x58, 0x7D, 0x1C, 0x3E, 0x01, 0x8D,
- 0xF8, 0xD6, 0x7F, 0xCF, 0xA2, 0x07, 0xB7, 0x95,
- 0xFD, 0xF0, 0x02, 0x34, 0x32, 0x30, 0xE8, 0xD4,
- 0x57, 0x5E, 0x53, 0xFB, 0x54, 0xE2, 0x03, 0x32,
- 0xCC, 0x52, 0x2E, 0xD2, 0x35, 0xD9, 0x58, 0x85,
- 0x2D, 0xEC, 0x2D, 0x71, 0xD1, 0x8A, 0x29, 0xD0,
- 0xB0, 0x24, 0xBD, 0x24, 0xDC, 0x1A, 0x28, 0x3F,
- 0xA0, 0x12, 0x81, 0x15, 0x24, 0xC9, 0xB5, 0x4A,
- 0x23, 0xB6, 0xA3, 0x45, 0x50, 0x2D, 0x73, 0x99,
- 0x6B, 0x1C, 0xFB, 0xA4, 0x53, 0xD7, 0x5C, 0xF4,
- 0x6C, 0xB0, 0xE5, 0x74, 0xB3, 0x76, 0xF8, 0xB1,
- 0x0D, 0x59, 0x70, 0x9F, 0xCA, 0xDE, 0xF2, 0xAA,
- 0x4C, 0x7D, 0x11, 0x54, 0xC4, 0x19, 0x0F, 0x36,
- 0x4A, 0x62, 0xFF, 0x8B, 0x10, 0xCB, 0x93, 0x50,
- 0xDA, 0x79, 0x5E, 0x4E, 0x09, 0x1F, 0x22, 0xC8,
- 0x19, 0x85, 0xE9, 0xEE, 0xB7, 0x71, 0x65, 0xB9,
- 0x10, 0xD2, 0x0A, 0x73, 0x5B, 0xA6, 0xDA, 0x37,
- 0x46, 0x02, 0x00, 0x98, 0x9E, 0x20, 0x6C, 0x7D,
- 0xC7, 0x69, 0xBB, 0xC2, 0x00, 0x40, 0x9C, 0x57,
- 0x00, 0xC2, 0x36, 0x76, 0xE8, 0x2A, 0x8D, 0xAD,
- 0x62, 0x57, 0xC8, 0xD0, 0x9D, 0x66, 0x27, 0x5A,
- 0xD8, 0x0D, 0x35, 0x60, 0x28, 0x38, 0x62, 0x94,
- 0x78, 0x36, 0x25, 0x58, 0xFD, 0xF8, 0x66, 0x1F,
- 0x68, 0x04, 0x0F, 0xD8, 0x00, 0xDF, 0xA0, 0x6C,
- 0x25, 0x42, 0x9A, 0x4C, 0xEB, 0x80, 0x13, 0x51,
- 0x7D, 0x2D, 0xA8, 0x89, 0xD6, 0x1B, 0x67, 0x72,
- 0x01, 0xF3, 0x2D, 0x16, 0x77, 0xFE, 0x22, 0xBC,
- 0x8A, 0x45, 0x09, 0x1F, 0x9C, 0x2F, 0x2A, 0xA9,
- 0x61, 0x5B, 0x4A, 0xE6, 0x64, 0x2C, 0x62, 0x1A,
- 0x3A, 0x96, 0xE6, 0x0A, 0xAE, 0x05, 0x1A, 0xC8,
- 0xCB, 0xD6, 0x8F, 0x3A, 0x4B, 0xE0, 0x7F, 0x82,
- 0xB4, 0x98, 0xF1, 0x9D, 0xD7, 0x14, 0x76, 0x5E,
- 0x77, 0x85, 0x87, 0xEC, 0x13, 0xDA, 0xFD, 0xAF,
- 0xCB, 0xA3, 0x1C, 0x99, 0xC1, 0xFE, 0x17, 0x0C,
- 0x40, 0x4D, 0x3C, 0x8F, 0x70, 0x86, 0x63, 0x64,
- 0xB7, 0x75, 0xA8, 0x71, 0x36, 0xDC, 0x54, 0x10,
- 0x57, 0x0C, 0xA8, 0xF2, 0xA1, 0xBB, 0xED, 0x03,
- 0x41, 0x57, 0x34, 0x2C, 0x8F, 0x7C, 0xA0, 0x09,
- 0xF3, 0x9E, 0x41, 0xB7, 0xA8, 0xD4, 0x66, 0x0D,
- 0x0D, 0xC0, 0x6A, 0xFC, 0x6A, 0xA2, 0xAC, 0xE2,
- 0x60, 0x00, 0xE3, 0xF7, 0x75, 0x43, 0x23, 0xEB,
- 0xC8, 0x61, 0xFA, 0xB3, 0xB8, 0x28, 0xCE, 0xCA,
- 0xF4, 0x47, 0x7F, 0x30, 0x6D, 0x61, 0x89, 0x47,
- 0xA1, 0x4A, 0xFE, 0xD1, 0x21, 0x0B, 0x6D, 0xF4,
- 0x3F, 0x00, 0x86, 0x30, 0x8E, 0x33, 0x21, 0x6F,
- 0xDA, 0x15, 0xFD, 0x5F, 0xEC, 0x8E, 0xF1, 0x12,
- 0x3F, 0xC9, 0x83, 0x0C, 0xCA, 0x22, 0x01, 0xF1,
- 0x70, 0x5F, 0x1F, 0x66, 0xB5, 0xF8, 0x3E, 0x7A,
- 0x6F, 0xDE, 0xDB, 0xA7, 0x8D, 0x18, 0x9E, 0xBE,
- 0xDB, 0xAD, 0x3D, 0x66, 0x30, 0xC1, 0x6C, 0x0C,
- 0x87, 0xB4, 0x65, 0x75, 0xE0, 0x9D, 0xEA, 0x16,
- 0x0D, 0x07, 0x37, 0x33, 0xC5, 0xEC, 0x97, 0x93,
- 0x37, 0xEB, 0x8E, 0x65, 0x9C, 0x40, 0x63, 0x6C,
- 0x43, 0x60, 0xB0, 0x40, 0x4D, 0x85, 0xEF, 0xC2,
- 0x47, 0x5F, 0xE7, 0x6B, 0xCB, 0x40, 0xE8, 0xEA,
- 0xD8, 0xAB, 0xB1, 0x9A, 0x72, 0xDC, 0x4C, 0x14,
- 0xFA, 0x43, 0x61, 0x5F, 0xA6, 0x5C, 0x3A, 0x05,
- 0x17, 0x2E, 0x74, 0xF3, 0x5E, 0x45, 0xD9, 0x47,
- 0xAA, 0x59, 0xB6, 0x8F, 0x42, 0x66, 0x42, 0x29,
- 0x90, 0x95, 0x48, 0x46, 0x91, 0x88, 0x3C, 0x8C,
- 0xDE, 0xCC, 0xED, 0xB3, 0xAA, 0x62, 0xEA, 0xBC,
- 0xB4, 0x0C, 0x48, 0x4C, 0x53, 0x23, 0x5E, 0x24,
- 0x85, 0xBF, 0x92, 0xDA, 0x14, 0xDB, 0x1A, 0x3D,
- 0xEF, 0x30, 0xD9, 0x49, 0x64, 0x4D, 0xE5, 0x01,
- 0xFC, 0xA4, 0x4B, 0xD1, 0x9F, 0xDE, 0x96, 0x7F,
- 0x50, 0xBC, 0x4D, 0x38, 0x44, 0xE9, 0x23, 0x5F,
- 0x37, 0x57, 0x1A, 0xA6, 0x52, 0x5A, 0x0F, 0x4F,
- 0x87, 0x33, 0x4A, 0x7B, 0x66, 0xEE, 0x3D, 0x66,
- 0x0A, 0x63, 0x39, 0x1F, 0x23, 0x38, 0x35, 0x73,
- 0x60, 0x5E, 0x47, 0x20, 0x4F, 0xC0, 0xC8, 0x3C,
- 0x09, 0xF9, 0x29, 0x4F, 0x5E, 0x55, 0x69, 0xC4,
- 0x6B, 0xE8, 0xF8, 0x91, 0xC0, 0x22, 0x65, 0x15,
- 0x1E, 0xFB, 0xB9, 0x61, 0xCE, 0x45, 0xBE, 0x2B,
- 0xEE, 0xB9, 0x04, 0x2B, 0xFD, 0xAE, 0x61, 0x1C,
- 0x3D, 0x3D, 0x7C, 0xBF, 0xC1, 0xF7, 0x3C, 0x4E,
- 0x9E, 0x0E, 0x54, 0xC8, 0xAD, 0xA9, 0xDF, 0x43,
- 0x49, 0xB9, 0x41, 0x05, 0xE5, 0xF1, 0x49, 0xAA,
- 0x77, 0x6C, 0x34, 0x5B, 0x93, 0x24, 0x24, 0x23,
- 0x74, 0x68, 0x11, 0xCE, 0x15, 0x80, 0xA1, 0xA4,
- 0x1F, 0x8D, 0x81, 0xCD, 0xB2, 0x98, 0xCA, 0x14,
- 0x0B, 0x0C, 0x61, 0x50, 0x69, 0x72, 0xAE, 0xFA,
- 0x8B, 0xC0, 0x3F, 0x0D, 0xE7, 0xF2, 0x0F, 0xEB,
- 0xC1, 0x11, 0xB9, 0x10, 0x03, 0x6A, 0xF5, 0x97,
- 0x3C, 0x53, 0x2F, 0x67, 0x86, 0x09, 0x6A, 0xE3,
- 0x28, 0xC0, 0x78, 0xC8, 0xB4, 0x39, 0x8E, 0xD1,
- 0xCE, 0x25, 0xE8, 0x66, 0xF7, 0x09, 0x40, 0x7D,
- 0x81, 0xFB, 0xAF, 0xFA, 0x59, 0xC4, 0x9B, 0x2B,
- 0x83, 0x45, 0x5B, 0xA8, 0x66, 0x9E, 0x38, 0xC8,
- 0xFD, 0xAC, 0xF2, 0x2D, 0x21, 0xDE, 0x50, 0x4C,
- 0x03, 0xCB, 0x88, 0x42, 0xDD, 0x84, 0x09, 0x99,
- 0x8E, 0x8B, 0x40, 0x97, 0x1B, 0x14, 0x85, 0x37,
- 0x11, 0x01, 0xE0, 0x74, 0x6B, 0x33, 0x52, 0x8C,
- 0x68, 0x3A, 0x89, 0xB2, 0xAF, 0x35, 0xE6, 0x65,
- 0xC3, 0x58, 0x70, 0xD2, 0xE7, 0x1F, 0x1F, 0xF6,
- 0xE5, 0x0A, 0xB1, 0xFE, 0xD0, 0xC9, 0x51, 0x50,
- 0xE7, 0xFD, 0x58, 0xF5, 0xC4, 0x58, 0x65, 0x94,
- 0xD1, 0x57, 0x55, 0x5E, 0xD2, 0x27, 0x98, 0xAF,
- 0xE7, 0x55, 0x0B, 0x87, 0x50, 0x9B, 0xEF, 0xE8,
- 0x2B, 0xFC, 0xE7, 0x3B, 0x4E, 0xD7, 0xB7, 0x4D,
- 0xF4, 0xBC, 0xF4, 0x88, 0x63, 0xE4, 0x8A, 0x20,
- 0x4B, 0x22, 0xB0, 0xA0, 0x53, 0x7F, 0xA8, 0xC9,
- 0x0C, 0xF8, 0xD7, 0xBD, 0x46, 0x39, 0xA7, 0x7D,
- 0xDD, 0x10, 0x91, 0x50, 0x54, 0x06, 0x47, 0xF0,
- 0x3C, 0xAA, 0x43, 0x40, 0xF8, 0x54, 0xDD, 0x8A,
- 0xEA, 0x8A, 0x0B, 0xA5, 0x7F, 0xCD, 0x5E, 0xAA,
- 0x02, 0x2E, 0x1F, 0xC6, 0x50, 0x15, 0xF8, 0x0A,
- 0x0C, 0x1B, 0x3C, 0x55, 0x3A, 0xC3, 0x6F, 0x88,
- 0xD7, 0xBF, 0xB1, 0x02, 0xCC, 0xE0, 0x08, 0x29,
- 0x97, 0xD2, 0xAA, 0x23, 0xC4, 0x6D, 0xE3, 0xE3,
- 0x76, 0x39, 0x92, 0xC3, 0x2E, 0x7A, 0xE2, 0x98,
- 0xD1, 0xFC, 0xAE, 0xCC, 0x95, 0xD8, 0xB4, 0xDC,
- 0x92, 0xEA, 0x6A, 0x5F, 0xF2, 0x92, 0x17, 0x0B,
- 0x8D, 0xC3, 0xFA, 0x9C, 0x62, 0xCE, 0x44, 0x8D,
- 0xC3, 0x1E, 0xC3, 0xB2, 0xD5, 0x00, 0xCD, 0xB4,
- 0x9E, 0x2D, 0x7B, 0xF2, 0x98, 0xA3, 0x00, 0x8B,
- 0x81, 0x30, 0x77, 0x5B, 0x02, 0x99, 0xB1, 0xCD,
- 0xC3, 0x1D, 0x74, 0x74, 0xEF, 0x41, 0xCB, 0x69,
- 0x63, 0x8E, 0xA6, 0xD3, 0x2D, 0x3E, 0x1F, 0x1D,
- 0x12, 0x9E, 0xD9, 0x18, 0x67, 0x06, 0xAF, 0x37,
- 0x29, 0xAD, 0x65, 0xD8, 0xEB, 0x71, 0xC4, 0x7D,
- 0x94, 0x3D, 0xEA, 0xCC, 0xDF, 0x72, 0x41, 0x51,
- 0x3C, 0xA1, 0x66, 0x98, 0x32, 0x32, 0x40, 0x54,
- 0xB0, 0x2F, 0xEB, 0xCE, 0xDF, 0x4A, 0x64, 0xFB,
- 0x9A, 0x90, 0xDC, 0xF6, 0x6F, 0xA9, 0xD4, 0xCA,
- 0xCB, 0x91, 0xC4, 0xFE, 0xEE, 0x9C, 0x01, 0x50,
- 0x2E, 0xAC, 0xCC, 0x5F, 0x89, 0xD0, 0x91, 0xA3,
- 0xD9, 0xF9, 0x4B, 0x8D, 0xDE, 0x6C, 0x60, 0x21,
- 0x19, 0xB1, 0xD3, 0x4D, 0x75, 0x56, 0x6F, 0xB8,
- 0x25, 0xA4, 0x92, 0x4F, 0x12, 0xF5, 0x8F, 0xC1,
- 0x17, 0x4B, 0xB3, 0x34, 0x21, 0x22, 0xAC, 0x52,
- 0xD2, 0x64, 0xC9, 0x9A, 0x7D, 0xFC, 0xC0, 0x0A,
- 0x89, 0x34, 0xFF, 0x08, 0xD3, 0x04, 0xDC, 0xFE,
- 0x7C, 0xB3, 0xB8, 0xFD, 0x85, 0xDD, 0x79, 0x51,
- 0xA7, 0x89, 0xE8, 0xF1, 0x23, 0xB1, 0xDF, 0xD7,
- 0x1F, 0x7B, 0xB1, 0x5D, 0x42, 0xF9, 0x61, 0xF8,
- 0xDC, 0x81, 0x04, 0xF1, 0xCC, 0xFA, 0xD7, 0xED,
- 0xBF, 0x47, 0xAC, 0xBD, 0xE5, 0xFA, 0xAC, 0xB3,
- 0x1C, 0xD9, 0xA1, 0xB3, 0x60, 0xEE, 0x9C, 0x8A,
- 0x36, 0x57, 0xB4, 0x2F, 0xA1, 0xA2, 0xF3, 0xE2,
- 0x09, 0x9A, 0x6E, 0x43, 0x9B, 0xE5, 0x93, 0xB8,
- 0x3D, 0x9E, 0x9F, 0xC1, 0xC6, 0x0D, 0x02, 0xEB,
- 0x4D, 0x38, 0xE9, 0xB4, 0x9F, 0xEA, 0x33, 0x8C,
- 0x07, 0xD8, 0xB4, 0x71, 0xAD, 0xE5, 0x43, 0xB2,
- 0xCC, 0x55, 0x93, 0x6A, 0xDB, 0x1E, 0x80, 0xDB,
- 0xC2, 0xEA, 0x42, 0x8E, 0xFC, 0x86, 0x44, 0xC9,
- 0x8A, 0xC4, 0xF2, 0x46, 0xA7, 0x39, 0x50, 0x0D,
- 0x1A, 0xAA, 0x07, 0x04, 0xBE, 0xD4, 0xCE, 0x62,
- 0x4D, 0x0F, 0x91, 0x7D, 0x29, 0x88, 0x9C, 0x4C,
- 0xAF, 0xF7, 0xD8, 0x40, 0x93, 0x88, 0xC7, 0x20,
- 0xD2, 0x17, 0x2A, 0xC4, 0x92, 0x72, 0xD0, 0xC0,
- 0x4E, 0x56, 0x47, 0xB1, 0x27, 0x02, 0xE6, 0x61,
- 0x82, 0x5E, 0xC8, 0x2E, 0x90, 0xD2, 0x31, 0x22,
- 0xE2, 0xA9, 0x4A, 0x91, 0x45, 0x69, 0xB1, 0xA5,
- 0x0F, 0x66, 0x2C, 0x30, 0xAD, 0x7F, 0x1B, 0x0E,
- 0x22, 0x17, 0x60, 0x2E, 0x3D, 0x7F, 0x7F, 0x8C,
- 0x33, 0x51, 0xA0, 0x25, 0xDE, 0xFD, 0x75, 0xBC,
- 0xEF, 0xE6, 0xE7, 0x20, 0x04, 0x5A, 0xEC, 0x50,
- 0x21, 0x48, 0x56, 0x98, 0xE2, 0x33, 0x6D, 0x22,
- 0x5C, 0xC3, 0xFB, 0xFC, 0x6F, 0xB3, 0xA7, 0x8E,
- 0x6F, 0x67, 0x70, 0x9D, 0xDA, 0x02, 0x01, 0x59,
- 0x7B, 0x3D, 0x2B, 0x38, 0xCC, 0x0F, 0x44, 0x3D,
- 0xFB, 0x9A, 0xB3, 0x23, 0x15, 0x50, 0x6E, 0xBF,
- 0x8B, 0xA1, 0x94, 0x33, 0xE5, 0x7B, 0x88, 0x4E,
- 0xCB, 0x6D, 0x9F, 0xBF, 0xBC, 0x7A, 0xA8, 0x1E,
- 0x68, 0x25, 0xED, 0x8E, 0x53, 0x21, 0x72, 0xC5,
- 0x70, 0xB3, 0xE4, 0xA6, 0xA1, 0x5A, 0x2D, 0xC8,
- 0x43, 0x9D, 0x60, 0x77, 0x78, 0xE0, 0xC4, 0xAF,
- 0xC8, 0x29, 0xBA, 0xD0, 0x4D, 0x39, 0x83, 0x51,
- 0xA7, 0x10, 0x7F, 0x0C, 0x34, 0x0E, 0x6C, 0x75,
- 0x26, 0xD7, 0xD6, 0xC7, 0x32, 0x53, 0xAF, 0x4E,
- 0xBE, 0xF2, 0xC2, 0x0F, 0x99, 0x23, 0xB9, 0xE1,
- 0xC8, 0xB4, 0xBC, 0x5A, 0xC6, 0xCB, 0xEB, 0x4D,
- 0x28, 0x56, 0x72, 0xFE, 0x1B, 0x2C, 0x5D, 0xE3,
- 0xBC, 0xC7, 0xA3, 0xC0, 0x7D, 0x27, 0xF0, 0xD0,
- 0x4F, 0x3F, 0x1F, 0xF7, 0x87, 0x15, 0xF2, 0xEA,
- 0xD4, 0x03, 0x6D, 0x2F, 0xD4, 0x8E, 0x50, 0x4B,
- 0x05, 0xBF, 0xF7, 0x8C, 0x67, 0x5A, 0xDC, 0x4D,
- 0xCD, 0xCF, 0x9D, 0x02, 0xB6, 0xE7, 0xAE, 0x49,
- 0xD1, 0x7C, 0x00, 0xE7, 0x3B, 0xEA, 0xFB, 0x0D,
- 0x2A, 0x7B, 0x41, 0x33, 0x66, 0xD0, 0x29, 0x9F,
- 0xB3, 0x8A, 0x71, 0xB0, 0xE2, 0x76, 0xA9, 0xDB,
- 0xFD, 0x64, 0x04, 0x69, 0xDF, 0x89, 0x1F, 0x56,
- 0x86, 0x92, 0xD9, 0xD9, 0xB9, 0xF3, 0x4F, 0xAC,
- 0xAE, 0x61, 0x48, 0x20, 0xCE, 0x3C, 0x2B, 0x44,
- 0xAB, 0x42, 0xFA, 0xAB, 0x2E, 0x94, 0x82, 0xC8,
- 0xD9, 0x97, 0xCF, 0x27, 0xDF, 0xAC, 0xAC, 0xE7,
- 0xCA, 0xB2, 0x84, 0xAB, 0xF2, 0x5D, 0xDF, 0x56,
- 0x0C, 0x8C, 0x07, 0x3C, 0x3D, 0xA8, 0xDD, 0xBE,
- 0xFF, 0x4E, 0x28, 0x0D, 0xB2, 0x2D, 0xE6, 0x9D,
- 0x44, 0x21, 0xCB, 0xE7, 0x33, 0x63, 0x22, 0x8F,
- 0x4C, 0xFF, 0xB6, 0x1D, 0x9A, 0x71, 0x3F, 0xB1,
- 0x29, 0xAE, 0x3A, 0x35, 0xEE, 0x9C, 0x97, 0x68,
- 0xA7, 0x52, 0x66, 0x01, 0xD8, 0x9A, 0x5D, 0xF4,
- 0xB3, 0x2F, 0x5C, 0xD4, 0x0E, 0xF9, 0xCF, 0x07,
- 0xF6, 0x8C, 0xBA, 0xA6, 0x8D, 0x6B, 0xC6, 0x01,
- 0xC2, 0x69, 0xAE, 0x60, 0x08, 0x1A, 0x0E, 0x3F,
- 0xAE, 0x60, 0x29, 0xF3, 0x48, 0x0D, 0xE0, 0xD0,
- 0xAE, 0x52, 0x44, 0xE9, 0x7F, 0x1F, 0x92, 0x5F,
- 0x71, 0xAD, 0xEC, 0x6B, 0x47, 0x66, 0x92, 0x22,
- 0x27, 0xAE, 0x6E, 0x25, 0xCD, 0xF3, 0x5F, 0x55,
- 0x59, 0xBD, 0x73, 0xCE, 0x2B, 0x7E, 0x99, 0x44,
- 0x56, 0x70, 0xA3, 0xE7, 0x7A, 0x59, 0x75, 0xD8,
- 0x48, 0x0C, 0x39, 0x2B, 0xD7, 0x53, 0xC6, 0xAD,
- 0x4A, 0x6F, 0xB4, 0x14, 0x96, 0xDF, 0xF2, 0x4A,
- 0x0C, 0xA2, 0xD5, 0x29, 0x98, 0x7C, 0x42, 0x87,
- 0xD9, 0x1F, 0x97, 0x61, 0xD9, 0xBF, 0x99, 0x4F,
- 0x2C, 0x4C, 0x75, 0xAC, 0xB8, 0x06, 0x75, 0xD6,
- 0x87, 0x76, 0x7E, 0xE3, 0x23, 0x4B, 0xEA, 0x1A,
- 0x1A, 0xF4, 0xB7, 0x09, 0xAF, 0x53, 0xEB, 0xA6,
- 0x39, 0x10, 0xFE, 0xD4, 0xEB, 0x1B, 0xAE, 0x38,
- 0x31, 0x33, 0xBA, 0x68, 0xEE, 0xC7, 0x65, 0x76,
- 0xFB, 0x49, 0x77, 0xD4, 0x19, 0xC4, 0xE6, 0xA7,
- 0x05, 0xFE, 0x2A, 0xDA, 0x39, 0x99, 0x1A, 0x92,
- 0xD2, 0xF0, 0x61, 0x97, 0xF6, 0x06, 0x6C, 0x88,
- 0x7B, 0x6F, 0x60, 0xE6, 0x70, 0x08, 0xF0, 0xB4,
- 0x6B, 0x39, 0x6F, 0x05, 0x41, 0x81, 0xF9, 0xBE,
- 0x7A, 0x51, 0xC4, 0x75, 0xB0, 0x6A, 0x89, 0xA0,
- 0xA6, 0x9A, 0x5B, 0xEE, 0x7D, 0x78, 0x17, 0x5F,
- 0x9F, 0x3B, 0x7D, 0xDD, 0x8A, 0x9E, 0xAA, 0x1A,
- 0xDA, 0x49, 0x08, 0xE9, 0xFD, 0x91, 0xA6, 0xFA,
- 0xCE, 0xCF, 0x67, 0xDF, 0x0F, 0xC9, 0xD6, 0x38,
- 0xD9, 0xD5, 0xD1, 0xC0, 0x76, 0x59, 0x42, 0x53,
- 0xBF, 0x48, 0xE9, 0x11, 0x74, 0xC7, 0x11, 0xD8,
- 0xE7, 0x8E, 0xD3, 0xC8, 0x25, 0xA1, 0x26, 0x50,
- 0xBB, 0xB4, 0x35, 0xAF, 0xAF, 0x06, 0x23, 0x69,
- 0x3E, 0x30, 0xFD, 0x7B, 0x34, 0x83, 0x07, 0xD0,
- 0xF0, 0x0F, 0x6C, 0x9A, 0x13, 0x5D, 0xC2, 0x7B,
- 0xDF, 0x6F, 0xDD, 0x8E, 0xF4, 0x30, 0x82, 0x05,
- 0x41, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x05, 0x32,
- 0x04, 0x82, 0x05, 0x2E, 0x30, 0x82, 0x05, 0x2A,
- 0x30, 0x82, 0x05, 0x26, 0x06, 0x0B, 0x2A, 0x86,
- 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01,
- 0x02, 0xA0, 0x82, 0x04, 0xEE, 0x30, 0x82, 0x04,
- 0xEA, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30,
- 0x0E, 0x04, 0x08, 0x74, 0xC0, 0x84, 0x8F, 0xC7,
- 0x74, 0x5E, 0x21, 0x02, 0x02, 0x08, 0x00, 0x04,
- 0x82, 0x04, 0xC8, 0x1E, 0xF4, 0xE9, 0x07, 0x27,
- 0x9E, 0x5A, 0xC9, 0x39, 0x1D, 0x37, 0x2C, 0x06,
- 0x4B, 0x57, 0xEA, 0xC5, 0x42, 0x9A, 0x60, 0xD5,
- 0x42, 0xB2, 0x34, 0x2D, 0xD3, 0x88, 0x7C, 0x78,
- 0x87, 0xB6, 0xE9, 0x42, 0x44, 0x1F, 0x67, 0x32,
- 0x92, 0x54, 0x22, 0xDA, 0xB2, 0x43, 0xE7, 0x40,
- 0xBE, 0x1F, 0xAF, 0x3A, 0xCD, 0x2A, 0x9F, 0xD7,
- 0x44, 0x5B, 0x37, 0x69, 0x85, 0xDF, 0xEB, 0x2A,
- 0xB9, 0xE2, 0x92, 0x3B, 0xEA, 0xD5, 0x42, 0x53,
- 0x95, 0x4A, 0xB0, 0x1B, 0xA5, 0xEF, 0xA6, 0x0D,
- 0x29, 0xF4, 0x33, 0xFE, 0xD7, 0x49, 0x04, 0x1E,
- 0x8C, 0xAD, 0x63, 0x1E, 0x79, 0x63, 0x74, 0x0C,
- 0xE5, 0x5E, 0xA2, 0x2C, 0xBE, 0xB8, 0x90, 0xCE,
- 0x06, 0x25, 0xBF, 0xD1, 0x5A, 0x50, 0xCF, 0x3B,
- 0x52, 0xE2, 0xA7, 0xFF, 0x19, 0x02, 0xCF, 0xD0,
- 0x9B, 0xD9, 0xF7, 0x28, 0x07, 0x38, 0x1F, 0xF2,
- 0xAF, 0x44, 0x91, 0x3F, 0x0F, 0xB6, 0x6E, 0x8C,
- 0xC0, 0x32, 0x92, 0xC0, 0xCD, 0x25, 0x98, 0x67,
- 0xF1, 0x47, 0x52, 0x50, 0xF0, 0xA3, 0x7B, 0xE6,
- 0x74, 0xDC, 0x72, 0x28, 0xC8, 0xAB, 0xB3, 0x31,
- 0x7D, 0xA3, 0xF7, 0xC7, 0xD1, 0xE6, 0x99, 0xB4,
- 0xB6, 0x5A, 0x3A, 0x4D, 0x83, 0x4F, 0xB8, 0xB5,
- 0x86, 0xF8, 0x37, 0x7F, 0xA0, 0x16, 0x2F, 0x3C,
- 0x62, 0x7A, 0xD4, 0x3A, 0xEB, 0xC2, 0xE8, 0x03,
- 0x49, 0x17, 0x9E, 0xFB, 0xD7, 0xAF, 0x91, 0x32,
- 0xFD, 0xEA, 0x4F, 0x64, 0xC6, 0x6E, 0x02, 0xEA,
- 0xC4, 0xC8, 0x1F, 0x16, 0xC5, 0x4C, 0xFB, 0xC5,
- 0x42, 0xF5, 0x85, 0x05, 0x92, 0x59, 0x4B, 0x31,
- 0xE5, 0xE9, 0x69, 0xE7, 0x02, 0x98, 0x33, 0xBA,
- 0x4C, 0x17, 0x09, 0xEF, 0x89, 0x20, 0xFA, 0x83,
- 0x9F, 0xAE, 0x0E, 0x1B, 0x7D, 0x98, 0xB9, 0xF2,
- 0x3C, 0x0F, 0xB7, 0x1C, 0x72, 0xDF, 0x17, 0x84,
- 0x7F, 0x0A, 0xFD, 0x12, 0x3C, 0x6F, 0x68, 0x5D,
- 0x45, 0xEB, 0xB8, 0xD6, 0x24, 0x65, 0x42, 0x75,
- 0x5C, 0xC2, 0xF3, 0x3A, 0x6A, 0x4E, 0x51, 0x34,
- 0x1B, 0xB6, 0x81, 0xB2, 0x8A, 0xEF, 0x28, 0xA4,
- 0xC5, 0x88, 0x9A, 0x97, 0xE0, 0xEF, 0x31, 0x12,
- 0x01, 0x7E, 0x1B, 0x43, 0x0F, 0x27, 0x80, 0x87,
- 0x98, 0xC5, 0xD5, 0x83, 0xCB, 0x4B, 0xB7, 0x01,
- 0x79, 0x60, 0xA1, 0x1A, 0x03, 0x05, 0xC6, 0x36,
- 0x04, 0x31, 0x3C, 0x06, 0xDB, 0x08, 0xA8, 0xDA,
- 0x8E, 0x32, 0x19, 0x91, 0xF1, 0x0D, 0x61, 0x6F,
- 0xE4, 0xB2, 0x79, 0x8A, 0xDE, 0xF4, 0xF7, 0xFB,
- 0x2C, 0x23, 0x5B, 0xD9, 0x64, 0x2F, 0xB7, 0xB3,
- 0x8B, 0xCA, 0xB8, 0x8C, 0x1D, 0x3B, 0x49, 0x05,
- 0x38, 0xA1, 0xE5, 0x8C, 0x1A, 0xDC, 0xA5, 0x61,
- 0xFE, 0xF4, 0x2B, 0xDC, 0x77, 0x28, 0xF6, 0x19,
- 0xE7, 0xB7, 0x8F, 0x4D, 0x27, 0x2D, 0xED, 0x8A,
- 0x3F, 0x3D, 0xDC, 0x9F, 0xD1, 0x30, 0xFF, 0xD6,
- 0xC3, 0xBE, 0x41, 0x25, 0xE3, 0xA5, 0x9B, 0x73,
- 0xDF, 0x6A, 0xD9, 0xF9, 0x70, 0x84, 0x02, 0x4C,
- 0x35, 0xD4, 0x3E, 0x05, 0x76, 0x3A, 0xDC, 0x6D,
- 0x5A, 0x81, 0xB3, 0x94, 0xF7, 0x22, 0xF7, 0xDC,
- 0xC1, 0x43, 0x31, 0x57, 0x5B, 0x42, 0x9A, 0x0B,
- 0xF4, 0x95, 0x30, 0xA9, 0xBB, 0xD8, 0x06, 0xFB,
- 0x1D, 0x6F, 0x9B, 0xC3, 0xBB, 0xF3, 0xBF, 0xFB,
- 0xB4, 0x9F, 0x35, 0x64, 0x0A, 0x69, 0xB7, 0xD1,
- 0x3E, 0xCA, 0x78, 0x07, 0x04, 0x03, 0x79, 0xD4,
- 0xF3, 0xA8, 0xEC, 0x18, 0xDB, 0x03, 0x5E, 0x47,
- 0xD7, 0xD0, 0x56, 0x2C, 0x74, 0x94, 0x86, 0x04,
- 0x46, 0xB8, 0xD4, 0x35, 0x0A, 0x7B, 0xE6, 0x78,
- 0xC4, 0x43, 0x3C, 0x56, 0xCC, 0x37, 0x8B, 0xFD,
- 0xE8, 0xF4, 0x57, 0xEA, 0xAE, 0xCF, 0x36, 0x97,
- 0x12, 0xAC, 0x39, 0xCF, 0x7C, 0xEF, 0x22, 0x67,
- 0x01, 0xEC, 0xD8, 0x09, 0x49, 0x4E, 0xE3, 0x74,
- 0xDD, 0x39, 0xE1, 0x39, 0xD7, 0x0C, 0x5F, 0x1B,
- 0xCE, 0x69, 0xBC, 0x72, 0x44, 0x87, 0x64, 0x1C,
- 0x08, 0x05, 0x93, 0x69, 0x6D, 0x7F, 0x90, 0x0A,
- 0x2C, 0xCB, 0x8A, 0xBB, 0x7F, 0xE3, 0xE0, 0x80,
- 0x31, 0xD0, 0x0A, 0x3A, 0x95, 0xFF, 0xF7, 0xB4,
- 0x36, 0x38, 0x93, 0xE0, 0x0C, 0x11, 0x37, 0x12,
- 0x06, 0xF6, 0xAD, 0xE9, 0xB1, 0x7A, 0x00, 0xF5,
- 0xD2, 0x32, 0x6B, 0xD0, 0x27, 0xA5, 0x1B, 0x3D,
- 0xE8, 0xDB, 0xCC, 0xA9, 0x1F, 0x1F, 0xB1, 0x99,
- 0x3D, 0x7C, 0xB7, 0xCA, 0xDA, 0x27, 0x2C, 0x64,
- 0x1C, 0x49, 0xB6, 0x87, 0x44, 0x06, 0x94, 0x9D,
- 0xBC, 0x6B, 0x20, 0xA2, 0x68, 0x15, 0x1F, 0xE2,
- 0xF2, 0xAD, 0x6D, 0x23, 0x2E, 0x2B, 0x74, 0xE2,
- 0x5D, 0xE4, 0xB0, 0xC7, 0x84, 0xCB, 0x64, 0xBF,
- 0xE0, 0xA8, 0x18, 0x83, 0xB4, 0xC9, 0xD9, 0x73,
- 0xA8, 0xE6, 0xA9, 0x36, 0xD5, 0x63, 0x1E, 0x2C,
- 0x2A, 0x55, 0x09, 0x77, 0x5E, 0xB3, 0x4B, 0xEA,
- 0xB5, 0xD0, 0x14, 0x5F, 0xEB, 0x50, 0x7B, 0xAA,
- 0xEF, 0x94, 0xBA, 0x2B, 0xD7, 0x8A, 0x07, 0xF1,
- 0xF9, 0x5E, 0x12, 0x12, 0x21, 0x52, 0xE5, 0x0A,
- 0x3E, 0xC0, 0xBC, 0x5D, 0x4C, 0xE2, 0x12, 0x7C,
- 0x39, 0xF9, 0x16, 0x9D, 0xBD, 0x96, 0x83, 0x3B,
- 0x7F, 0x3D, 0x6A, 0xEC, 0xF1, 0x25, 0xD2, 0xB0,
- 0xB0, 0xEB, 0x20, 0x06, 0x07, 0xD6, 0xD9, 0x4C,
- 0x07, 0x9A, 0x82, 0xC1, 0xFC, 0xF7, 0x66, 0x15,
- 0xBD, 0x62, 0x65, 0xD8, 0x6C, 0xF6, 0x33, 0x7B,
- 0x5A, 0x28, 0xEC, 0x90, 0xA1, 0x26, 0x9F, 0xC3,
- 0x28, 0x4A, 0x64, 0x50, 0x5F, 0xCA, 0xE2, 0x6D,
- 0xB8, 0x0F, 0xE2, 0x94, 0xB5, 0x8E, 0x1F, 0x8A,
- 0x8F, 0x6B, 0xA6, 0x86, 0x1F, 0xEE, 0xDC, 0x24,
- 0xB4, 0xB8, 0x25, 0xEC, 0x28, 0x2D, 0xF9, 0xCB,
- 0x7D, 0x38, 0xFF, 0xC7, 0x74, 0x2E, 0xD3, 0x10,
- 0xEC, 0x03, 0x31, 0xEE, 0x83, 0xE7, 0xA4, 0xF7,
- 0xBA, 0x28, 0x21, 0xE0, 0x7F, 0xB4, 0xB7, 0xE1,
- 0x7A, 0xF9, 0x2B, 0xB0, 0x2C, 0x3B, 0x80, 0x5F,
- 0xE0, 0x5D, 0xB2, 0x7E, 0x59, 0xFF, 0x59, 0x07,
- 0x58, 0x42, 0x57, 0xEE, 0x44, 0xF1, 0xB1, 0xAD,
- 0xBA, 0xDE, 0xCB, 0x1D, 0x8A, 0x36, 0x67, 0xE8,
- 0x45, 0xFF, 0x07, 0x8D, 0xEE, 0xA4, 0x51, 0x9C,
- 0x4C, 0x83, 0x5D, 0x2E, 0x2F, 0xE1, 0x5B, 0x75,
- 0xE8, 0x29, 0xCD, 0x0B, 0x07, 0x62, 0xE0, 0xC3,
- 0x0D, 0x1D, 0xEA, 0xCF, 0xF0, 0x8A, 0x65, 0x27,
- 0x70, 0x42, 0x9F, 0x26, 0x00, 0x15, 0x70, 0xC5,
- 0x4A, 0xF6, 0x25, 0xD0, 0x40, 0x72, 0xE9, 0xC1,
- 0x73, 0xFD, 0x48, 0x94, 0xA3, 0x8D, 0x66, 0x63,
- 0x96, 0x4F, 0xF7, 0xEE, 0xFB, 0x4C, 0xC7, 0xB8,
- 0x6B, 0xE9, 0x90, 0xE1, 0x2A, 0x66, 0x80, 0x99,
- 0x3B, 0xB0, 0x1A, 0x6C, 0xF9, 0x0E, 0x72, 0xDA,
- 0x8E, 0x4F, 0x46, 0xC2, 0x6A, 0x4B, 0x7A, 0x16,
- 0xE5, 0x26, 0x0B, 0x5C, 0xD4, 0x47, 0x34, 0xE5,
- 0x37, 0xBE, 0x68, 0x6C, 0xDA, 0xD3, 0x9B, 0x6F,
- 0xAE, 0x51, 0x9C, 0x99, 0x0A, 0x5B, 0xF8, 0x37,
- 0xBC, 0xDE, 0xFC, 0x93, 0xC5, 0xE7, 0x0F, 0xEF,
- 0x0B, 0xA6, 0x07, 0xC2, 0xA6, 0xE6, 0xDA, 0x2D,
- 0x1B, 0x49, 0xC9, 0xDE, 0x6B, 0x27, 0xDC, 0x00,
- 0xEF, 0x23, 0x87, 0x0E, 0xEB, 0xD1, 0x48, 0x7D,
- 0xB4, 0xF2, 0x58, 0xC6, 0x3C, 0xE2, 0x89, 0xBA,
- 0xB0, 0x05, 0xAC, 0x94, 0x41, 0x9A, 0xA8, 0xFF,
- 0x3E, 0xBC, 0x3A, 0x52, 0x9C, 0xF9, 0x7F, 0x07,
- 0x8B, 0xB0, 0x2C, 0x71, 0x83, 0x7B, 0xCF, 0x2E,
- 0x7F, 0x7C, 0x96, 0x65, 0xD9, 0x08, 0x17, 0xEC,
- 0xFA, 0xDE, 0x4E, 0x40, 0x12, 0x26, 0x70, 0x71,
- 0x65, 0xA5, 0xDC, 0x98, 0x47, 0xA3, 0xFC, 0xE0,
- 0x9A, 0x16, 0xED, 0x45, 0x56, 0x72, 0x50, 0x05,
- 0x28, 0x2C, 0x99, 0xEC, 0x20, 0x2E, 0x40, 0xC0,
- 0x26, 0x69, 0xCD, 0x49, 0x45, 0x17, 0xA4, 0xA3,
- 0x42, 0x0D, 0x14, 0x65, 0x87, 0x33, 0x8C, 0x92,
- 0xC5, 0xC4, 0x61, 0xFD, 0xE8, 0x68, 0x56, 0x20,
- 0x57, 0xF5, 0x8E, 0x5F, 0xCF, 0x7E, 0x97, 0xF6,
- 0x49, 0x97, 0x0A, 0xFE, 0xD3, 0x60, 0x1A, 0x5B,
- 0x0C, 0x75, 0xDD, 0x8E, 0x31, 0x78, 0x29, 0xA6,
- 0xB1, 0x4D, 0xAA, 0xDF, 0x8A, 0xD1, 0xE6, 0x91,
- 0xE3, 0x32, 0x3F, 0xEC, 0x8A, 0x1F, 0x0E, 0x35,
- 0x07, 0x6E, 0x4B, 0x83, 0x3B, 0xE5, 0x67, 0x34,
- 0x1F, 0x0C, 0x81, 0xD8, 0xD5, 0x25, 0x68, 0xE5,
- 0x28, 0x1B, 0x5C, 0x81, 0x3E, 0xE3, 0x5C, 0xB4,
- 0xB6, 0xBD, 0x62, 0x6A, 0x70, 0x33, 0xC2, 0xC5,
- 0x75, 0x27, 0xF4, 0x30, 0xE1, 0x1D, 0xC1, 0x4C,
- 0xC5, 0x02, 0x12, 0x46, 0xAC, 0xEC, 0xF9, 0xE8,
- 0xE7, 0x58, 0x24, 0x11, 0xB1, 0xF3, 0xB7, 0x8C,
- 0x3C, 0xA4, 0x0A, 0x94, 0xA6, 0x7C, 0x68, 0x54,
- 0x5B, 0xB9, 0x4D, 0x57, 0x9C, 0xE7, 0x28, 0x09,
- 0x6B, 0x89, 0x26, 0x5D, 0xE7, 0x50, 0xA9, 0x95,
- 0x90, 0x91, 0x8E, 0x00, 0x59, 0xF8, 0x3A, 0x70,
- 0xAF, 0x48, 0x2E, 0xE8, 0xC4, 0x34, 0x8C, 0xF4,
- 0x5F, 0x7F, 0xCB, 0x07, 0xAA, 0xF0, 0xD9, 0xFB,
- 0x5C, 0x32, 0x90, 0x22, 0x1A, 0xD2, 0x1A, 0xCF,
- 0x92, 0x06, 0x02, 0xCF, 0x10, 0x18, 0x7B, 0x93,
- 0xCC, 0x07, 0x4A, 0x31, 0x25, 0x30, 0x23, 0x06,
- 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
- 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0xD1, 0xDE,
- 0x23, 0x16, 0x9F, 0x6E, 0xF4, 0x42, 0x21, 0x23,
- 0xE1, 0x11, 0xAA, 0xC8, 0x7C, 0x60, 0x4A, 0x78,
- 0x9D, 0x24, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09,
- 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05,
- 0x00, 0x04, 0x14, 0xD6, 0x4A, 0xBB, 0x75, 0xB1,
- 0xF9, 0x9E, 0xD3, 0x58, 0x6D, 0xD1, 0x74, 0x9F,
- 0x00, 0x8A, 0xF2, 0xC8, 0xAA, 0x52, 0x4D, 0x04,
- 0x08, 0x77, 0x46, 0xE7, 0xBA, 0x25, 0x4B, 0xDA,
- 0x41, 0x02, 0x02, 0x08, 0x00]
-};
-
-const WPA_EAP_CLIENT_LIST = [
- {
- ssid: 'WPA-EAP-PEAP',
- keyManagement: 'WPA-EAP',
- eap: 'PEAP',
- identity: EAP_USERNAME,
- password: EAP_PASSWORD,
- serverCertificate: CLIENT_PKCS12_CERT.nickname,
- phase2: 'MSCHAPV2'
- }
-];
-
-/**
- * Convert the given MozWifiNetwork object array to testAssociate chain.
- *
- * @param aNetworks
- * An array of MozWifiNetwork which we want to convert.
- *
- * @return A promise chain which "then"s testAssociate accordingly.
- */
-function convertToTestAssociateChain(aNetworks) {
- let chain = Promise.resolve();
-
- aNetworks.forEach(function (aNetwork) {
- network = new window.MozWifiNetwork(aNetwork);
- chain = chain.then(() => gTestSuite.testAssociate(network));
- });
-
- return chain;
-}
-
-gTestSuite.doTestWithCertificate(
- new Blob([new Uint8Array(CLIENT_PKCS12_CERT.content)]),
- CLIENT_PKCS12_CERT.password,
- CLIENT_PKCS12_CERT.nickname,
- CLIENT_PKCS12_CERT.usage,
- function() {
- return gTestSuite.ensureWifiEnabled(true)
- // Load required server files.
- .then(() => gTestSuite.writeFile(SERVER_EAP_USER_CONF.path, SERVER_EAP_USER_CONF.content))
- .then(() => gTestSuite.writeFile(CA_CERT.path, CA_CERT.content))
- .then(() => gTestSuite.writeFile(SERVER_CERT.path, SERVER_CERT.content))
- .then(() => gTestSuite.writeFile(SERVER_KEY.path, SERVER_KEY.content))
- // Start AP.
- .then(() => gTestSuite.startHostapds(WPA_EAP_AP_LIST))
- // Scan test.
- .then(() => gTestSuite.testWifiScanWithRetry(SCAN_RETRY_CNT, WPA_EAP_AP_LIST))
- // Associate test.
- .then(() => convertToTestAssociateChain(WPA_EAP_CLIENT_LIST))
- // Tear down.
- .then(gTestSuite.killAllHostapd)
-});
diff --git a/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_TLS.js b/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_TLS.js
deleted file mode 100644
index 35b942f8e..000000000
--- a/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_TLS.js
+++ /dev/null
@@ -1,622 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const SCAN_RETRY_CNT = 5;
-
-const EAP_USERNAME = 'username';
-const EAP_PASSWORD = 'password';
-
-const SERVER_EAP_USER_CONF = {
- path: HOSTAPD_CONFIG_PATH + 'hostapd.eap_user',
- content: '* PEAP,TTLS,TLS\n' +
- '"' + EAP_USERNAME + '" MSCHAPV2,TTLS-MSCHAPV2 "' + EAP_PASSWORD + '" [2]\n'
-};
-const CA_CERT = {
- path: HOSTAPD_CONFIG_PATH + 'ca.pem',
- content: '-----BEGIN CERTIFICATE-----\n' +
- 'MIIDsTCCApmgAwIBAgIJAKxTf+8X8qngMA0GCSqGSIb3DQEBCwUAMG4xCzAJBgNV\n' +
- 'BAYTAlRXMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhjaHVja2xlZTER\n' +
- 'MA8GA1UEAwwIY2h1Y2tsZWUxJDAiBgkqhkiG9w0BCQEWFWNodWNrbGkwNzA2QGdt\n' +
- 'YWlsLmNvbTAgFw0xNDEyMjQxMTI4NTBaGA8yMjg4MTAwNzExMjg1MFowbjELMAkG\n' +
- 'A1UEBhMCVFcxEzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAoMCGNodWNrbGVl\n' +
- 'MREwDwYDVQQDDAhjaHVja2xlZTEkMCIGCSqGSIb3DQEJARYVY2h1Y2tsaTA3MDZA\n' +
- 'Z21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo3c2yFxY\n' +
- 'o6gGg0I83jy00ME+MAfzCd+4ShL45ZLqysQP93jRBfPzU9ZuZ29ysVwgWIdqkZao\n' +
- 'XTuV/NAW2GMGd8W1jQJ3J81fjb9wvhlny3rrACwvUn1N1S1BnM+BAAiDLGxEmvAQ\n' +
- 'onp2aaa6HsHsYS8ONX+d2Qh4LEA4vupeSGAqJychCZv/l+aq/ErFZhFYB3CPUQEt\n' +
- 'cClO24ucsIYP95lA0zhscnmAj06qplFD4Bv6IVrdDqujy1zNwCQwsJq/8OQdaTN/\n' +
- 'h3y9pWvNKMBMM2niOUAjtuNpqsSK/lTS1WAT3PdtVECX9fYBi0Bg+HM92xs/6gt6\n' +
- 'kh9jPV8keXHvSwIDAQABo1AwTjAdBgNVHQ4EFgQU7hBqhuG04xeCzrQ3ngx18ZJ3\n' +
- 'lUswHwYDVR0jBBgwFoAU7hBqhuG04xeCzrQ3ngx18ZJ3lUswDAYDVR0TBAUwAwEB\n' +
- '/zANBgkqhkiG9w0BAQsFAAOCAQEAFYX2iy680GAnBTttk0gyX6gk+8pYr3D22k/G\n' +
- '6rvcjefzS7ELQPRKr6mfmwXq3mMf/4jiS2zI5zmXsestPYzHYxf2viQ6t7vr9XiJ\n' +
- '3WfFjNw4ERlRisAvg0aqqTNNQq5v2VME4sdFZagy217f73C7azwCHl0bqOLH05rl\n' +
- '8RubOxiHEj7ZybJqnRciK/bht4D+rZkwf4bBBmoloqH7xT0+rFQclpYXDGGjNUQB\n' +
- 'LcHLF10xcr7g3ZVVu82fe6+d85gIGOIMR9+TKhdw6gO3CNcnDAj6gxksghgtcxmh\n' +
- 'OzOggCn7nlIwImtsg2sZkpWB4lEi9hdv4lkNuyFjOL3bnuc+NA==\n' +
- '-----END CERTIFICATE-----\n'
-};
-
-const SERVER_CERT = {
- path: HOSTAPD_CONFIG_PATH + 'server.pem',
- content: '-----BEGIN CERTIFICATE-----\n' +
- 'MIID1DCCArygAwIBAgIBADANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJUVzET\n' +
- 'MBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UECgwIY2h1Y2tsZWUxETAPBgNVBAMM\n' +
- 'CGNodWNrbGVlMSQwIgYJKoZIhvcNAQkBFhVjaHVja2xpMDcwNkBnbWFpbC5jb20w\n' +
- 'IBcNMTQxMjI0MTEyOTQ5WhgPMjI4ODEwMDcxMTI5NDlaMG4xCzAJBgNVBAYTAlRX\n' +
- 'MRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhjaHVja2xlZTERMA8GA1UE\n' +
- 'AwwIY2h1Y2tsZWUxJDAiBgkqhkiG9w0BCQEWFWNodWNrbGkwNzA2QGdtYWlsLmNv\n' +
- 'bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMdhQmKilTJbWZRxTiSV\n' +
- 'rqIU+LYW1RKghx5o+0JpNRJVLuz5kBMaNskbbfUSNuHbEq0QA9BDKAZWIc4LSotk\n' +
- 'lCo8TbcO9CJvJPQGGjGdHcohWX5vy6BE/OVE46CUteMFyZF6F8R2fNUww08iR/u1\n' +
- 'YZebL5pWO1j43sPpAzEy6Tij2ACPt6EZcFaZG3SF2mVJWkCQnBqrojP65WUvZQqp\n' +
- 'seUhW2YAS8Nu0Yrohgxz6VYk+cNDuDZVGs6qWRStZzJfYrfc76DtkHof5B14M+xp\n' +
- 'XJaBLxN+whvnYkDTfinaCxnW1O7eXUltr87fLc5zmeBkgwaiaQuIdcfZm7vDUiz8\n' +
- 'vnUCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH\n' +
- 'ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFKK4f9/YavTHOfEiAB83Deac\n' +
- '6gT5MB8GA1UdIwQYMBaAFO4QaobhtOMXgs60N54MdfGSd5VLMA0GCSqGSIb3DQEB\n' +
- 'CwUAA4IBAQBWnO9o9KSJIqjoz5Nwll63ULOdcvgGdOeJIw1fcKQ817Rsp+TVcjcH\n' +
- 'IrIADsT/QZGXRO/l6p1750e2iFtJEo1hsRaxtA1wWn2I9HO3+av2spQhr3jpYGPf\n' +
- 'zpsMTp4RNYV7Q8+q1kZIz9PY4V1T0p6lveK8+fUj2hSLnxSj0QiGSJJtnEC3w4Rv\n' +
- 'C9T6oUwIeToULmi+8FXQFdEqwKRU98DPq3eLzN28ZxUgoPE1C8+42D2UW8uyp/Gm\n' +
- 'tGOa/k7nzkCdVqZI7lX7f0AjEvQgjtAMQ/k7Mhxx7TzW2HO+1YPMoKji6Z4WkNwt\n' +
- 'JEj9ZUBSNt8B26UksJMBDkcvSegF3a7o\n' +
- '-----END CERTIFICATE-----\n'
-};
-
-const SERVER_KEY = {
- path: HOSTAPD_CONFIG_PATH + 'server.key',
- content: '-----BEGIN RSA PRIVATE KEY-----\n' +
- 'MIIEpAIBAAKCAQEAx2FCYqKVMltZlHFOJJWuohT4thbVEqCHHmj7Qmk1ElUu7PmQ\n' +
- 'Exo2yRtt9RI24dsSrRAD0EMoBlYhzgtKi2SUKjxNtw70Im8k9AYaMZ0dyiFZfm/L\n' +
- 'oET85UTjoJS14wXJkXoXxHZ81TDDTyJH+7Vhl5svmlY7WPjew+kDMTLpOKPYAI+3\n' +
- 'oRlwVpkbdIXaZUlaQJCcGquiM/rlZS9lCqmx5SFbZgBLw27RiuiGDHPpViT5w0O4\n' +
- 'NlUazqpZFK1nMl9it9zvoO2Qeh/kHXgz7GlcloEvE37CG+diQNN+KdoLGdbU7t5d\n' +
- 'SW2vzt8tznOZ4GSDBqJpC4h1x9mbu8NSLPy+dQIDAQABAoIBAASG4Mr8hgaurEoC\n' +
- 'iJOsElr7vunjetMBcg/uskW/vcS8ymP3Bp5oafYG+WgnEbfvEW18f5mq7K24JuxW\n' +
- 'tUqU7ghHdjxByqk9fMlNmiqmNpbwSufkAeuRpWxPNBvhRH/zEbCL5R5A0nTEtqqF\n' +
- 'TL0aUSzwCRSoAJD0lZo9ICVt0n3GsDyM9rqQg/uZmh1qsRdwPsRuYORND9g48rKq\n' +
- '6WN9leskSxhhsYE2D9ocOFd9bNt8Zxejh9ppVSnG/KsIdt18iBzcabatgAQ046fb\n' +
- 'Z3vprcZJLg93Sg2gSuVqlSTs3M2W8VQnm22/EBMb1y0M48MSRCgnbPLG/CcCLLfF\n' +
- 'LwxCOgECgYEA/eYt67xyJ6JeAdxdwOZuT1WWGbFpLiG9+2OgiHumyRQ5969XMTWo\n' +
- 'fIhMKchDdjoy9RR236\/\/EFCs7UEyB7+a7ODRzNiK2zCD8Smjp+21fUPSthEeQesk\n' +
- 'eiMYICIu5Ay35x9sxIX+XOUVvRhPOGcD29GVeRnKh1inTHOz2dje8LkCgYEAyQeY\n' +
- 'STi9jjCEcHkM1E/UeDiLfHHepLXi8wS41JNRHl5Jacp7XB5djAjKu/jf367/VpFy\n' +
- 'GDDMetE7n8eWkrnAvovxOwZ000YDMtL1sUYSjL+XtBS5s6VY1p4qaSAY9nUUGrJh\n' +
- 'JvtvsuI7SKTtL+60vjBOH7zDnvOdBgAp0utLhZ0CgYEAuLzzqrPKB8afShFSchn4\n' +
- 'J2dpuLYahsNsXW7HDqeR2nsKFosRETAusLXnXPtnAq4kB6jlOarwFqnsuRCX24Vx\n' +
- 'r2uBm9/vYL7zMdUPTA+s30ErHuhjsKjsOKYyVqcooSwT32pBFNk+E89nutfmRG7I\n' +
- 'IvhjHuNCNqqtx/Xj5d1jkZkCgYBQicppC2Jl5OoqZVTOem0U/RJk+PnJ41TZJ7sk\n' +
- '7yBAmmWvDH\/\/l+rCf4M5a6vFYcbKV9rt9h711X2dtciNX/3oWQh8LUoAmrwNUJc+\n' +
- 'PmSQHvIYI3WCk2vUD+nN1B4sHxu+1lg11eYaNKiroeeknG2tBI1ICcgVlmQCU25u\n' +
- 'IfZPwQKBgQCdO6QHhPLtcHUDNFA6FQ1jKL1iEd7G0JLVRz4Xkpkn1Vrr5MD6JFDa\n' +
- '5ccabADyl0lpFqDIVJQIzLku2hOD2i9aBNCY0pL391HeOS7CkZX+TdOY1tquoBq5\n' +
- 'MnmixZjDCVd2VcrVyTA6ntOBoharKFW0rH1PqU+qu7dZF7CBPbAdEw==\n' +
- '-----END RSA PRIVATE KEY-----\n'
-};
-
-const WPA_EAP_AP_LIST = [
- {
- ssid: 'WPA-EAP-TLS',
- ieee8021x: 1,
- eapol_version: 1,
- eap_server: 1,
- eapol_key_index_workaround: 0,
- eap_user_file: SERVER_EAP_USER_CONF.path,
- ca_cert: CA_CERT.path,
- server_cert: SERVER_CERT.path,
- private_key: SERVER_KEY.path,
- wpa: 2,
- wpa_key_mgmt: 'WPA-EAP'
- }
-];
-
-const CLIENT_PKCS12_CERT = {
- nickname: 'client',
- password: 'password',
- usage: ['UserCert', 'ServerCert'],
- content: [0x30, 0x82, 0x0E, 0x01, 0x02, 0x01, 0x03, 0x30,
- 0x82, 0x0D, 0xC7, 0x06, 0x09, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82,
- 0x0D, 0xB8, 0x04, 0x82, 0x0D, 0xB4, 0x30, 0x82,
- 0x0D, 0xB0, 0x30, 0x82, 0x08, 0x67, 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07,
- 0x06, 0xA0, 0x82, 0x08, 0x58, 0x30, 0x82, 0x08,
- 0x54, 0x02, 0x01, 0x00, 0x30, 0x82, 0x08, 0x4D,
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x07, 0x01, 0x30, 0x1C, 0x06, 0x0A, 0x2A,
- 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01,
- 0x06, 0x30, 0x0E, 0x04, 0x08, 0x67, 0x7A, 0xF3,
- 0x61, 0xBE, 0xE0, 0x51, 0xC1, 0x02, 0x02, 0x08,
- 0x00, 0x80, 0x82, 0x08, 0x20, 0xFC, 0x6A, 0x79,
- 0xA1, 0x6C, 0xAF, 0xBE, 0xEE, 0x62, 0x45, 0x33,
- 0xB8, 0x48, 0xE1, 0x68, 0xA1, 0x15, 0x11, 0x4B,
- 0x95, 0xCB, 0x77, 0xC0, 0x5D, 0xA2, 0xCB, 0xDB,
- 0xD1, 0x83, 0x74, 0x60, 0xD7, 0xEC, 0x42, 0xA6,
- 0x3A, 0x23, 0xF7, 0x85, 0xEB, 0xC1, 0xFE, 0x6A,
- 0x57, 0x8E, 0xC1, 0x44, 0xF3, 0x1F, 0xFE, 0xB8,
- 0x2D, 0x8C, 0x4D, 0xC9, 0x5B, 0xAE, 0x21, 0x2E,
- 0x4C, 0x1A, 0xEB, 0x84, 0x09, 0xF3, 0x40, 0x92,
- 0x39, 0x7F, 0x56, 0x02, 0x46, 0x61, 0x16, 0xDE,
- 0x5C, 0x48, 0xB6, 0x0C, 0x1D, 0xD3, 0x5F, 0x10,
- 0x9A, 0x39, 0xB8, 0x66, 0x31, 0xFC, 0x39, 0x71,
- 0x87, 0x23, 0x46, 0x9D, 0xE8, 0x3C, 0x2B, 0xA1,
- 0x39, 0x8A, 0xD3, 0xFF, 0xD9, 0x43, 0xB6, 0x61,
- 0xC6, 0x67, 0x70, 0x40, 0xBD, 0xFE, 0xD3, 0xC1,
- 0x68, 0xF5, 0xF7, 0xC8, 0x89, 0xD8, 0x17, 0xC5,
- 0xE8, 0x3D, 0x29, 0xD5, 0x91, 0xDF, 0x1F, 0x56,
- 0x74, 0x5A, 0xC4, 0xA8, 0x14, 0xBA, 0xD4, 0xFA,
- 0x13, 0x49, 0x2A, 0x9F, 0x63, 0xF1, 0xB2, 0x45,
- 0xF1, 0xF0, 0x2A, 0xDD, 0x75, 0x66, 0x8A, 0xF7,
- 0xAB, 0x73, 0x86, 0x26, 0x9D, 0x1F, 0x07, 0xAD,
- 0xD3, 0xFE, 0xE0, 0xA3, 0xED, 0xA0, 0x96, 0x3E,
- 0x1E, 0x89, 0x86, 0x02, 0x4C, 0x28, 0xFD, 0x57,
- 0xA1, 0x67, 0x55, 0xF0, 0x82, 0x3B, 0x7F, 0xCC,
- 0x2A, 0x32, 0x01, 0x93, 0x1D, 0x8B, 0x66, 0x8A,
- 0x20, 0x52, 0x84, 0xDD, 0x2C, 0xFD, 0xEE, 0x72,
- 0xF3, 0x8C, 0x58, 0xB9, 0x99, 0xE5, 0xC1, 0x22,
- 0x63, 0x59, 0x00, 0xE2, 0x76, 0xC5, 0x3A, 0x17,
- 0x7F, 0x93, 0xE9, 0x67, 0x61, 0xAA, 0x10, 0xC3,
- 0xD9, 0xC8, 0x24, 0x46, 0x5B, 0xBE, 0x8C, 0x1F,
- 0x2D, 0x66, 0x48, 0xD2, 0x02, 0x11, 0xFB, 0x74,
- 0x14, 0x76, 0x76, 0x5A, 0x98, 0x54, 0x35, 0xA7,
- 0x85, 0x66, 0x20, 0x26, 0x8B, 0x13, 0x6F, 0x68,
- 0xE3, 0xC9, 0x58, 0x7D, 0x1C, 0x3E, 0x01, 0x8D,
- 0xF8, 0xD6, 0x7F, 0xCF, 0xA2, 0x07, 0xB7, 0x95,
- 0xFD, 0xF0, 0x02, 0x34, 0x32, 0x30, 0xE8, 0xD4,
- 0x57, 0x5E, 0x53, 0xFB, 0x54, 0xE2, 0x03, 0x32,
- 0xCC, 0x52, 0x2E, 0xD2, 0x35, 0xD9, 0x58, 0x85,
- 0x2D, 0xEC, 0x2D, 0x71, 0xD1, 0x8A, 0x29, 0xD0,
- 0xB0, 0x24, 0xBD, 0x24, 0xDC, 0x1A, 0x28, 0x3F,
- 0xA0, 0x12, 0x81, 0x15, 0x24, 0xC9, 0xB5, 0x4A,
- 0x23, 0xB6, 0xA3, 0x45, 0x50, 0x2D, 0x73, 0x99,
- 0x6B, 0x1C, 0xFB, 0xA4, 0x53, 0xD7, 0x5C, 0xF4,
- 0x6C, 0xB0, 0xE5, 0x74, 0xB3, 0x76, 0xF8, 0xB1,
- 0x0D, 0x59, 0x70, 0x9F, 0xCA, 0xDE, 0xF2, 0xAA,
- 0x4C, 0x7D, 0x11, 0x54, 0xC4, 0x19, 0x0F, 0x36,
- 0x4A, 0x62, 0xFF, 0x8B, 0x10, 0xCB, 0x93, 0x50,
- 0xDA, 0x79, 0x5E, 0x4E, 0x09, 0x1F, 0x22, 0xC8,
- 0x19, 0x85, 0xE9, 0xEE, 0xB7, 0x71, 0x65, 0xB9,
- 0x10, 0xD2, 0x0A, 0x73, 0x5B, 0xA6, 0xDA, 0x37,
- 0x46, 0x02, 0x00, 0x98, 0x9E, 0x20, 0x6C, 0x7D,
- 0xC7, 0x69, 0xBB, 0xC2, 0x00, 0x40, 0x9C, 0x57,
- 0x00, 0xC2, 0x36, 0x76, 0xE8, 0x2A, 0x8D, 0xAD,
- 0x62, 0x57, 0xC8, 0xD0, 0x9D, 0x66, 0x27, 0x5A,
- 0xD8, 0x0D, 0x35, 0x60, 0x28, 0x38, 0x62, 0x94,
- 0x78, 0x36, 0x25, 0x58, 0xFD, 0xF8, 0x66, 0x1F,
- 0x68, 0x04, 0x0F, 0xD8, 0x00, 0xDF, 0xA0, 0x6C,
- 0x25, 0x42, 0x9A, 0x4C, 0xEB, 0x80, 0x13, 0x51,
- 0x7D, 0x2D, 0xA8, 0x89, 0xD6, 0x1B, 0x67, 0x72,
- 0x01, 0xF3, 0x2D, 0x16, 0x77, 0xFE, 0x22, 0xBC,
- 0x8A, 0x45, 0x09, 0x1F, 0x9C, 0x2F, 0x2A, 0xA9,
- 0x61, 0x5B, 0x4A, 0xE6, 0x64, 0x2C, 0x62, 0x1A,
- 0x3A, 0x96, 0xE6, 0x0A, 0xAE, 0x05, 0x1A, 0xC8,
- 0xCB, 0xD6, 0x8F, 0x3A, 0x4B, 0xE0, 0x7F, 0x82,
- 0xB4, 0x98, 0xF1, 0x9D, 0xD7, 0x14, 0x76, 0x5E,
- 0x77, 0x85, 0x87, 0xEC, 0x13, 0xDA, 0xFD, 0xAF,
- 0xCB, 0xA3, 0x1C, 0x99, 0xC1, 0xFE, 0x17, 0x0C,
- 0x40, 0x4D, 0x3C, 0x8F, 0x70, 0x86, 0x63, 0x64,
- 0xB7, 0x75, 0xA8, 0x71, 0x36, 0xDC, 0x54, 0x10,
- 0x57, 0x0C, 0xA8, 0xF2, 0xA1, 0xBB, 0xED, 0x03,
- 0x41, 0x57, 0x34, 0x2C, 0x8F, 0x7C, 0xA0, 0x09,
- 0xF3, 0x9E, 0x41, 0xB7, 0xA8, 0xD4, 0x66, 0x0D,
- 0x0D, 0xC0, 0x6A, 0xFC, 0x6A, 0xA2, 0xAC, 0xE2,
- 0x60, 0x00, 0xE3, 0xF7, 0x75, 0x43, 0x23, 0xEB,
- 0xC8, 0x61, 0xFA, 0xB3, 0xB8, 0x28, 0xCE, 0xCA,
- 0xF4, 0x47, 0x7F, 0x30, 0x6D, 0x61, 0x89, 0x47,
- 0xA1, 0x4A, 0xFE, 0xD1, 0x21, 0x0B, 0x6D, 0xF4,
- 0x3F, 0x00, 0x86, 0x30, 0x8E, 0x33, 0x21, 0x6F,
- 0xDA, 0x15, 0xFD, 0x5F, 0xEC, 0x8E, 0xF1, 0x12,
- 0x3F, 0xC9, 0x83, 0x0C, 0xCA, 0x22, 0x01, 0xF1,
- 0x70, 0x5F, 0x1F, 0x66, 0xB5, 0xF8, 0x3E, 0x7A,
- 0x6F, 0xDE, 0xDB, 0xA7, 0x8D, 0x18, 0x9E, 0xBE,
- 0xDB, 0xAD, 0x3D, 0x66, 0x30, 0xC1, 0x6C, 0x0C,
- 0x87, 0xB4, 0x65, 0x75, 0xE0, 0x9D, 0xEA, 0x16,
- 0x0D, 0x07, 0x37, 0x33, 0xC5, 0xEC, 0x97, 0x93,
- 0x37, 0xEB, 0x8E, 0x65, 0x9C, 0x40, 0x63, 0x6C,
- 0x43, 0x60, 0xB0, 0x40, 0x4D, 0x85, 0xEF, 0xC2,
- 0x47, 0x5F, 0xE7, 0x6B, 0xCB, 0x40, 0xE8, 0xEA,
- 0xD8, 0xAB, 0xB1, 0x9A, 0x72, 0xDC, 0x4C, 0x14,
- 0xFA, 0x43, 0x61, 0x5F, 0xA6, 0x5C, 0x3A, 0x05,
- 0x17, 0x2E, 0x74, 0xF3, 0x5E, 0x45, 0xD9, 0x47,
- 0xAA, 0x59, 0xB6, 0x8F, 0x42, 0x66, 0x42, 0x29,
- 0x90, 0x95, 0x48, 0x46, 0x91, 0x88, 0x3C, 0x8C,
- 0xDE, 0xCC, 0xED, 0xB3, 0xAA, 0x62, 0xEA, 0xBC,
- 0xB4, 0x0C, 0x48, 0x4C, 0x53, 0x23, 0x5E, 0x24,
- 0x85, 0xBF, 0x92, 0xDA, 0x14, 0xDB, 0x1A, 0x3D,
- 0xEF, 0x30, 0xD9, 0x49, 0x64, 0x4D, 0xE5, 0x01,
- 0xFC, 0xA4, 0x4B, 0xD1, 0x9F, 0xDE, 0x96, 0x7F,
- 0x50, 0xBC, 0x4D, 0x38, 0x44, 0xE9, 0x23, 0x5F,
- 0x37, 0x57, 0x1A, 0xA6, 0x52, 0x5A, 0x0F, 0x4F,
- 0x87, 0x33, 0x4A, 0x7B, 0x66, 0xEE, 0x3D, 0x66,
- 0x0A, 0x63, 0x39, 0x1F, 0x23, 0x38, 0x35, 0x73,
- 0x60, 0x5E, 0x47, 0x20, 0x4F, 0xC0, 0xC8, 0x3C,
- 0x09, 0xF9, 0x29, 0x4F, 0x5E, 0x55, 0x69, 0xC4,
- 0x6B, 0xE8, 0xF8, 0x91, 0xC0, 0x22, 0x65, 0x15,
- 0x1E, 0xFB, 0xB9, 0x61, 0xCE, 0x45, 0xBE, 0x2B,
- 0xEE, 0xB9, 0x04, 0x2B, 0xFD, 0xAE, 0x61, 0x1C,
- 0x3D, 0x3D, 0x7C, 0xBF, 0xC1, 0xF7, 0x3C, 0x4E,
- 0x9E, 0x0E, 0x54, 0xC8, 0xAD, 0xA9, 0xDF, 0x43,
- 0x49, 0xB9, 0x41, 0x05, 0xE5, 0xF1, 0x49, 0xAA,
- 0x77, 0x6C, 0x34, 0x5B, 0x93, 0x24, 0x24, 0x23,
- 0x74, 0x68, 0x11, 0xCE, 0x15, 0x80, 0xA1, 0xA4,
- 0x1F, 0x8D, 0x81, 0xCD, 0xB2, 0x98, 0xCA, 0x14,
- 0x0B, 0x0C, 0x61, 0x50, 0x69, 0x72, 0xAE, 0xFA,
- 0x8B, 0xC0, 0x3F, 0x0D, 0xE7, 0xF2, 0x0F, 0xEB,
- 0xC1, 0x11, 0xB9, 0x10, 0x03, 0x6A, 0xF5, 0x97,
- 0x3C, 0x53, 0x2F, 0x67, 0x86, 0x09, 0x6A, 0xE3,
- 0x28, 0xC0, 0x78, 0xC8, 0xB4, 0x39, 0x8E, 0xD1,
- 0xCE, 0x25, 0xE8, 0x66, 0xF7, 0x09, 0x40, 0x7D,
- 0x81, 0xFB, 0xAF, 0xFA, 0x59, 0xC4, 0x9B, 0x2B,
- 0x83, 0x45, 0x5B, 0xA8, 0x66, 0x9E, 0x38, 0xC8,
- 0xFD, 0xAC, 0xF2, 0x2D, 0x21, 0xDE, 0x50, 0x4C,
- 0x03, 0xCB, 0x88, 0x42, 0xDD, 0x84, 0x09, 0x99,
- 0x8E, 0x8B, 0x40, 0x97, 0x1B, 0x14, 0x85, 0x37,
- 0x11, 0x01, 0xE0, 0x74, 0x6B, 0x33, 0x52, 0x8C,
- 0x68, 0x3A, 0x89, 0xB2, 0xAF, 0x35, 0xE6, 0x65,
- 0xC3, 0x58, 0x70, 0xD2, 0xE7, 0x1F, 0x1F, 0xF6,
- 0xE5, 0x0A, 0xB1, 0xFE, 0xD0, 0xC9, 0x51, 0x50,
- 0xE7, 0xFD, 0x58, 0xF5, 0xC4, 0x58, 0x65, 0x94,
- 0xD1, 0x57, 0x55, 0x5E, 0xD2, 0x27, 0x98, 0xAF,
- 0xE7, 0x55, 0x0B, 0x87, 0x50, 0x9B, 0xEF, 0xE8,
- 0x2B, 0xFC, 0xE7, 0x3B, 0x4E, 0xD7, 0xB7, 0x4D,
- 0xF4, 0xBC, 0xF4, 0x88, 0x63, 0xE4, 0x8A, 0x20,
- 0x4B, 0x22, 0xB0, 0xA0, 0x53, 0x7F, 0xA8, 0xC9,
- 0x0C, 0xF8, 0xD7, 0xBD, 0x46, 0x39, 0xA7, 0x7D,
- 0xDD, 0x10, 0x91, 0x50, 0x54, 0x06, 0x47, 0xF0,
- 0x3C, 0xAA, 0x43, 0x40, 0xF8, 0x54, 0xDD, 0x8A,
- 0xEA, 0x8A, 0x0B, 0xA5, 0x7F, 0xCD, 0x5E, 0xAA,
- 0x02, 0x2E, 0x1F, 0xC6, 0x50, 0x15, 0xF8, 0x0A,
- 0x0C, 0x1B, 0x3C, 0x55, 0x3A, 0xC3, 0x6F, 0x88,
- 0xD7, 0xBF, 0xB1, 0x02, 0xCC, 0xE0, 0x08, 0x29,
- 0x97, 0xD2, 0xAA, 0x23, 0xC4, 0x6D, 0xE3, 0xE3,
- 0x76, 0x39, 0x92, 0xC3, 0x2E, 0x7A, 0xE2, 0x98,
- 0xD1, 0xFC, 0xAE, 0xCC, 0x95, 0xD8, 0xB4, 0xDC,
- 0x92, 0xEA, 0x6A, 0x5F, 0xF2, 0x92, 0x17, 0x0B,
- 0x8D, 0xC3, 0xFA, 0x9C, 0x62, 0xCE, 0x44, 0x8D,
- 0xC3, 0x1E, 0xC3, 0xB2, 0xD5, 0x00, 0xCD, 0xB4,
- 0x9E, 0x2D, 0x7B, 0xF2, 0x98, 0xA3, 0x00, 0x8B,
- 0x81, 0x30, 0x77, 0x5B, 0x02, 0x99, 0xB1, 0xCD,
- 0xC3, 0x1D, 0x74, 0x74, 0xEF, 0x41, 0xCB, 0x69,
- 0x63, 0x8E, 0xA6, 0xD3, 0x2D, 0x3E, 0x1F, 0x1D,
- 0x12, 0x9E, 0xD9, 0x18, 0x67, 0x06, 0xAF, 0x37,
- 0x29, 0xAD, 0x65, 0xD8, 0xEB, 0x71, 0xC4, 0x7D,
- 0x94, 0x3D, 0xEA, 0xCC, 0xDF, 0x72, 0x41, 0x51,
- 0x3C, 0xA1, 0x66, 0x98, 0x32, 0x32, 0x40, 0x54,
- 0xB0, 0x2F, 0xEB, 0xCE, 0xDF, 0x4A, 0x64, 0xFB,
- 0x9A, 0x90, 0xDC, 0xF6, 0x6F, 0xA9, 0xD4, 0xCA,
- 0xCB, 0x91, 0xC4, 0xFE, 0xEE, 0x9C, 0x01, 0x50,
- 0x2E, 0xAC, 0xCC, 0x5F, 0x89, 0xD0, 0x91, 0xA3,
- 0xD9, 0xF9, 0x4B, 0x8D, 0xDE, 0x6C, 0x60, 0x21,
- 0x19, 0xB1, 0xD3, 0x4D, 0x75, 0x56, 0x6F, 0xB8,
- 0x25, 0xA4, 0x92, 0x4F, 0x12, 0xF5, 0x8F, 0xC1,
- 0x17, 0x4B, 0xB3, 0x34, 0x21, 0x22, 0xAC, 0x52,
- 0xD2, 0x64, 0xC9, 0x9A, 0x7D, 0xFC, 0xC0, 0x0A,
- 0x89, 0x34, 0xFF, 0x08, 0xD3, 0x04, 0xDC, 0xFE,
- 0x7C, 0xB3, 0xB8, 0xFD, 0x85, 0xDD, 0x79, 0x51,
- 0xA7, 0x89, 0xE8, 0xF1, 0x23, 0xB1, 0xDF, 0xD7,
- 0x1F, 0x7B, 0xB1, 0x5D, 0x42, 0xF9, 0x61, 0xF8,
- 0xDC, 0x81, 0x04, 0xF1, 0xCC, 0xFA, 0xD7, 0xED,
- 0xBF, 0x47, 0xAC, 0xBD, 0xE5, 0xFA, 0xAC, 0xB3,
- 0x1C, 0xD9, 0xA1, 0xB3, 0x60, 0xEE, 0x9C, 0x8A,
- 0x36, 0x57, 0xB4, 0x2F, 0xA1, 0xA2, 0xF3, 0xE2,
- 0x09, 0x9A, 0x6E, 0x43, 0x9B, 0xE5, 0x93, 0xB8,
- 0x3D, 0x9E, 0x9F, 0xC1, 0xC6, 0x0D, 0x02, 0xEB,
- 0x4D, 0x38, 0xE9, 0xB4, 0x9F, 0xEA, 0x33, 0x8C,
- 0x07, 0xD8, 0xB4, 0x71, 0xAD, 0xE5, 0x43, 0xB2,
- 0xCC, 0x55, 0x93, 0x6A, 0xDB, 0x1E, 0x80, 0xDB,
- 0xC2, 0xEA, 0x42, 0x8E, 0xFC, 0x86, 0x44, 0xC9,
- 0x8A, 0xC4, 0xF2, 0x46, 0xA7, 0x39, 0x50, 0x0D,
- 0x1A, 0xAA, 0x07, 0x04, 0xBE, 0xD4, 0xCE, 0x62,
- 0x4D, 0x0F, 0x91, 0x7D, 0x29, 0x88, 0x9C, 0x4C,
- 0xAF, 0xF7, 0xD8, 0x40, 0x93, 0x88, 0xC7, 0x20,
- 0xD2, 0x17, 0x2A, 0xC4, 0x92, 0x72, 0xD0, 0xC0,
- 0x4E, 0x56, 0x47, 0xB1, 0x27, 0x02, 0xE6, 0x61,
- 0x82, 0x5E, 0xC8, 0x2E, 0x90, 0xD2, 0x31, 0x22,
- 0xE2, 0xA9, 0x4A, 0x91, 0x45, 0x69, 0xB1, 0xA5,
- 0x0F, 0x66, 0x2C, 0x30, 0xAD, 0x7F, 0x1B, 0x0E,
- 0x22, 0x17, 0x60, 0x2E, 0x3D, 0x7F, 0x7F, 0x8C,
- 0x33, 0x51, 0xA0, 0x25, 0xDE, 0xFD, 0x75, 0xBC,
- 0xEF, 0xE6, 0xE7, 0x20, 0x04, 0x5A, 0xEC, 0x50,
- 0x21, 0x48, 0x56, 0x98, 0xE2, 0x33, 0x6D, 0x22,
- 0x5C, 0xC3, 0xFB, 0xFC, 0x6F, 0xB3, 0xA7, 0x8E,
- 0x6F, 0x67, 0x70, 0x9D, 0xDA, 0x02, 0x01, 0x59,
- 0x7B, 0x3D, 0x2B, 0x38, 0xCC, 0x0F, 0x44, 0x3D,
- 0xFB, 0x9A, 0xB3, 0x23, 0x15, 0x50, 0x6E, 0xBF,
- 0x8B, 0xA1, 0x94, 0x33, 0xE5, 0x7B, 0x88, 0x4E,
- 0xCB, 0x6D, 0x9F, 0xBF, 0xBC, 0x7A, 0xA8, 0x1E,
- 0x68, 0x25, 0xED, 0x8E, 0x53, 0x21, 0x72, 0xC5,
- 0x70, 0xB3, 0xE4, 0xA6, 0xA1, 0x5A, 0x2D, 0xC8,
- 0x43, 0x9D, 0x60, 0x77, 0x78, 0xE0, 0xC4, 0xAF,
- 0xC8, 0x29, 0xBA, 0xD0, 0x4D, 0x39, 0x83, 0x51,
- 0xA7, 0x10, 0x7F, 0x0C, 0x34, 0x0E, 0x6C, 0x75,
- 0x26, 0xD7, 0xD6, 0xC7, 0x32, 0x53, 0xAF, 0x4E,
- 0xBE, 0xF2, 0xC2, 0x0F, 0x99, 0x23, 0xB9, 0xE1,
- 0xC8, 0xB4, 0xBC, 0x5A, 0xC6, 0xCB, 0xEB, 0x4D,
- 0x28, 0x56, 0x72, 0xFE, 0x1B, 0x2C, 0x5D, 0xE3,
- 0xBC, 0xC7, 0xA3, 0xC0, 0x7D, 0x27, 0xF0, 0xD0,
- 0x4F, 0x3F, 0x1F, 0xF7, 0x87, 0x15, 0xF2, 0xEA,
- 0xD4, 0x03, 0x6D, 0x2F, 0xD4, 0x8E, 0x50, 0x4B,
- 0x05, 0xBF, 0xF7, 0x8C, 0x67, 0x5A, 0xDC, 0x4D,
- 0xCD, 0xCF, 0x9D, 0x02, 0xB6, 0xE7, 0xAE, 0x49,
- 0xD1, 0x7C, 0x00, 0xE7, 0x3B, 0xEA, 0xFB, 0x0D,
- 0x2A, 0x7B, 0x41, 0x33, 0x66, 0xD0, 0x29, 0x9F,
- 0xB3, 0x8A, 0x71, 0xB0, 0xE2, 0x76, 0xA9, 0xDB,
- 0xFD, 0x64, 0x04, 0x69, 0xDF, 0x89, 0x1F, 0x56,
- 0x86, 0x92, 0xD9, 0xD9, 0xB9, 0xF3, 0x4F, 0xAC,
- 0xAE, 0x61, 0x48, 0x20, 0xCE, 0x3C, 0x2B, 0x44,
- 0xAB, 0x42, 0xFA, 0xAB, 0x2E, 0x94, 0x82, 0xC8,
- 0xD9, 0x97, 0xCF, 0x27, 0xDF, 0xAC, 0xAC, 0xE7,
- 0xCA, 0xB2, 0x84, 0xAB, 0xF2, 0x5D, 0xDF, 0x56,
- 0x0C, 0x8C, 0x07, 0x3C, 0x3D, 0xA8, 0xDD, 0xBE,
- 0xFF, 0x4E, 0x28, 0x0D, 0xB2, 0x2D, 0xE6, 0x9D,
- 0x44, 0x21, 0xCB, 0xE7, 0x33, 0x63, 0x22, 0x8F,
- 0x4C, 0xFF, 0xB6, 0x1D, 0x9A, 0x71, 0x3F, 0xB1,
- 0x29, 0xAE, 0x3A, 0x35, 0xEE, 0x9C, 0x97, 0x68,
- 0xA7, 0x52, 0x66, 0x01, 0xD8, 0x9A, 0x5D, 0xF4,
- 0xB3, 0x2F, 0x5C, 0xD4, 0x0E, 0xF9, 0xCF, 0x07,
- 0xF6, 0x8C, 0xBA, 0xA6, 0x8D, 0x6B, 0xC6, 0x01,
- 0xC2, 0x69, 0xAE, 0x60, 0x08, 0x1A, 0x0E, 0x3F,
- 0xAE, 0x60, 0x29, 0xF3, 0x48, 0x0D, 0xE0, 0xD0,
- 0xAE, 0x52, 0x44, 0xE9, 0x7F, 0x1F, 0x92, 0x5F,
- 0x71, 0xAD, 0xEC, 0x6B, 0x47, 0x66, 0x92, 0x22,
- 0x27, 0xAE, 0x6E, 0x25, 0xCD, 0xF3, 0x5F, 0x55,
- 0x59, 0xBD, 0x73, 0xCE, 0x2B, 0x7E, 0x99, 0x44,
- 0x56, 0x70, 0xA3, 0xE7, 0x7A, 0x59, 0x75, 0xD8,
- 0x48, 0x0C, 0x39, 0x2B, 0xD7, 0x53, 0xC6, 0xAD,
- 0x4A, 0x6F, 0xB4, 0x14, 0x96, 0xDF, 0xF2, 0x4A,
- 0x0C, 0xA2, 0xD5, 0x29, 0x98, 0x7C, 0x42, 0x87,
- 0xD9, 0x1F, 0x97, 0x61, 0xD9, 0xBF, 0x99, 0x4F,
- 0x2C, 0x4C, 0x75, 0xAC, 0xB8, 0x06, 0x75, 0xD6,
- 0x87, 0x76, 0x7E, 0xE3, 0x23, 0x4B, 0xEA, 0x1A,
- 0x1A, 0xF4, 0xB7, 0x09, 0xAF, 0x53, 0xEB, 0xA6,
- 0x39, 0x10, 0xFE, 0xD4, 0xEB, 0x1B, 0xAE, 0x38,
- 0x31, 0x33, 0xBA, 0x68, 0xEE, 0xC7, 0x65, 0x76,
- 0xFB, 0x49, 0x77, 0xD4, 0x19, 0xC4, 0xE6, 0xA7,
- 0x05, 0xFE, 0x2A, 0xDA, 0x39, 0x99, 0x1A, 0x92,
- 0xD2, 0xF0, 0x61, 0x97, 0xF6, 0x06, 0x6C, 0x88,
- 0x7B, 0x6F, 0x60, 0xE6, 0x70, 0x08, 0xF0, 0xB4,
- 0x6B, 0x39, 0x6F, 0x05, 0x41, 0x81, 0xF9, 0xBE,
- 0x7A, 0x51, 0xC4, 0x75, 0xB0, 0x6A, 0x89, 0xA0,
- 0xA6, 0x9A, 0x5B, 0xEE, 0x7D, 0x78, 0x17, 0x5F,
- 0x9F, 0x3B, 0x7D, 0xDD, 0x8A, 0x9E, 0xAA, 0x1A,
- 0xDA, 0x49, 0x08, 0xE9, 0xFD, 0x91, 0xA6, 0xFA,
- 0xCE, 0xCF, 0x67, 0xDF, 0x0F, 0xC9, 0xD6, 0x38,
- 0xD9, 0xD5, 0xD1, 0xC0, 0x76, 0x59, 0x42, 0x53,
- 0xBF, 0x48, 0xE9, 0x11, 0x74, 0xC7, 0x11, 0xD8,
- 0xE7, 0x8E, 0xD3, 0xC8, 0x25, 0xA1, 0x26, 0x50,
- 0xBB, 0xB4, 0x35, 0xAF, 0xAF, 0x06, 0x23, 0x69,
- 0x3E, 0x30, 0xFD, 0x7B, 0x34, 0x83, 0x07, 0xD0,
- 0xF0, 0x0F, 0x6C, 0x9A, 0x13, 0x5D, 0xC2, 0x7B,
- 0xDF, 0x6F, 0xDD, 0x8E, 0xF4, 0x30, 0x82, 0x05,
- 0x41, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x05, 0x32,
- 0x04, 0x82, 0x05, 0x2E, 0x30, 0x82, 0x05, 0x2A,
- 0x30, 0x82, 0x05, 0x26, 0x06, 0x0B, 0x2A, 0x86,
- 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01,
- 0x02, 0xA0, 0x82, 0x04, 0xEE, 0x30, 0x82, 0x04,
- 0xEA, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30,
- 0x0E, 0x04, 0x08, 0x74, 0xC0, 0x84, 0x8F, 0xC7,
- 0x74, 0x5E, 0x21, 0x02, 0x02, 0x08, 0x00, 0x04,
- 0x82, 0x04, 0xC8, 0x1E, 0xF4, 0xE9, 0x07, 0x27,
- 0x9E, 0x5A, 0xC9, 0x39, 0x1D, 0x37, 0x2C, 0x06,
- 0x4B, 0x57, 0xEA, 0xC5, 0x42, 0x9A, 0x60, 0xD5,
- 0x42, 0xB2, 0x34, 0x2D, 0xD3, 0x88, 0x7C, 0x78,
- 0x87, 0xB6, 0xE9, 0x42, 0x44, 0x1F, 0x67, 0x32,
- 0x92, 0x54, 0x22, 0xDA, 0xB2, 0x43, 0xE7, 0x40,
- 0xBE, 0x1F, 0xAF, 0x3A, 0xCD, 0x2A, 0x9F, 0xD7,
- 0x44, 0x5B, 0x37, 0x69, 0x85, 0xDF, 0xEB, 0x2A,
- 0xB9, 0xE2, 0x92, 0x3B, 0xEA, 0xD5, 0x42, 0x53,
- 0x95, 0x4A, 0xB0, 0x1B, 0xA5, 0xEF, 0xA6, 0x0D,
- 0x29, 0xF4, 0x33, 0xFE, 0xD7, 0x49, 0x04, 0x1E,
- 0x8C, 0xAD, 0x63, 0x1E, 0x79, 0x63, 0x74, 0x0C,
- 0xE5, 0x5E, 0xA2, 0x2C, 0xBE, 0xB8, 0x90, 0xCE,
- 0x06, 0x25, 0xBF, 0xD1, 0x5A, 0x50, 0xCF, 0x3B,
- 0x52, 0xE2, 0xA7, 0xFF, 0x19, 0x02, 0xCF, 0xD0,
- 0x9B, 0xD9, 0xF7, 0x28, 0x07, 0x38, 0x1F, 0xF2,
- 0xAF, 0x44, 0x91, 0x3F, 0x0F, 0xB6, 0x6E, 0x8C,
- 0xC0, 0x32, 0x92, 0xC0, 0xCD, 0x25, 0x98, 0x67,
- 0xF1, 0x47, 0x52, 0x50, 0xF0, 0xA3, 0x7B, 0xE6,
- 0x74, 0xDC, 0x72, 0x28, 0xC8, 0xAB, 0xB3, 0x31,
- 0x7D, 0xA3, 0xF7, 0xC7, 0xD1, 0xE6, 0x99, 0xB4,
- 0xB6, 0x5A, 0x3A, 0x4D, 0x83, 0x4F, 0xB8, 0xB5,
- 0x86, 0xF8, 0x37, 0x7F, 0xA0, 0x16, 0x2F, 0x3C,
- 0x62, 0x7A, 0xD4, 0x3A, 0xEB, 0xC2, 0xE8, 0x03,
- 0x49, 0x17, 0x9E, 0xFB, 0xD7, 0xAF, 0x91, 0x32,
- 0xFD, 0xEA, 0x4F, 0x64, 0xC6, 0x6E, 0x02, 0xEA,
- 0xC4, 0xC8, 0x1F, 0x16, 0xC5, 0x4C, 0xFB, 0xC5,
- 0x42, 0xF5, 0x85, 0x05, 0x92, 0x59, 0x4B, 0x31,
- 0xE5, 0xE9, 0x69, 0xE7, 0x02, 0x98, 0x33, 0xBA,
- 0x4C, 0x17, 0x09, 0xEF, 0x89, 0x20, 0xFA, 0x83,
- 0x9F, 0xAE, 0x0E, 0x1B, 0x7D, 0x98, 0xB9, 0xF2,
- 0x3C, 0x0F, 0xB7, 0x1C, 0x72, 0xDF, 0x17, 0x84,
- 0x7F, 0x0A, 0xFD, 0x12, 0x3C, 0x6F, 0x68, 0x5D,
- 0x45, 0xEB, 0xB8, 0xD6, 0x24, 0x65, 0x42, 0x75,
- 0x5C, 0xC2, 0xF3, 0x3A, 0x6A, 0x4E, 0x51, 0x34,
- 0x1B, 0xB6, 0x81, 0xB2, 0x8A, 0xEF, 0x28, 0xA4,
- 0xC5, 0x88, 0x9A, 0x97, 0xE0, 0xEF, 0x31, 0x12,
- 0x01, 0x7E, 0x1B, 0x43, 0x0F, 0x27, 0x80, 0x87,
- 0x98, 0xC5, 0xD5, 0x83, 0xCB, 0x4B, 0xB7, 0x01,
- 0x79, 0x60, 0xA1, 0x1A, 0x03, 0x05, 0xC6, 0x36,
- 0x04, 0x31, 0x3C, 0x06, 0xDB, 0x08, 0xA8, 0xDA,
- 0x8E, 0x32, 0x19, 0x91, 0xF1, 0x0D, 0x61, 0x6F,
- 0xE4, 0xB2, 0x79, 0x8A, 0xDE, 0xF4, 0xF7, 0xFB,
- 0x2C, 0x23, 0x5B, 0xD9, 0x64, 0x2F, 0xB7, 0xB3,
- 0x8B, 0xCA, 0xB8, 0x8C, 0x1D, 0x3B, 0x49, 0x05,
- 0x38, 0xA1, 0xE5, 0x8C, 0x1A, 0xDC, 0xA5, 0x61,
- 0xFE, 0xF4, 0x2B, 0xDC, 0x77, 0x28, 0xF6, 0x19,
- 0xE7, 0xB7, 0x8F, 0x4D, 0x27, 0x2D, 0xED, 0x8A,
- 0x3F, 0x3D, 0xDC, 0x9F, 0xD1, 0x30, 0xFF, 0xD6,
- 0xC3, 0xBE, 0x41, 0x25, 0xE3, 0xA5, 0x9B, 0x73,
- 0xDF, 0x6A, 0xD9, 0xF9, 0x70, 0x84, 0x02, 0x4C,
- 0x35, 0xD4, 0x3E, 0x05, 0x76, 0x3A, 0xDC, 0x6D,
- 0x5A, 0x81, 0xB3, 0x94, 0xF7, 0x22, 0xF7, 0xDC,
- 0xC1, 0x43, 0x31, 0x57, 0x5B, 0x42, 0x9A, 0x0B,
- 0xF4, 0x95, 0x30, 0xA9, 0xBB, 0xD8, 0x06, 0xFB,
- 0x1D, 0x6F, 0x9B, 0xC3, 0xBB, 0xF3, 0xBF, 0xFB,
- 0xB4, 0x9F, 0x35, 0x64, 0x0A, 0x69, 0xB7, 0xD1,
- 0x3E, 0xCA, 0x78, 0x07, 0x04, 0x03, 0x79, 0xD4,
- 0xF3, 0xA8, 0xEC, 0x18, 0xDB, 0x03, 0x5E, 0x47,
- 0xD7, 0xD0, 0x56, 0x2C, 0x74, 0x94, 0x86, 0x04,
- 0x46, 0xB8, 0xD4, 0x35, 0x0A, 0x7B, 0xE6, 0x78,
- 0xC4, 0x43, 0x3C, 0x56, 0xCC, 0x37, 0x8B, 0xFD,
- 0xE8, 0xF4, 0x57, 0xEA, 0xAE, 0xCF, 0x36, 0x97,
- 0x12, 0xAC, 0x39, 0xCF, 0x7C, 0xEF, 0x22, 0x67,
- 0x01, 0xEC, 0xD8, 0x09, 0x49, 0x4E, 0xE3, 0x74,
- 0xDD, 0x39, 0xE1, 0x39, 0xD7, 0x0C, 0x5F, 0x1B,
- 0xCE, 0x69, 0xBC, 0x72, 0x44, 0x87, 0x64, 0x1C,
- 0x08, 0x05, 0x93, 0x69, 0x6D, 0x7F, 0x90, 0x0A,
- 0x2C, 0xCB, 0x8A, 0xBB, 0x7F, 0xE3, 0xE0, 0x80,
- 0x31, 0xD0, 0x0A, 0x3A, 0x95, 0xFF, 0xF7, 0xB4,
- 0x36, 0x38, 0x93, 0xE0, 0x0C, 0x11, 0x37, 0x12,
- 0x06, 0xF6, 0xAD, 0xE9, 0xB1, 0x7A, 0x00, 0xF5,
- 0xD2, 0x32, 0x6B, 0xD0, 0x27, 0xA5, 0x1B, 0x3D,
- 0xE8, 0xDB, 0xCC, 0xA9, 0x1F, 0x1F, 0xB1, 0x99,
- 0x3D, 0x7C, 0xB7, 0xCA, 0xDA, 0x27, 0x2C, 0x64,
- 0x1C, 0x49, 0xB6, 0x87, 0x44, 0x06, 0x94, 0x9D,
- 0xBC, 0x6B, 0x20, 0xA2, 0x68, 0x15, 0x1F, 0xE2,
- 0xF2, 0xAD, 0x6D, 0x23, 0x2E, 0x2B, 0x74, 0xE2,
- 0x5D, 0xE4, 0xB0, 0xC7, 0x84, 0xCB, 0x64, 0xBF,
- 0xE0, 0xA8, 0x18, 0x83, 0xB4, 0xC9, 0xD9, 0x73,
- 0xA8, 0xE6, 0xA9, 0x36, 0xD5, 0x63, 0x1E, 0x2C,
- 0x2A, 0x55, 0x09, 0x77, 0x5E, 0xB3, 0x4B, 0xEA,
- 0xB5, 0xD0, 0x14, 0x5F, 0xEB, 0x50, 0x7B, 0xAA,
- 0xEF, 0x94, 0xBA, 0x2B, 0xD7, 0x8A, 0x07, 0xF1,
- 0xF9, 0x5E, 0x12, 0x12, 0x21, 0x52, 0xE5, 0x0A,
- 0x3E, 0xC0, 0xBC, 0x5D, 0x4C, 0xE2, 0x12, 0x7C,
- 0x39, 0xF9, 0x16, 0x9D, 0xBD, 0x96, 0x83, 0x3B,
- 0x7F, 0x3D, 0x6A, 0xEC, 0xF1, 0x25, 0xD2, 0xB0,
- 0xB0, 0xEB, 0x20, 0x06, 0x07, 0xD6, 0xD9, 0x4C,
- 0x07, 0x9A, 0x82, 0xC1, 0xFC, 0xF7, 0x66, 0x15,
- 0xBD, 0x62, 0x65, 0xD8, 0x6C, 0xF6, 0x33, 0x7B,
- 0x5A, 0x28, 0xEC, 0x90, 0xA1, 0x26, 0x9F, 0xC3,
- 0x28, 0x4A, 0x64, 0x50, 0x5F, 0xCA, 0xE2, 0x6D,
- 0xB8, 0x0F, 0xE2, 0x94, 0xB5, 0x8E, 0x1F, 0x8A,
- 0x8F, 0x6B, 0xA6, 0x86, 0x1F, 0xEE, 0xDC, 0x24,
- 0xB4, 0xB8, 0x25, 0xEC, 0x28, 0x2D, 0xF9, 0xCB,
- 0x7D, 0x38, 0xFF, 0xC7, 0x74, 0x2E, 0xD3, 0x10,
- 0xEC, 0x03, 0x31, 0xEE, 0x83, 0xE7, 0xA4, 0xF7,
- 0xBA, 0x28, 0x21, 0xE0, 0x7F, 0xB4, 0xB7, 0xE1,
- 0x7A, 0xF9, 0x2B, 0xB0, 0x2C, 0x3B, 0x80, 0x5F,
- 0xE0, 0x5D, 0xB2, 0x7E, 0x59, 0xFF, 0x59, 0x07,
- 0x58, 0x42, 0x57, 0xEE, 0x44, 0xF1, 0xB1, 0xAD,
- 0xBA, 0xDE, 0xCB, 0x1D, 0x8A, 0x36, 0x67, 0xE8,
- 0x45, 0xFF, 0x07, 0x8D, 0xEE, 0xA4, 0x51, 0x9C,
- 0x4C, 0x83, 0x5D, 0x2E, 0x2F, 0xE1, 0x5B, 0x75,
- 0xE8, 0x29, 0xCD, 0x0B, 0x07, 0x62, 0xE0, 0xC3,
- 0x0D, 0x1D, 0xEA, 0xCF, 0xF0, 0x8A, 0x65, 0x27,
- 0x70, 0x42, 0x9F, 0x26, 0x00, 0x15, 0x70, 0xC5,
- 0x4A, 0xF6, 0x25, 0xD0, 0x40, 0x72, 0xE9, 0xC1,
- 0x73, 0xFD, 0x48, 0x94, 0xA3, 0x8D, 0x66, 0x63,
- 0x96, 0x4F, 0xF7, 0xEE, 0xFB, 0x4C, 0xC7, 0xB8,
- 0x6B, 0xE9, 0x90, 0xE1, 0x2A, 0x66, 0x80, 0x99,
- 0x3B, 0xB0, 0x1A, 0x6C, 0xF9, 0x0E, 0x72, 0xDA,
- 0x8E, 0x4F, 0x46, 0xC2, 0x6A, 0x4B, 0x7A, 0x16,
- 0xE5, 0x26, 0x0B, 0x5C, 0xD4, 0x47, 0x34, 0xE5,
- 0x37, 0xBE, 0x68, 0x6C, 0xDA, 0xD3, 0x9B, 0x6F,
- 0xAE, 0x51, 0x9C, 0x99, 0x0A, 0x5B, 0xF8, 0x37,
- 0xBC, 0xDE, 0xFC, 0x93, 0xC5, 0xE7, 0x0F, 0xEF,
- 0x0B, 0xA6, 0x07, 0xC2, 0xA6, 0xE6, 0xDA, 0x2D,
- 0x1B, 0x49, 0xC9, 0xDE, 0x6B, 0x27, 0xDC, 0x00,
- 0xEF, 0x23, 0x87, 0x0E, 0xEB, 0xD1, 0x48, 0x7D,
- 0xB4, 0xF2, 0x58, 0xC6, 0x3C, 0xE2, 0x89, 0xBA,
- 0xB0, 0x05, 0xAC, 0x94, 0x41, 0x9A, 0xA8, 0xFF,
- 0x3E, 0xBC, 0x3A, 0x52, 0x9C, 0xF9, 0x7F, 0x07,
- 0x8B, 0xB0, 0x2C, 0x71, 0x83, 0x7B, 0xCF, 0x2E,
- 0x7F, 0x7C, 0x96, 0x65, 0xD9, 0x08, 0x17, 0xEC,
- 0xFA, 0xDE, 0x4E, 0x40, 0x12, 0x26, 0x70, 0x71,
- 0x65, 0xA5, 0xDC, 0x98, 0x47, 0xA3, 0xFC, 0xE0,
- 0x9A, 0x16, 0xED, 0x45, 0x56, 0x72, 0x50, 0x05,
- 0x28, 0x2C, 0x99, 0xEC, 0x20, 0x2E, 0x40, 0xC0,
- 0x26, 0x69, 0xCD, 0x49, 0x45, 0x17, 0xA4, 0xA3,
- 0x42, 0x0D, 0x14, 0x65, 0x87, 0x33, 0x8C, 0x92,
- 0xC5, 0xC4, 0x61, 0xFD, 0xE8, 0x68, 0x56, 0x20,
- 0x57, 0xF5, 0x8E, 0x5F, 0xCF, 0x7E, 0x97, 0xF6,
- 0x49, 0x97, 0x0A, 0xFE, 0xD3, 0x60, 0x1A, 0x5B,
- 0x0C, 0x75, 0xDD, 0x8E, 0x31, 0x78, 0x29, 0xA6,
- 0xB1, 0x4D, 0xAA, 0xDF, 0x8A, 0xD1, 0xE6, 0x91,
- 0xE3, 0x32, 0x3F, 0xEC, 0x8A, 0x1F, 0x0E, 0x35,
- 0x07, 0x6E, 0x4B, 0x83, 0x3B, 0xE5, 0x67, 0x34,
- 0x1F, 0x0C, 0x81, 0xD8, 0xD5, 0x25, 0x68, 0xE5,
- 0x28, 0x1B, 0x5C, 0x81, 0x3E, 0xE3, 0x5C, 0xB4,
- 0xB6, 0xBD, 0x62, 0x6A, 0x70, 0x33, 0xC2, 0xC5,
- 0x75, 0x27, 0xF4, 0x30, 0xE1, 0x1D, 0xC1, 0x4C,
- 0xC5, 0x02, 0x12, 0x46, 0xAC, 0xEC, 0xF9, 0xE8,
- 0xE7, 0x58, 0x24, 0x11, 0xB1, 0xF3, 0xB7, 0x8C,
- 0x3C, 0xA4, 0x0A, 0x94, 0xA6, 0x7C, 0x68, 0x54,
- 0x5B, 0xB9, 0x4D, 0x57, 0x9C, 0xE7, 0x28, 0x09,
- 0x6B, 0x89, 0x26, 0x5D, 0xE7, 0x50, 0xA9, 0x95,
- 0x90, 0x91, 0x8E, 0x00, 0x59, 0xF8, 0x3A, 0x70,
- 0xAF, 0x48, 0x2E, 0xE8, 0xC4, 0x34, 0x8C, 0xF4,
- 0x5F, 0x7F, 0xCB, 0x07, 0xAA, 0xF0, 0xD9, 0xFB,
- 0x5C, 0x32, 0x90, 0x22, 0x1A, 0xD2, 0x1A, 0xCF,
- 0x92, 0x06, 0x02, 0xCF, 0x10, 0x18, 0x7B, 0x93,
- 0xCC, 0x07, 0x4A, 0x31, 0x25, 0x30, 0x23, 0x06,
- 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
- 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0xD1, 0xDE,
- 0x23, 0x16, 0x9F, 0x6E, 0xF4, 0x42, 0x21, 0x23,
- 0xE1, 0x11, 0xAA, 0xC8, 0x7C, 0x60, 0x4A, 0x78,
- 0x9D, 0x24, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09,
- 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05,
- 0x00, 0x04, 0x14, 0xD6, 0x4A, 0xBB, 0x75, 0xB1,
- 0xF9, 0x9E, 0xD3, 0x58, 0x6D, 0xD1, 0x74, 0x9F,
- 0x00, 0x8A, 0xF2, 0xC8, 0xAA, 0x52, 0x4D, 0x04,
- 0x08, 0x77, 0x46, 0xE7, 0xBA, 0x25, 0x4B, 0xDA,
- 0x41, 0x02, 0x02, 0x08, 0x00]
-};
-
-const WPA_EAP_CLIENT_LIST = [
- {
- ssid: 'WPA-EAP-TLS',
- keyManagement: 'WPA-EAP',
- eap: 'TLS',
- identity: EAP_USERNAME,
- serverCertificate: CLIENT_PKCS12_CERT.nickname,
- userCertificate: CLIENT_PKCS12_CERT.nickname
- }
-];
-
-/**
- * Convert the given MozWifiNetwork object array to testAssociate chain.
- *
- * @param aNetworks
- * An array of MozWifiNetwork which we want to convert.
- *
- * @return A promise chain which "then"s testAssociate accordingly.
- */
-function convertToTestAssociateChain(aNetworks) {
- let chain = Promise.resolve();
-
- aNetworks.forEach(function (aNetwork) {
- network = new window.MozWifiNetwork(aNetwork);
- chain = chain.then(() => gTestSuite.testAssociate(network));
- });
-
- return chain;
-}
-
-gTestSuite.doTestWithCertificate(
- new Blob([new Uint8Array(CLIENT_PKCS12_CERT.content)]),
- CLIENT_PKCS12_CERT.password,
- CLIENT_PKCS12_CERT.nickname,
- CLIENT_PKCS12_CERT.usage,
- function() {
- return gTestSuite.ensureWifiEnabled(true)
- // Load required server files.
- .then(() => gTestSuite.writeFile(SERVER_EAP_USER_CONF.path, SERVER_EAP_USER_CONF.content))
- .then(() => gTestSuite.writeFile(CA_CERT.path, CA_CERT.content))
- .then(() => gTestSuite.writeFile(SERVER_CERT.path, SERVER_CERT.content))
- .then(() => gTestSuite.writeFile(SERVER_KEY.path, SERVER_KEY.content))
- // Start AP.
- .then(() => gTestSuite.startHostapds(WPA_EAP_AP_LIST))
- // Scan test.
- .then(() => gTestSuite.testWifiScanWithRetry(SCAN_RETRY_CNT, WPA_EAP_AP_LIST))
- // Associate test.
- .then(() => convertToTestAssociateChain(WPA_EAP_CLIENT_LIST))
- // Tear down.
- .then(gTestSuite.killAllHostapd)
-});
diff --git a/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_TTLS.js b/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_TTLS.js
deleted file mode 100644
index 06e052909..000000000
--- a/dom/wifi/test/marionette/test_wifi_associate_WPA_EAP_TTLS.js
+++ /dev/null
@@ -1,623 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const SCAN_RETRY_CNT = 5;
-
-const EAP_USERNAME = 'username';
-const EAP_PASSWORD = 'password';
-
-const SERVER_EAP_USER_CONF = {
- path: HOSTAPD_CONFIG_PATH + 'hostapd.eap_user',
- content: '* PEAP,TTLS,TLS\n' +
- '"' + EAP_USERNAME + '" MSCHAPV2,TTLS-MSCHAPV2 "' + EAP_PASSWORD + '" [2]\n'
-};
-const CA_CERT = {
- path: HOSTAPD_CONFIG_PATH + 'ca.pem',
- content: '-----BEGIN CERTIFICATE-----\n' +
- 'MIIDsTCCApmgAwIBAgIJAKxTf+8X8qngMA0GCSqGSIb3DQEBCwUAMG4xCzAJBgNV\n' +
- 'BAYTAlRXMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhjaHVja2xlZTER\n' +
- 'MA8GA1UEAwwIY2h1Y2tsZWUxJDAiBgkqhkiG9w0BCQEWFWNodWNrbGkwNzA2QGdt\n' +
- 'YWlsLmNvbTAgFw0xNDEyMjQxMTI4NTBaGA8yMjg4MTAwNzExMjg1MFowbjELMAkG\n' +
- 'A1UEBhMCVFcxEzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAoMCGNodWNrbGVl\n' +
- 'MREwDwYDVQQDDAhjaHVja2xlZTEkMCIGCSqGSIb3DQEJARYVY2h1Y2tsaTA3MDZA\n' +
- 'Z21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo3c2yFxY\n' +
- 'o6gGg0I83jy00ME+MAfzCd+4ShL45ZLqysQP93jRBfPzU9ZuZ29ysVwgWIdqkZao\n' +
- 'XTuV/NAW2GMGd8W1jQJ3J81fjb9wvhlny3rrACwvUn1N1S1BnM+BAAiDLGxEmvAQ\n' +
- 'onp2aaa6HsHsYS8ONX+d2Qh4LEA4vupeSGAqJychCZv/l+aq/ErFZhFYB3CPUQEt\n' +
- 'cClO24ucsIYP95lA0zhscnmAj06qplFD4Bv6IVrdDqujy1zNwCQwsJq/8OQdaTN/\n' +
- 'h3y9pWvNKMBMM2niOUAjtuNpqsSK/lTS1WAT3PdtVECX9fYBi0Bg+HM92xs/6gt6\n' +
- 'kh9jPV8keXHvSwIDAQABo1AwTjAdBgNVHQ4EFgQU7hBqhuG04xeCzrQ3ngx18ZJ3\n' +
- 'lUswHwYDVR0jBBgwFoAU7hBqhuG04xeCzrQ3ngx18ZJ3lUswDAYDVR0TBAUwAwEB\n' +
- '/zANBgkqhkiG9w0BAQsFAAOCAQEAFYX2iy680GAnBTttk0gyX6gk+8pYr3D22k/G\n' +
- '6rvcjefzS7ELQPRKr6mfmwXq3mMf/4jiS2zI5zmXsestPYzHYxf2viQ6t7vr9XiJ\n' +
- '3WfFjNw4ERlRisAvg0aqqTNNQq5v2VME4sdFZagy217f73C7azwCHl0bqOLH05rl\n' +
- '8RubOxiHEj7ZybJqnRciK/bht4D+rZkwf4bBBmoloqH7xT0+rFQclpYXDGGjNUQB\n' +
- 'LcHLF10xcr7g3ZVVu82fe6+d85gIGOIMR9+TKhdw6gO3CNcnDAj6gxksghgtcxmh\n' +
- 'OzOggCn7nlIwImtsg2sZkpWB4lEi9hdv4lkNuyFjOL3bnuc+NA==\n' +
- '-----END CERTIFICATE-----\n'
-};
-
-const SERVER_CERT = {
- path: HOSTAPD_CONFIG_PATH + 'server.pem',
- content: '-----BEGIN CERTIFICATE-----\n' +
- 'MIID1DCCArygAwIBAgIBADANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJUVzET\n' +
- 'MBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UECgwIY2h1Y2tsZWUxETAPBgNVBAMM\n' +
- 'CGNodWNrbGVlMSQwIgYJKoZIhvcNAQkBFhVjaHVja2xpMDcwNkBnbWFpbC5jb20w\n' +
- 'IBcNMTQxMjI0MTEyOTQ5WhgPMjI4ODEwMDcxMTI5NDlaMG4xCzAJBgNVBAYTAlRX\n' +
- 'MRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhjaHVja2xlZTERMA8GA1UE\n' +
- 'AwwIY2h1Y2tsZWUxJDAiBgkqhkiG9w0BCQEWFWNodWNrbGkwNzA2QGdtYWlsLmNv\n' +
- 'bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMdhQmKilTJbWZRxTiSV\n' +
- 'rqIU+LYW1RKghx5o+0JpNRJVLuz5kBMaNskbbfUSNuHbEq0QA9BDKAZWIc4LSotk\n' +
- 'lCo8TbcO9CJvJPQGGjGdHcohWX5vy6BE/OVE46CUteMFyZF6F8R2fNUww08iR/u1\n' +
- 'YZebL5pWO1j43sPpAzEy6Tij2ACPt6EZcFaZG3SF2mVJWkCQnBqrojP65WUvZQqp\n' +
- 'seUhW2YAS8Nu0Yrohgxz6VYk+cNDuDZVGs6qWRStZzJfYrfc76DtkHof5B14M+xp\n' +
- 'XJaBLxN+whvnYkDTfinaCxnW1O7eXUltr87fLc5zmeBkgwaiaQuIdcfZm7vDUiz8\n' +
- 'vnUCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH\n' +
- 'ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFKK4f9/YavTHOfEiAB83Deac\n' +
- '6gT5MB8GA1UdIwQYMBaAFO4QaobhtOMXgs60N54MdfGSd5VLMA0GCSqGSIb3DQEB\n' +
- 'CwUAA4IBAQBWnO9o9KSJIqjoz5Nwll63ULOdcvgGdOeJIw1fcKQ817Rsp+TVcjcH\n' +
- 'IrIADsT/QZGXRO/l6p1750e2iFtJEo1hsRaxtA1wWn2I9HO3+av2spQhr3jpYGPf\n' +
- 'zpsMTp4RNYV7Q8+q1kZIz9PY4V1T0p6lveK8+fUj2hSLnxSj0QiGSJJtnEC3w4Rv\n' +
- 'C9T6oUwIeToULmi+8FXQFdEqwKRU98DPq3eLzN28ZxUgoPE1C8+42D2UW8uyp/Gm\n' +
- 'tGOa/k7nzkCdVqZI7lX7f0AjEvQgjtAMQ/k7Mhxx7TzW2HO+1YPMoKji6Z4WkNwt\n' +
- 'JEj9ZUBSNt8B26UksJMBDkcvSegF3a7o\n' +
- '-----END CERTIFICATE-----\n'
-};
-
-const SERVER_KEY = {
- path: HOSTAPD_CONFIG_PATH + 'server.key',
- content: '-----BEGIN RSA PRIVATE KEY-----\n' +
- 'MIIEpAIBAAKCAQEAx2FCYqKVMltZlHFOJJWuohT4thbVEqCHHmj7Qmk1ElUu7PmQ\n' +
- 'Exo2yRtt9RI24dsSrRAD0EMoBlYhzgtKi2SUKjxNtw70Im8k9AYaMZ0dyiFZfm/L\n' +
- 'oET85UTjoJS14wXJkXoXxHZ81TDDTyJH+7Vhl5svmlY7WPjew+kDMTLpOKPYAI+3\n' +
- 'oRlwVpkbdIXaZUlaQJCcGquiM/rlZS9lCqmx5SFbZgBLw27RiuiGDHPpViT5w0O4\n' +
- 'NlUazqpZFK1nMl9it9zvoO2Qeh/kHXgz7GlcloEvE37CG+diQNN+KdoLGdbU7t5d\n' +
- 'SW2vzt8tznOZ4GSDBqJpC4h1x9mbu8NSLPy+dQIDAQABAoIBAASG4Mr8hgaurEoC\n' +
- 'iJOsElr7vunjetMBcg/uskW/vcS8ymP3Bp5oafYG+WgnEbfvEW18f5mq7K24JuxW\n' +
- 'tUqU7ghHdjxByqk9fMlNmiqmNpbwSufkAeuRpWxPNBvhRH/zEbCL5R5A0nTEtqqF\n' +
- 'TL0aUSzwCRSoAJD0lZo9ICVt0n3GsDyM9rqQg/uZmh1qsRdwPsRuYORND9g48rKq\n' +
- '6WN9leskSxhhsYE2D9ocOFd9bNt8Zxejh9ppVSnG/KsIdt18iBzcabatgAQ046fb\n' +
- 'Z3vprcZJLg93Sg2gSuVqlSTs3M2W8VQnm22/EBMb1y0M48MSRCgnbPLG/CcCLLfF\n' +
- 'LwxCOgECgYEA/eYt67xyJ6JeAdxdwOZuT1WWGbFpLiG9+2OgiHumyRQ5969XMTWo\n' +
- 'fIhMKchDdjoy9RR236\/\/EFCs7UEyB7+a7ODRzNiK2zCD8Smjp+21fUPSthEeQesk\n' +
- 'eiMYICIu5Ay35x9sxIX+XOUVvRhPOGcD29GVeRnKh1inTHOz2dje8LkCgYEAyQeY\n' +
- 'STi9jjCEcHkM1E/UeDiLfHHepLXi8wS41JNRHl5Jacp7XB5djAjKu/jf367/VpFy\n' +
- 'GDDMetE7n8eWkrnAvovxOwZ000YDMtL1sUYSjL+XtBS5s6VY1p4qaSAY9nUUGrJh\n' +
- 'JvtvsuI7SKTtL+60vjBOH7zDnvOdBgAp0utLhZ0CgYEAuLzzqrPKB8afShFSchn4\n' +
- 'J2dpuLYahsNsXW7HDqeR2nsKFosRETAusLXnXPtnAq4kB6jlOarwFqnsuRCX24Vx\n' +
- 'r2uBm9/vYL7zMdUPTA+s30ErHuhjsKjsOKYyVqcooSwT32pBFNk+E89nutfmRG7I\n' +
- 'IvhjHuNCNqqtx/Xj5d1jkZkCgYBQicppC2Jl5OoqZVTOem0U/RJk+PnJ41TZJ7sk\n' +
- '7yBAmmWvDH\/\/l+rCf4M5a6vFYcbKV9rt9h711X2dtciNX/3oWQh8LUoAmrwNUJc+\n' +
- 'PmSQHvIYI3WCk2vUD+nN1B4sHxu+1lg11eYaNKiroeeknG2tBI1ICcgVlmQCU25u\n' +
- 'IfZPwQKBgQCdO6QHhPLtcHUDNFA6FQ1jKL1iEd7G0JLVRz4Xkpkn1Vrr5MD6JFDa\n' +
- '5ccabADyl0lpFqDIVJQIzLku2hOD2i9aBNCY0pL391HeOS7CkZX+TdOY1tquoBq5\n' +
- 'MnmixZjDCVd2VcrVyTA6ntOBoharKFW0rH1PqU+qu7dZF7CBPbAdEw==\n' +
- '-----END RSA PRIVATE KEY-----\n'
-};
-
-const WPA_EAP_AP_LIST = [
- {
- ssid: 'WPA-EAP-TTLS',
- ieee8021x: 1,
- eapol_version: 1,
- eap_server: 1,
- eapol_key_index_workaround: 0,
- eap_user_file: SERVER_EAP_USER_CONF.path,
- ca_cert: CA_CERT.path,
- server_cert: SERVER_CERT.path,
- private_key: SERVER_KEY.path,
- wpa: 3,
- wpa_key_mgmt: 'WPA-EAP'
- }
-];
-
-const CLIENT_PKCS12_CERT = {
- nickname: 'client',
- password: 'password',
- usage: ['UserCert', 'ServerCert'],
- content: [0x30, 0x82, 0x0E, 0x01, 0x02, 0x01, 0x03, 0x30,
- 0x82, 0x0D, 0xC7, 0x06, 0x09, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82,
- 0x0D, 0xB8, 0x04, 0x82, 0x0D, 0xB4, 0x30, 0x82,
- 0x0D, 0xB0, 0x30, 0x82, 0x08, 0x67, 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07,
- 0x06, 0xA0, 0x82, 0x08, 0x58, 0x30, 0x82, 0x08,
- 0x54, 0x02, 0x01, 0x00, 0x30, 0x82, 0x08, 0x4D,
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x07, 0x01, 0x30, 0x1C, 0x06, 0x0A, 0x2A,
- 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01,
- 0x06, 0x30, 0x0E, 0x04, 0x08, 0x67, 0x7A, 0xF3,
- 0x61, 0xBE, 0xE0, 0x51, 0xC1, 0x02, 0x02, 0x08,
- 0x00, 0x80, 0x82, 0x08, 0x20, 0xFC, 0x6A, 0x79,
- 0xA1, 0x6C, 0xAF, 0xBE, 0xEE, 0x62, 0x45, 0x33,
- 0xB8, 0x48, 0xE1, 0x68, 0xA1, 0x15, 0x11, 0x4B,
- 0x95, 0xCB, 0x77, 0xC0, 0x5D, 0xA2, 0xCB, 0xDB,
- 0xD1, 0x83, 0x74, 0x60, 0xD7, 0xEC, 0x42, 0xA6,
- 0x3A, 0x23, 0xF7, 0x85, 0xEB, 0xC1, 0xFE, 0x6A,
- 0x57, 0x8E, 0xC1, 0x44, 0xF3, 0x1F, 0xFE, 0xB8,
- 0x2D, 0x8C, 0x4D, 0xC9, 0x5B, 0xAE, 0x21, 0x2E,
- 0x4C, 0x1A, 0xEB, 0x84, 0x09, 0xF3, 0x40, 0x92,
- 0x39, 0x7F, 0x56, 0x02, 0x46, 0x61, 0x16, 0xDE,
- 0x5C, 0x48, 0xB6, 0x0C, 0x1D, 0xD3, 0x5F, 0x10,
- 0x9A, 0x39, 0xB8, 0x66, 0x31, 0xFC, 0x39, 0x71,
- 0x87, 0x23, 0x46, 0x9D, 0xE8, 0x3C, 0x2B, 0xA1,
- 0x39, 0x8A, 0xD3, 0xFF, 0xD9, 0x43, 0xB6, 0x61,
- 0xC6, 0x67, 0x70, 0x40, 0xBD, 0xFE, 0xD3, 0xC1,
- 0x68, 0xF5, 0xF7, 0xC8, 0x89, 0xD8, 0x17, 0xC5,
- 0xE8, 0x3D, 0x29, 0xD5, 0x91, 0xDF, 0x1F, 0x56,
- 0x74, 0x5A, 0xC4, 0xA8, 0x14, 0xBA, 0xD4, 0xFA,
- 0x13, 0x49, 0x2A, 0x9F, 0x63, 0xF1, 0xB2, 0x45,
- 0xF1, 0xF0, 0x2A, 0xDD, 0x75, 0x66, 0x8A, 0xF7,
- 0xAB, 0x73, 0x86, 0x26, 0x9D, 0x1F, 0x07, 0xAD,
- 0xD3, 0xFE, 0xE0, 0xA3, 0xED, 0xA0, 0x96, 0x3E,
- 0x1E, 0x89, 0x86, 0x02, 0x4C, 0x28, 0xFD, 0x57,
- 0xA1, 0x67, 0x55, 0xF0, 0x82, 0x3B, 0x7F, 0xCC,
- 0x2A, 0x32, 0x01, 0x93, 0x1D, 0x8B, 0x66, 0x8A,
- 0x20, 0x52, 0x84, 0xDD, 0x2C, 0xFD, 0xEE, 0x72,
- 0xF3, 0x8C, 0x58, 0xB9, 0x99, 0xE5, 0xC1, 0x22,
- 0x63, 0x59, 0x00, 0xE2, 0x76, 0xC5, 0x3A, 0x17,
- 0x7F, 0x93, 0xE9, 0x67, 0x61, 0xAA, 0x10, 0xC3,
- 0xD9, 0xC8, 0x24, 0x46, 0x5B, 0xBE, 0x8C, 0x1F,
- 0x2D, 0x66, 0x48, 0xD2, 0x02, 0x11, 0xFB, 0x74,
- 0x14, 0x76, 0x76, 0x5A, 0x98, 0x54, 0x35, 0xA7,
- 0x85, 0x66, 0x20, 0x26, 0x8B, 0x13, 0x6F, 0x68,
- 0xE3, 0xC9, 0x58, 0x7D, 0x1C, 0x3E, 0x01, 0x8D,
- 0xF8, 0xD6, 0x7F, 0xCF, 0xA2, 0x07, 0xB7, 0x95,
- 0xFD, 0xF0, 0x02, 0x34, 0x32, 0x30, 0xE8, 0xD4,
- 0x57, 0x5E, 0x53, 0xFB, 0x54, 0xE2, 0x03, 0x32,
- 0xCC, 0x52, 0x2E, 0xD2, 0x35, 0xD9, 0x58, 0x85,
- 0x2D, 0xEC, 0x2D, 0x71, 0xD1, 0x8A, 0x29, 0xD0,
- 0xB0, 0x24, 0xBD, 0x24, 0xDC, 0x1A, 0x28, 0x3F,
- 0xA0, 0x12, 0x81, 0x15, 0x24, 0xC9, 0xB5, 0x4A,
- 0x23, 0xB6, 0xA3, 0x45, 0x50, 0x2D, 0x73, 0x99,
- 0x6B, 0x1C, 0xFB, 0xA4, 0x53, 0xD7, 0x5C, 0xF4,
- 0x6C, 0xB0, 0xE5, 0x74, 0xB3, 0x76, 0xF8, 0xB1,
- 0x0D, 0x59, 0x70, 0x9F, 0xCA, 0xDE, 0xF2, 0xAA,
- 0x4C, 0x7D, 0x11, 0x54, 0xC4, 0x19, 0x0F, 0x36,
- 0x4A, 0x62, 0xFF, 0x8B, 0x10, 0xCB, 0x93, 0x50,
- 0xDA, 0x79, 0x5E, 0x4E, 0x09, 0x1F, 0x22, 0xC8,
- 0x19, 0x85, 0xE9, 0xEE, 0xB7, 0x71, 0x65, 0xB9,
- 0x10, 0xD2, 0x0A, 0x73, 0x5B, 0xA6, 0xDA, 0x37,
- 0x46, 0x02, 0x00, 0x98, 0x9E, 0x20, 0x6C, 0x7D,
- 0xC7, 0x69, 0xBB, 0xC2, 0x00, 0x40, 0x9C, 0x57,
- 0x00, 0xC2, 0x36, 0x76, 0xE8, 0x2A, 0x8D, 0xAD,
- 0x62, 0x57, 0xC8, 0xD0, 0x9D, 0x66, 0x27, 0x5A,
- 0xD8, 0x0D, 0x35, 0x60, 0x28, 0x38, 0x62, 0x94,
- 0x78, 0x36, 0x25, 0x58, 0xFD, 0xF8, 0x66, 0x1F,
- 0x68, 0x04, 0x0F, 0xD8, 0x00, 0xDF, 0xA0, 0x6C,
- 0x25, 0x42, 0x9A, 0x4C, 0xEB, 0x80, 0x13, 0x51,
- 0x7D, 0x2D, 0xA8, 0x89, 0xD6, 0x1B, 0x67, 0x72,
- 0x01, 0xF3, 0x2D, 0x16, 0x77, 0xFE, 0x22, 0xBC,
- 0x8A, 0x45, 0x09, 0x1F, 0x9C, 0x2F, 0x2A, 0xA9,
- 0x61, 0x5B, 0x4A, 0xE6, 0x64, 0x2C, 0x62, 0x1A,
- 0x3A, 0x96, 0xE6, 0x0A, 0xAE, 0x05, 0x1A, 0xC8,
- 0xCB, 0xD6, 0x8F, 0x3A, 0x4B, 0xE0, 0x7F, 0x82,
- 0xB4, 0x98, 0xF1, 0x9D, 0xD7, 0x14, 0x76, 0x5E,
- 0x77, 0x85, 0x87, 0xEC, 0x13, 0xDA, 0xFD, 0xAF,
- 0xCB, 0xA3, 0x1C, 0x99, 0xC1, 0xFE, 0x17, 0x0C,
- 0x40, 0x4D, 0x3C, 0x8F, 0x70, 0x86, 0x63, 0x64,
- 0xB7, 0x75, 0xA8, 0x71, 0x36, 0xDC, 0x54, 0x10,
- 0x57, 0x0C, 0xA8, 0xF2, 0xA1, 0xBB, 0xED, 0x03,
- 0x41, 0x57, 0x34, 0x2C, 0x8F, 0x7C, 0xA0, 0x09,
- 0xF3, 0x9E, 0x41, 0xB7, 0xA8, 0xD4, 0x66, 0x0D,
- 0x0D, 0xC0, 0x6A, 0xFC, 0x6A, 0xA2, 0xAC, 0xE2,
- 0x60, 0x00, 0xE3, 0xF7, 0x75, 0x43, 0x23, 0xEB,
- 0xC8, 0x61, 0xFA, 0xB3, 0xB8, 0x28, 0xCE, 0xCA,
- 0xF4, 0x47, 0x7F, 0x30, 0x6D, 0x61, 0x89, 0x47,
- 0xA1, 0x4A, 0xFE, 0xD1, 0x21, 0x0B, 0x6D, 0xF4,
- 0x3F, 0x00, 0x86, 0x30, 0x8E, 0x33, 0x21, 0x6F,
- 0xDA, 0x15, 0xFD, 0x5F, 0xEC, 0x8E, 0xF1, 0x12,
- 0x3F, 0xC9, 0x83, 0x0C, 0xCA, 0x22, 0x01, 0xF1,
- 0x70, 0x5F, 0x1F, 0x66, 0xB5, 0xF8, 0x3E, 0x7A,
- 0x6F, 0xDE, 0xDB, 0xA7, 0x8D, 0x18, 0x9E, 0xBE,
- 0xDB, 0xAD, 0x3D, 0x66, 0x30, 0xC1, 0x6C, 0x0C,
- 0x87, 0xB4, 0x65, 0x75, 0xE0, 0x9D, 0xEA, 0x16,
- 0x0D, 0x07, 0x37, 0x33, 0xC5, 0xEC, 0x97, 0x93,
- 0x37, 0xEB, 0x8E, 0x65, 0x9C, 0x40, 0x63, 0x6C,
- 0x43, 0x60, 0xB0, 0x40, 0x4D, 0x85, 0xEF, 0xC2,
- 0x47, 0x5F, 0xE7, 0x6B, 0xCB, 0x40, 0xE8, 0xEA,
- 0xD8, 0xAB, 0xB1, 0x9A, 0x72, 0xDC, 0x4C, 0x14,
- 0xFA, 0x43, 0x61, 0x5F, 0xA6, 0x5C, 0x3A, 0x05,
- 0x17, 0x2E, 0x74, 0xF3, 0x5E, 0x45, 0xD9, 0x47,
- 0xAA, 0x59, 0xB6, 0x8F, 0x42, 0x66, 0x42, 0x29,
- 0x90, 0x95, 0x48, 0x46, 0x91, 0x88, 0x3C, 0x8C,
- 0xDE, 0xCC, 0xED, 0xB3, 0xAA, 0x62, 0xEA, 0xBC,
- 0xB4, 0x0C, 0x48, 0x4C, 0x53, 0x23, 0x5E, 0x24,
- 0x85, 0xBF, 0x92, 0xDA, 0x14, 0xDB, 0x1A, 0x3D,
- 0xEF, 0x30, 0xD9, 0x49, 0x64, 0x4D, 0xE5, 0x01,
- 0xFC, 0xA4, 0x4B, 0xD1, 0x9F, 0xDE, 0x96, 0x7F,
- 0x50, 0xBC, 0x4D, 0x38, 0x44, 0xE9, 0x23, 0x5F,
- 0x37, 0x57, 0x1A, 0xA6, 0x52, 0x5A, 0x0F, 0x4F,
- 0x87, 0x33, 0x4A, 0x7B, 0x66, 0xEE, 0x3D, 0x66,
- 0x0A, 0x63, 0x39, 0x1F, 0x23, 0x38, 0x35, 0x73,
- 0x60, 0x5E, 0x47, 0x20, 0x4F, 0xC0, 0xC8, 0x3C,
- 0x09, 0xF9, 0x29, 0x4F, 0x5E, 0x55, 0x69, 0xC4,
- 0x6B, 0xE8, 0xF8, 0x91, 0xC0, 0x22, 0x65, 0x15,
- 0x1E, 0xFB, 0xB9, 0x61, 0xCE, 0x45, 0xBE, 0x2B,
- 0xEE, 0xB9, 0x04, 0x2B, 0xFD, 0xAE, 0x61, 0x1C,
- 0x3D, 0x3D, 0x7C, 0xBF, 0xC1, 0xF7, 0x3C, 0x4E,
- 0x9E, 0x0E, 0x54, 0xC8, 0xAD, 0xA9, 0xDF, 0x43,
- 0x49, 0xB9, 0x41, 0x05, 0xE5, 0xF1, 0x49, 0xAA,
- 0x77, 0x6C, 0x34, 0x5B, 0x93, 0x24, 0x24, 0x23,
- 0x74, 0x68, 0x11, 0xCE, 0x15, 0x80, 0xA1, 0xA4,
- 0x1F, 0x8D, 0x81, 0xCD, 0xB2, 0x98, 0xCA, 0x14,
- 0x0B, 0x0C, 0x61, 0x50, 0x69, 0x72, 0xAE, 0xFA,
- 0x8B, 0xC0, 0x3F, 0x0D, 0xE7, 0xF2, 0x0F, 0xEB,
- 0xC1, 0x11, 0xB9, 0x10, 0x03, 0x6A, 0xF5, 0x97,
- 0x3C, 0x53, 0x2F, 0x67, 0x86, 0x09, 0x6A, 0xE3,
- 0x28, 0xC0, 0x78, 0xC8, 0xB4, 0x39, 0x8E, 0xD1,
- 0xCE, 0x25, 0xE8, 0x66, 0xF7, 0x09, 0x40, 0x7D,
- 0x81, 0xFB, 0xAF, 0xFA, 0x59, 0xC4, 0x9B, 0x2B,
- 0x83, 0x45, 0x5B, 0xA8, 0x66, 0x9E, 0x38, 0xC8,
- 0xFD, 0xAC, 0xF2, 0x2D, 0x21, 0xDE, 0x50, 0x4C,
- 0x03, 0xCB, 0x88, 0x42, 0xDD, 0x84, 0x09, 0x99,
- 0x8E, 0x8B, 0x40, 0x97, 0x1B, 0x14, 0x85, 0x37,
- 0x11, 0x01, 0xE0, 0x74, 0x6B, 0x33, 0x52, 0x8C,
- 0x68, 0x3A, 0x89, 0xB2, 0xAF, 0x35, 0xE6, 0x65,
- 0xC3, 0x58, 0x70, 0xD2, 0xE7, 0x1F, 0x1F, 0xF6,
- 0xE5, 0x0A, 0xB1, 0xFE, 0xD0, 0xC9, 0x51, 0x50,
- 0xE7, 0xFD, 0x58, 0xF5, 0xC4, 0x58, 0x65, 0x94,
- 0xD1, 0x57, 0x55, 0x5E, 0xD2, 0x27, 0x98, 0xAF,
- 0xE7, 0x55, 0x0B, 0x87, 0x50, 0x9B, 0xEF, 0xE8,
- 0x2B, 0xFC, 0xE7, 0x3B, 0x4E, 0xD7, 0xB7, 0x4D,
- 0xF4, 0xBC, 0xF4, 0x88, 0x63, 0xE4, 0x8A, 0x20,
- 0x4B, 0x22, 0xB0, 0xA0, 0x53, 0x7F, 0xA8, 0xC9,
- 0x0C, 0xF8, 0xD7, 0xBD, 0x46, 0x39, 0xA7, 0x7D,
- 0xDD, 0x10, 0x91, 0x50, 0x54, 0x06, 0x47, 0xF0,
- 0x3C, 0xAA, 0x43, 0x40, 0xF8, 0x54, 0xDD, 0x8A,
- 0xEA, 0x8A, 0x0B, 0xA5, 0x7F, 0xCD, 0x5E, 0xAA,
- 0x02, 0x2E, 0x1F, 0xC6, 0x50, 0x15, 0xF8, 0x0A,
- 0x0C, 0x1B, 0x3C, 0x55, 0x3A, 0xC3, 0x6F, 0x88,
- 0xD7, 0xBF, 0xB1, 0x02, 0xCC, 0xE0, 0x08, 0x29,
- 0x97, 0xD2, 0xAA, 0x23, 0xC4, 0x6D, 0xE3, 0xE3,
- 0x76, 0x39, 0x92, 0xC3, 0x2E, 0x7A, 0xE2, 0x98,
- 0xD1, 0xFC, 0xAE, 0xCC, 0x95, 0xD8, 0xB4, 0xDC,
- 0x92, 0xEA, 0x6A, 0x5F, 0xF2, 0x92, 0x17, 0x0B,
- 0x8D, 0xC3, 0xFA, 0x9C, 0x62, 0xCE, 0x44, 0x8D,
- 0xC3, 0x1E, 0xC3, 0xB2, 0xD5, 0x00, 0xCD, 0xB4,
- 0x9E, 0x2D, 0x7B, 0xF2, 0x98, 0xA3, 0x00, 0x8B,
- 0x81, 0x30, 0x77, 0x5B, 0x02, 0x99, 0xB1, 0xCD,
- 0xC3, 0x1D, 0x74, 0x74, 0xEF, 0x41, 0xCB, 0x69,
- 0x63, 0x8E, 0xA6, 0xD3, 0x2D, 0x3E, 0x1F, 0x1D,
- 0x12, 0x9E, 0xD9, 0x18, 0x67, 0x06, 0xAF, 0x37,
- 0x29, 0xAD, 0x65, 0xD8, 0xEB, 0x71, 0xC4, 0x7D,
- 0x94, 0x3D, 0xEA, 0xCC, 0xDF, 0x72, 0x41, 0x51,
- 0x3C, 0xA1, 0x66, 0x98, 0x32, 0x32, 0x40, 0x54,
- 0xB0, 0x2F, 0xEB, 0xCE, 0xDF, 0x4A, 0x64, 0xFB,
- 0x9A, 0x90, 0xDC, 0xF6, 0x6F, 0xA9, 0xD4, 0xCA,
- 0xCB, 0x91, 0xC4, 0xFE, 0xEE, 0x9C, 0x01, 0x50,
- 0x2E, 0xAC, 0xCC, 0x5F, 0x89, 0xD0, 0x91, 0xA3,
- 0xD9, 0xF9, 0x4B, 0x8D, 0xDE, 0x6C, 0x60, 0x21,
- 0x19, 0xB1, 0xD3, 0x4D, 0x75, 0x56, 0x6F, 0xB8,
- 0x25, 0xA4, 0x92, 0x4F, 0x12, 0xF5, 0x8F, 0xC1,
- 0x17, 0x4B, 0xB3, 0x34, 0x21, 0x22, 0xAC, 0x52,
- 0xD2, 0x64, 0xC9, 0x9A, 0x7D, 0xFC, 0xC0, 0x0A,
- 0x89, 0x34, 0xFF, 0x08, 0xD3, 0x04, 0xDC, 0xFE,
- 0x7C, 0xB3, 0xB8, 0xFD, 0x85, 0xDD, 0x79, 0x51,
- 0xA7, 0x89, 0xE8, 0xF1, 0x23, 0xB1, 0xDF, 0xD7,
- 0x1F, 0x7B, 0xB1, 0x5D, 0x42, 0xF9, 0x61, 0xF8,
- 0xDC, 0x81, 0x04, 0xF1, 0xCC, 0xFA, 0xD7, 0xED,
- 0xBF, 0x47, 0xAC, 0xBD, 0xE5, 0xFA, 0xAC, 0xB3,
- 0x1C, 0xD9, 0xA1, 0xB3, 0x60, 0xEE, 0x9C, 0x8A,
- 0x36, 0x57, 0xB4, 0x2F, 0xA1, 0xA2, 0xF3, 0xE2,
- 0x09, 0x9A, 0x6E, 0x43, 0x9B, 0xE5, 0x93, 0xB8,
- 0x3D, 0x9E, 0x9F, 0xC1, 0xC6, 0x0D, 0x02, 0xEB,
- 0x4D, 0x38, 0xE9, 0xB4, 0x9F, 0xEA, 0x33, 0x8C,
- 0x07, 0xD8, 0xB4, 0x71, 0xAD, 0xE5, 0x43, 0xB2,
- 0xCC, 0x55, 0x93, 0x6A, 0xDB, 0x1E, 0x80, 0xDB,
- 0xC2, 0xEA, 0x42, 0x8E, 0xFC, 0x86, 0x44, 0xC9,
- 0x8A, 0xC4, 0xF2, 0x46, 0xA7, 0x39, 0x50, 0x0D,
- 0x1A, 0xAA, 0x07, 0x04, 0xBE, 0xD4, 0xCE, 0x62,
- 0x4D, 0x0F, 0x91, 0x7D, 0x29, 0x88, 0x9C, 0x4C,
- 0xAF, 0xF7, 0xD8, 0x40, 0x93, 0x88, 0xC7, 0x20,
- 0xD2, 0x17, 0x2A, 0xC4, 0x92, 0x72, 0xD0, 0xC0,
- 0x4E, 0x56, 0x47, 0xB1, 0x27, 0x02, 0xE6, 0x61,
- 0x82, 0x5E, 0xC8, 0x2E, 0x90, 0xD2, 0x31, 0x22,
- 0xE2, 0xA9, 0x4A, 0x91, 0x45, 0x69, 0xB1, 0xA5,
- 0x0F, 0x66, 0x2C, 0x30, 0xAD, 0x7F, 0x1B, 0x0E,
- 0x22, 0x17, 0x60, 0x2E, 0x3D, 0x7F, 0x7F, 0x8C,
- 0x33, 0x51, 0xA0, 0x25, 0xDE, 0xFD, 0x75, 0xBC,
- 0xEF, 0xE6, 0xE7, 0x20, 0x04, 0x5A, 0xEC, 0x50,
- 0x21, 0x48, 0x56, 0x98, 0xE2, 0x33, 0x6D, 0x22,
- 0x5C, 0xC3, 0xFB, 0xFC, 0x6F, 0xB3, 0xA7, 0x8E,
- 0x6F, 0x67, 0x70, 0x9D, 0xDA, 0x02, 0x01, 0x59,
- 0x7B, 0x3D, 0x2B, 0x38, 0xCC, 0x0F, 0x44, 0x3D,
- 0xFB, 0x9A, 0xB3, 0x23, 0x15, 0x50, 0x6E, 0xBF,
- 0x8B, 0xA1, 0x94, 0x33, 0xE5, 0x7B, 0x88, 0x4E,
- 0xCB, 0x6D, 0x9F, 0xBF, 0xBC, 0x7A, 0xA8, 0x1E,
- 0x68, 0x25, 0xED, 0x8E, 0x53, 0x21, 0x72, 0xC5,
- 0x70, 0xB3, 0xE4, 0xA6, 0xA1, 0x5A, 0x2D, 0xC8,
- 0x43, 0x9D, 0x60, 0x77, 0x78, 0xE0, 0xC4, 0xAF,
- 0xC8, 0x29, 0xBA, 0xD0, 0x4D, 0x39, 0x83, 0x51,
- 0xA7, 0x10, 0x7F, 0x0C, 0x34, 0x0E, 0x6C, 0x75,
- 0x26, 0xD7, 0xD6, 0xC7, 0x32, 0x53, 0xAF, 0x4E,
- 0xBE, 0xF2, 0xC2, 0x0F, 0x99, 0x23, 0xB9, 0xE1,
- 0xC8, 0xB4, 0xBC, 0x5A, 0xC6, 0xCB, 0xEB, 0x4D,
- 0x28, 0x56, 0x72, 0xFE, 0x1B, 0x2C, 0x5D, 0xE3,
- 0xBC, 0xC7, 0xA3, 0xC0, 0x7D, 0x27, 0xF0, 0xD0,
- 0x4F, 0x3F, 0x1F, 0xF7, 0x87, 0x15, 0xF2, 0xEA,
- 0xD4, 0x03, 0x6D, 0x2F, 0xD4, 0x8E, 0x50, 0x4B,
- 0x05, 0xBF, 0xF7, 0x8C, 0x67, 0x5A, 0xDC, 0x4D,
- 0xCD, 0xCF, 0x9D, 0x02, 0xB6, 0xE7, 0xAE, 0x49,
- 0xD1, 0x7C, 0x00, 0xE7, 0x3B, 0xEA, 0xFB, 0x0D,
- 0x2A, 0x7B, 0x41, 0x33, 0x66, 0xD0, 0x29, 0x9F,
- 0xB3, 0x8A, 0x71, 0xB0, 0xE2, 0x76, 0xA9, 0xDB,
- 0xFD, 0x64, 0x04, 0x69, 0xDF, 0x89, 0x1F, 0x56,
- 0x86, 0x92, 0xD9, 0xD9, 0xB9, 0xF3, 0x4F, 0xAC,
- 0xAE, 0x61, 0x48, 0x20, 0xCE, 0x3C, 0x2B, 0x44,
- 0xAB, 0x42, 0xFA, 0xAB, 0x2E, 0x94, 0x82, 0xC8,
- 0xD9, 0x97, 0xCF, 0x27, 0xDF, 0xAC, 0xAC, 0xE7,
- 0xCA, 0xB2, 0x84, 0xAB, 0xF2, 0x5D, 0xDF, 0x56,
- 0x0C, 0x8C, 0x07, 0x3C, 0x3D, 0xA8, 0xDD, 0xBE,
- 0xFF, 0x4E, 0x28, 0x0D, 0xB2, 0x2D, 0xE6, 0x9D,
- 0x44, 0x21, 0xCB, 0xE7, 0x33, 0x63, 0x22, 0x8F,
- 0x4C, 0xFF, 0xB6, 0x1D, 0x9A, 0x71, 0x3F, 0xB1,
- 0x29, 0xAE, 0x3A, 0x35, 0xEE, 0x9C, 0x97, 0x68,
- 0xA7, 0x52, 0x66, 0x01, 0xD8, 0x9A, 0x5D, 0xF4,
- 0xB3, 0x2F, 0x5C, 0xD4, 0x0E, 0xF9, 0xCF, 0x07,
- 0xF6, 0x8C, 0xBA, 0xA6, 0x8D, 0x6B, 0xC6, 0x01,
- 0xC2, 0x69, 0xAE, 0x60, 0x08, 0x1A, 0x0E, 0x3F,
- 0xAE, 0x60, 0x29, 0xF3, 0x48, 0x0D, 0xE0, 0xD0,
- 0xAE, 0x52, 0x44, 0xE9, 0x7F, 0x1F, 0x92, 0x5F,
- 0x71, 0xAD, 0xEC, 0x6B, 0x47, 0x66, 0x92, 0x22,
- 0x27, 0xAE, 0x6E, 0x25, 0xCD, 0xF3, 0x5F, 0x55,
- 0x59, 0xBD, 0x73, 0xCE, 0x2B, 0x7E, 0x99, 0x44,
- 0x56, 0x70, 0xA3, 0xE7, 0x7A, 0x59, 0x75, 0xD8,
- 0x48, 0x0C, 0x39, 0x2B, 0xD7, 0x53, 0xC6, 0xAD,
- 0x4A, 0x6F, 0xB4, 0x14, 0x96, 0xDF, 0xF2, 0x4A,
- 0x0C, 0xA2, 0xD5, 0x29, 0x98, 0x7C, 0x42, 0x87,
- 0xD9, 0x1F, 0x97, 0x61, 0xD9, 0xBF, 0x99, 0x4F,
- 0x2C, 0x4C, 0x75, 0xAC, 0xB8, 0x06, 0x75, 0xD6,
- 0x87, 0x76, 0x7E, 0xE3, 0x23, 0x4B, 0xEA, 0x1A,
- 0x1A, 0xF4, 0xB7, 0x09, 0xAF, 0x53, 0xEB, 0xA6,
- 0x39, 0x10, 0xFE, 0xD4, 0xEB, 0x1B, 0xAE, 0x38,
- 0x31, 0x33, 0xBA, 0x68, 0xEE, 0xC7, 0x65, 0x76,
- 0xFB, 0x49, 0x77, 0xD4, 0x19, 0xC4, 0xE6, 0xA7,
- 0x05, 0xFE, 0x2A, 0xDA, 0x39, 0x99, 0x1A, 0x92,
- 0xD2, 0xF0, 0x61, 0x97, 0xF6, 0x06, 0x6C, 0x88,
- 0x7B, 0x6F, 0x60, 0xE6, 0x70, 0x08, 0xF0, 0xB4,
- 0x6B, 0x39, 0x6F, 0x05, 0x41, 0x81, 0xF9, 0xBE,
- 0x7A, 0x51, 0xC4, 0x75, 0xB0, 0x6A, 0x89, 0xA0,
- 0xA6, 0x9A, 0x5B, 0xEE, 0x7D, 0x78, 0x17, 0x5F,
- 0x9F, 0x3B, 0x7D, 0xDD, 0x8A, 0x9E, 0xAA, 0x1A,
- 0xDA, 0x49, 0x08, 0xE9, 0xFD, 0x91, 0xA6, 0xFA,
- 0xCE, 0xCF, 0x67, 0xDF, 0x0F, 0xC9, 0xD6, 0x38,
- 0xD9, 0xD5, 0xD1, 0xC0, 0x76, 0x59, 0x42, 0x53,
- 0xBF, 0x48, 0xE9, 0x11, 0x74, 0xC7, 0x11, 0xD8,
- 0xE7, 0x8E, 0xD3, 0xC8, 0x25, 0xA1, 0x26, 0x50,
- 0xBB, 0xB4, 0x35, 0xAF, 0xAF, 0x06, 0x23, 0x69,
- 0x3E, 0x30, 0xFD, 0x7B, 0x34, 0x83, 0x07, 0xD0,
- 0xF0, 0x0F, 0x6C, 0x9A, 0x13, 0x5D, 0xC2, 0x7B,
- 0xDF, 0x6F, 0xDD, 0x8E, 0xF4, 0x30, 0x82, 0x05,
- 0x41, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x05, 0x32,
- 0x04, 0x82, 0x05, 0x2E, 0x30, 0x82, 0x05, 0x2A,
- 0x30, 0x82, 0x05, 0x26, 0x06, 0x0B, 0x2A, 0x86,
- 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01,
- 0x02, 0xA0, 0x82, 0x04, 0xEE, 0x30, 0x82, 0x04,
- 0xEA, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30,
- 0x0E, 0x04, 0x08, 0x74, 0xC0, 0x84, 0x8F, 0xC7,
- 0x74, 0x5E, 0x21, 0x02, 0x02, 0x08, 0x00, 0x04,
- 0x82, 0x04, 0xC8, 0x1E, 0xF4, 0xE9, 0x07, 0x27,
- 0x9E, 0x5A, 0xC9, 0x39, 0x1D, 0x37, 0x2C, 0x06,
- 0x4B, 0x57, 0xEA, 0xC5, 0x42, 0x9A, 0x60, 0xD5,
- 0x42, 0xB2, 0x34, 0x2D, 0xD3, 0x88, 0x7C, 0x78,
- 0x87, 0xB6, 0xE9, 0x42, 0x44, 0x1F, 0x67, 0x32,
- 0x92, 0x54, 0x22, 0xDA, 0xB2, 0x43, 0xE7, 0x40,
- 0xBE, 0x1F, 0xAF, 0x3A, 0xCD, 0x2A, 0x9F, 0xD7,
- 0x44, 0x5B, 0x37, 0x69, 0x85, 0xDF, 0xEB, 0x2A,
- 0xB9, 0xE2, 0x92, 0x3B, 0xEA, 0xD5, 0x42, 0x53,
- 0x95, 0x4A, 0xB0, 0x1B, 0xA5, 0xEF, 0xA6, 0x0D,
- 0x29, 0xF4, 0x33, 0xFE, 0xD7, 0x49, 0x04, 0x1E,
- 0x8C, 0xAD, 0x63, 0x1E, 0x79, 0x63, 0x74, 0x0C,
- 0xE5, 0x5E, 0xA2, 0x2C, 0xBE, 0xB8, 0x90, 0xCE,
- 0x06, 0x25, 0xBF, 0xD1, 0x5A, 0x50, 0xCF, 0x3B,
- 0x52, 0xE2, 0xA7, 0xFF, 0x19, 0x02, 0xCF, 0xD0,
- 0x9B, 0xD9, 0xF7, 0x28, 0x07, 0x38, 0x1F, 0xF2,
- 0xAF, 0x44, 0x91, 0x3F, 0x0F, 0xB6, 0x6E, 0x8C,
- 0xC0, 0x32, 0x92, 0xC0, 0xCD, 0x25, 0x98, 0x67,
- 0xF1, 0x47, 0x52, 0x50, 0xF0, 0xA3, 0x7B, 0xE6,
- 0x74, 0xDC, 0x72, 0x28, 0xC8, 0xAB, 0xB3, 0x31,
- 0x7D, 0xA3, 0xF7, 0xC7, 0xD1, 0xE6, 0x99, 0xB4,
- 0xB6, 0x5A, 0x3A, 0x4D, 0x83, 0x4F, 0xB8, 0xB5,
- 0x86, 0xF8, 0x37, 0x7F, 0xA0, 0x16, 0x2F, 0x3C,
- 0x62, 0x7A, 0xD4, 0x3A, 0xEB, 0xC2, 0xE8, 0x03,
- 0x49, 0x17, 0x9E, 0xFB, 0xD7, 0xAF, 0x91, 0x32,
- 0xFD, 0xEA, 0x4F, 0x64, 0xC6, 0x6E, 0x02, 0xEA,
- 0xC4, 0xC8, 0x1F, 0x16, 0xC5, 0x4C, 0xFB, 0xC5,
- 0x42, 0xF5, 0x85, 0x05, 0x92, 0x59, 0x4B, 0x31,
- 0xE5, 0xE9, 0x69, 0xE7, 0x02, 0x98, 0x33, 0xBA,
- 0x4C, 0x17, 0x09, 0xEF, 0x89, 0x20, 0xFA, 0x83,
- 0x9F, 0xAE, 0x0E, 0x1B, 0x7D, 0x98, 0xB9, 0xF2,
- 0x3C, 0x0F, 0xB7, 0x1C, 0x72, 0xDF, 0x17, 0x84,
- 0x7F, 0x0A, 0xFD, 0x12, 0x3C, 0x6F, 0x68, 0x5D,
- 0x45, 0xEB, 0xB8, 0xD6, 0x24, 0x65, 0x42, 0x75,
- 0x5C, 0xC2, 0xF3, 0x3A, 0x6A, 0x4E, 0x51, 0x34,
- 0x1B, 0xB6, 0x81, 0xB2, 0x8A, 0xEF, 0x28, 0xA4,
- 0xC5, 0x88, 0x9A, 0x97, 0xE0, 0xEF, 0x31, 0x12,
- 0x01, 0x7E, 0x1B, 0x43, 0x0F, 0x27, 0x80, 0x87,
- 0x98, 0xC5, 0xD5, 0x83, 0xCB, 0x4B, 0xB7, 0x01,
- 0x79, 0x60, 0xA1, 0x1A, 0x03, 0x05, 0xC6, 0x36,
- 0x04, 0x31, 0x3C, 0x06, 0xDB, 0x08, 0xA8, 0xDA,
- 0x8E, 0x32, 0x19, 0x91, 0xF1, 0x0D, 0x61, 0x6F,
- 0xE4, 0xB2, 0x79, 0x8A, 0xDE, 0xF4, 0xF7, 0xFB,
- 0x2C, 0x23, 0x5B, 0xD9, 0x64, 0x2F, 0xB7, 0xB3,
- 0x8B, 0xCA, 0xB8, 0x8C, 0x1D, 0x3B, 0x49, 0x05,
- 0x38, 0xA1, 0xE5, 0x8C, 0x1A, 0xDC, 0xA5, 0x61,
- 0xFE, 0xF4, 0x2B, 0xDC, 0x77, 0x28, 0xF6, 0x19,
- 0xE7, 0xB7, 0x8F, 0x4D, 0x27, 0x2D, 0xED, 0x8A,
- 0x3F, 0x3D, 0xDC, 0x9F, 0xD1, 0x30, 0xFF, 0xD6,
- 0xC3, 0xBE, 0x41, 0x25, 0xE3, 0xA5, 0x9B, 0x73,
- 0xDF, 0x6A, 0xD9, 0xF9, 0x70, 0x84, 0x02, 0x4C,
- 0x35, 0xD4, 0x3E, 0x05, 0x76, 0x3A, 0xDC, 0x6D,
- 0x5A, 0x81, 0xB3, 0x94, 0xF7, 0x22, 0xF7, 0xDC,
- 0xC1, 0x43, 0x31, 0x57, 0x5B, 0x42, 0x9A, 0x0B,
- 0xF4, 0x95, 0x30, 0xA9, 0xBB, 0xD8, 0x06, 0xFB,
- 0x1D, 0x6F, 0x9B, 0xC3, 0xBB, 0xF3, 0xBF, 0xFB,
- 0xB4, 0x9F, 0x35, 0x64, 0x0A, 0x69, 0xB7, 0xD1,
- 0x3E, 0xCA, 0x78, 0x07, 0x04, 0x03, 0x79, 0xD4,
- 0xF3, 0xA8, 0xEC, 0x18, 0xDB, 0x03, 0x5E, 0x47,
- 0xD7, 0xD0, 0x56, 0x2C, 0x74, 0x94, 0x86, 0x04,
- 0x46, 0xB8, 0xD4, 0x35, 0x0A, 0x7B, 0xE6, 0x78,
- 0xC4, 0x43, 0x3C, 0x56, 0xCC, 0x37, 0x8B, 0xFD,
- 0xE8, 0xF4, 0x57, 0xEA, 0xAE, 0xCF, 0x36, 0x97,
- 0x12, 0xAC, 0x39, 0xCF, 0x7C, 0xEF, 0x22, 0x67,
- 0x01, 0xEC, 0xD8, 0x09, 0x49, 0x4E, 0xE3, 0x74,
- 0xDD, 0x39, 0xE1, 0x39, 0xD7, 0x0C, 0x5F, 0x1B,
- 0xCE, 0x69, 0xBC, 0x72, 0x44, 0x87, 0x64, 0x1C,
- 0x08, 0x05, 0x93, 0x69, 0x6D, 0x7F, 0x90, 0x0A,
- 0x2C, 0xCB, 0x8A, 0xBB, 0x7F, 0xE3, 0xE0, 0x80,
- 0x31, 0xD0, 0x0A, 0x3A, 0x95, 0xFF, 0xF7, 0xB4,
- 0x36, 0x38, 0x93, 0xE0, 0x0C, 0x11, 0x37, 0x12,
- 0x06, 0xF6, 0xAD, 0xE9, 0xB1, 0x7A, 0x00, 0xF5,
- 0xD2, 0x32, 0x6B, 0xD0, 0x27, 0xA5, 0x1B, 0x3D,
- 0xE8, 0xDB, 0xCC, 0xA9, 0x1F, 0x1F, 0xB1, 0x99,
- 0x3D, 0x7C, 0xB7, 0xCA, 0xDA, 0x27, 0x2C, 0x64,
- 0x1C, 0x49, 0xB6, 0x87, 0x44, 0x06, 0x94, 0x9D,
- 0xBC, 0x6B, 0x20, 0xA2, 0x68, 0x15, 0x1F, 0xE2,
- 0xF2, 0xAD, 0x6D, 0x23, 0x2E, 0x2B, 0x74, 0xE2,
- 0x5D, 0xE4, 0xB0, 0xC7, 0x84, 0xCB, 0x64, 0xBF,
- 0xE0, 0xA8, 0x18, 0x83, 0xB4, 0xC9, 0xD9, 0x73,
- 0xA8, 0xE6, 0xA9, 0x36, 0xD5, 0x63, 0x1E, 0x2C,
- 0x2A, 0x55, 0x09, 0x77, 0x5E, 0xB3, 0x4B, 0xEA,
- 0xB5, 0xD0, 0x14, 0x5F, 0xEB, 0x50, 0x7B, 0xAA,
- 0xEF, 0x94, 0xBA, 0x2B, 0xD7, 0x8A, 0x07, 0xF1,
- 0xF9, 0x5E, 0x12, 0x12, 0x21, 0x52, 0xE5, 0x0A,
- 0x3E, 0xC0, 0xBC, 0x5D, 0x4C, 0xE2, 0x12, 0x7C,
- 0x39, 0xF9, 0x16, 0x9D, 0xBD, 0x96, 0x83, 0x3B,
- 0x7F, 0x3D, 0x6A, 0xEC, 0xF1, 0x25, 0xD2, 0xB0,
- 0xB0, 0xEB, 0x20, 0x06, 0x07, 0xD6, 0xD9, 0x4C,
- 0x07, 0x9A, 0x82, 0xC1, 0xFC, 0xF7, 0x66, 0x15,
- 0xBD, 0x62, 0x65, 0xD8, 0x6C, 0xF6, 0x33, 0x7B,
- 0x5A, 0x28, 0xEC, 0x90, 0xA1, 0x26, 0x9F, 0xC3,
- 0x28, 0x4A, 0x64, 0x50, 0x5F, 0xCA, 0xE2, 0x6D,
- 0xB8, 0x0F, 0xE2, 0x94, 0xB5, 0x8E, 0x1F, 0x8A,
- 0x8F, 0x6B, 0xA6, 0x86, 0x1F, 0xEE, 0xDC, 0x24,
- 0xB4, 0xB8, 0x25, 0xEC, 0x28, 0x2D, 0xF9, 0xCB,
- 0x7D, 0x38, 0xFF, 0xC7, 0x74, 0x2E, 0xD3, 0x10,
- 0xEC, 0x03, 0x31, 0xEE, 0x83, 0xE7, 0xA4, 0xF7,
- 0xBA, 0x28, 0x21, 0xE0, 0x7F, 0xB4, 0xB7, 0xE1,
- 0x7A, 0xF9, 0x2B, 0xB0, 0x2C, 0x3B, 0x80, 0x5F,
- 0xE0, 0x5D, 0xB2, 0x7E, 0x59, 0xFF, 0x59, 0x07,
- 0x58, 0x42, 0x57, 0xEE, 0x44, 0xF1, 0xB1, 0xAD,
- 0xBA, 0xDE, 0xCB, 0x1D, 0x8A, 0x36, 0x67, 0xE8,
- 0x45, 0xFF, 0x07, 0x8D, 0xEE, 0xA4, 0x51, 0x9C,
- 0x4C, 0x83, 0x5D, 0x2E, 0x2F, 0xE1, 0x5B, 0x75,
- 0xE8, 0x29, 0xCD, 0x0B, 0x07, 0x62, 0xE0, 0xC3,
- 0x0D, 0x1D, 0xEA, 0xCF, 0xF0, 0x8A, 0x65, 0x27,
- 0x70, 0x42, 0x9F, 0x26, 0x00, 0x15, 0x70, 0xC5,
- 0x4A, 0xF6, 0x25, 0xD0, 0x40, 0x72, 0xE9, 0xC1,
- 0x73, 0xFD, 0x48, 0x94, 0xA3, 0x8D, 0x66, 0x63,
- 0x96, 0x4F, 0xF7, 0xEE, 0xFB, 0x4C, 0xC7, 0xB8,
- 0x6B, 0xE9, 0x90, 0xE1, 0x2A, 0x66, 0x80, 0x99,
- 0x3B, 0xB0, 0x1A, 0x6C, 0xF9, 0x0E, 0x72, 0xDA,
- 0x8E, 0x4F, 0x46, 0xC2, 0x6A, 0x4B, 0x7A, 0x16,
- 0xE5, 0x26, 0x0B, 0x5C, 0xD4, 0x47, 0x34, 0xE5,
- 0x37, 0xBE, 0x68, 0x6C, 0xDA, 0xD3, 0x9B, 0x6F,
- 0xAE, 0x51, 0x9C, 0x99, 0x0A, 0x5B, 0xF8, 0x37,
- 0xBC, 0xDE, 0xFC, 0x93, 0xC5, 0xE7, 0x0F, 0xEF,
- 0x0B, 0xA6, 0x07, 0xC2, 0xA6, 0xE6, 0xDA, 0x2D,
- 0x1B, 0x49, 0xC9, 0xDE, 0x6B, 0x27, 0xDC, 0x00,
- 0xEF, 0x23, 0x87, 0x0E, 0xEB, 0xD1, 0x48, 0x7D,
- 0xB4, 0xF2, 0x58, 0xC6, 0x3C, 0xE2, 0x89, 0xBA,
- 0xB0, 0x05, 0xAC, 0x94, 0x41, 0x9A, 0xA8, 0xFF,
- 0x3E, 0xBC, 0x3A, 0x52, 0x9C, 0xF9, 0x7F, 0x07,
- 0x8B, 0xB0, 0x2C, 0x71, 0x83, 0x7B, 0xCF, 0x2E,
- 0x7F, 0x7C, 0x96, 0x65, 0xD9, 0x08, 0x17, 0xEC,
- 0xFA, 0xDE, 0x4E, 0x40, 0x12, 0x26, 0x70, 0x71,
- 0x65, 0xA5, 0xDC, 0x98, 0x47, 0xA3, 0xFC, 0xE0,
- 0x9A, 0x16, 0xED, 0x45, 0x56, 0x72, 0x50, 0x05,
- 0x28, 0x2C, 0x99, 0xEC, 0x20, 0x2E, 0x40, 0xC0,
- 0x26, 0x69, 0xCD, 0x49, 0x45, 0x17, 0xA4, 0xA3,
- 0x42, 0x0D, 0x14, 0x65, 0x87, 0x33, 0x8C, 0x92,
- 0xC5, 0xC4, 0x61, 0xFD, 0xE8, 0x68, 0x56, 0x20,
- 0x57, 0xF5, 0x8E, 0x5F, 0xCF, 0x7E, 0x97, 0xF6,
- 0x49, 0x97, 0x0A, 0xFE, 0xD3, 0x60, 0x1A, 0x5B,
- 0x0C, 0x75, 0xDD, 0x8E, 0x31, 0x78, 0x29, 0xA6,
- 0xB1, 0x4D, 0xAA, 0xDF, 0x8A, 0xD1, 0xE6, 0x91,
- 0xE3, 0x32, 0x3F, 0xEC, 0x8A, 0x1F, 0x0E, 0x35,
- 0x07, 0x6E, 0x4B, 0x83, 0x3B, 0xE5, 0x67, 0x34,
- 0x1F, 0x0C, 0x81, 0xD8, 0xD5, 0x25, 0x68, 0xE5,
- 0x28, 0x1B, 0x5C, 0x81, 0x3E, 0xE3, 0x5C, 0xB4,
- 0xB6, 0xBD, 0x62, 0x6A, 0x70, 0x33, 0xC2, 0xC5,
- 0x75, 0x27, 0xF4, 0x30, 0xE1, 0x1D, 0xC1, 0x4C,
- 0xC5, 0x02, 0x12, 0x46, 0xAC, 0xEC, 0xF9, 0xE8,
- 0xE7, 0x58, 0x24, 0x11, 0xB1, 0xF3, 0xB7, 0x8C,
- 0x3C, 0xA4, 0x0A, 0x94, 0xA6, 0x7C, 0x68, 0x54,
- 0x5B, 0xB9, 0x4D, 0x57, 0x9C, 0xE7, 0x28, 0x09,
- 0x6B, 0x89, 0x26, 0x5D, 0xE7, 0x50, 0xA9, 0x95,
- 0x90, 0x91, 0x8E, 0x00, 0x59, 0xF8, 0x3A, 0x70,
- 0xAF, 0x48, 0x2E, 0xE8, 0xC4, 0x34, 0x8C, 0xF4,
- 0x5F, 0x7F, 0xCB, 0x07, 0xAA, 0xF0, 0xD9, 0xFB,
- 0x5C, 0x32, 0x90, 0x22, 0x1A, 0xD2, 0x1A, 0xCF,
- 0x92, 0x06, 0x02, 0xCF, 0x10, 0x18, 0x7B, 0x93,
- 0xCC, 0x07, 0x4A, 0x31, 0x25, 0x30, 0x23, 0x06,
- 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
- 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0xD1, 0xDE,
- 0x23, 0x16, 0x9F, 0x6E, 0xF4, 0x42, 0x21, 0x23,
- 0xE1, 0x11, 0xAA, 0xC8, 0x7C, 0x60, 0x4A, 0x78,
- 0x9D, 0x24, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09,
- 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05,
- 0x00, 0x04, 0x14, 0xD6, 0x4A, 0xBB, 0x75, 0xB1,
- 0xF9, 0x9E, 0xD3, 0x58, 0x6D, 0xD1, 0x74, 0x9F,
- 0x00, 0x8A, 0xF2, 0xC8, 0xAA, 0x52, 0x4D, 0x04,
- 0x08, 0x77, 0x46, 0xE7, 0xBA, 0x25, 0x4B, 0xDA,
- 0x41, 0x02, 0x02, 0x08, 0x00]
-};
-
-const WPA_EAP_CLIENT_LIST = [
- {
- ssid: 'WPA-EAP-TTLS',
- keyManagement: 'WPA-EAP',
- eap: 'TTLS',
- identity: EAP_USERNAME,
- password: EAP_PASSWORD,
- serverCertificate: CLIENT_PKCS12_CERT.nickname,
- phase2: 'MSCHAPV2'
- }
-];
-
-/**
- * Convert the given MozWifiNetwork object array to testAssociate chain.
- *
- * @param aNetworks
- * An array of MozWifiNetwork which we want to convert.
- *
- * @return A promise chain which "then"s testAssociate accordingly.
- */
-function convertToTestAssociateChain(aNetworks) {
- let chain = Promise.resolve();
-
- aNetworks.forEach(function (aNetwork) {
- network = new window.MozWifiNetwork(aNetwork);
- chain = chain.then(() => gTestSuite.testAssociate(network));
- });
-
- return chain;
-}
-
-gTestSuite.doTestWithCertificate(
- new Blob([new Uint8Array(CLIENT_PKCS12_CERT.content)]),
- CLIENT_PKCS12_CERT.password,
- CLIENT_PKCS12_CERT.nickname,
- CLIENT_PKCS12_CERT.usage,
- function() {
- return gTestSuite.ensureWifiEnabled(true)
- // Load required server files.
- .then(() => gTestSuite.writeFile(SERVER_EAP_USER_CONF.path, SERVER_EAP_USER_CONF.content))
- .then(() => gTestSuite.writeFile(CA_CERT.path, CA_CERT.content))
- .then(() => gTestSuite.writeFile(SERVER_CERT.path, SERVER_CERT.content))
- .then(() => gTestSuite.writeFile(SERVER_KEY.path, SERVER_KEY.content))
- // Start AP.
- .then(() => gTestSuite.startHostapds(WPA_EAP_AP_LIST))
- // Scan test.
- .then(() => gTestSuite.testWifiScanWithRetry(SCAN_RETRY_CNT, WPA_EAP_AP_LIST))
- // Associate test.
- .then(() => convertToTestAssociateChain(WPA_EAP_CLIENT_LIST))
- // Tear down.
- .then(gTestSuite.killAllHostapd)
-});
diff --git a/dom/wifi/test/marionette/test_wifi_associate_wo_connect.js b/dom/wifi/test/marionette/test_wifi_associate_wo_connect.js
deleted file mode 100644
index 3fba0b2c6..000000000
--- a/dom/wifi/test/marionette/test_wifi_associate_wo_connect.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-/**
- * Associate with the given networks but don't connect to it.
- *
- * Issue a association-only request, which will not have us connect
- * to the network. Instead, the network config will be added as the
- * known networks. After calling the "associate" API, we will wait
- * a while to make sure the "connected" event is not received.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aNetwork
- * MozWifiNetwork object.
- *
- * @return A deferred promise.
- */
-function associateButDontConnect(aNetwork) {
- log('Associating with ' + aNetwork.ssid);
- aNetwork.dontConnect = true;
-
- let promises = [];
- promises.push(gTestSuite.waitForTimeout(10 * 1000)
- .then(() => { throw 'timeout'; }));
-
- promises.push(gTestSuite.testAssociate(aNetwork));
-
- return Promise.all(promises)
- .then(() => { throw 'unexpected state'; },
- function(aReason) {
- is(typeof aReason, 'string', 'typeof aReason');
- is(aReason, 'timeout', aReason);
- });
-}
-
-gTestSuite.doTest(function() {
- let firstNetwork;
- return gTestSuite.ensureWifiEnabled(true)
- .then(gTestSuite.requestWifiScan)
- .then(function(aNetworks) {
- firstNetwork = aNetworks[0];
- return associateButDontConnect(firstNetwork);
- })
- .then(gTestSuite.getKnownNetworks)
- .then(function(aKnownNetworks) {
- is(1, aKnownNetworks.length, 'There should be only one known network!');
- is(aKnownNetworks[0].ssid, firstNetwork.ssid,
- 'The only one known network should be ' + firstNetwork.ssid)
- });
-});
diff --git a/dom/wifi/test/marionette/test_wifi_auto_connect.js b/dom/wifi/test/marionette/test_wifi_auto_connect.js
deleted file mode 100644
index 7add9f03d..000000000
--- a/dom/wifi/test/marionette/test_wifi_auto_connect.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const TESTING_HOSTAPD = [{ ssid: 'ap0' }];
-
-gTestSuite.doTestWithoutStockAp(function() {
- let firstNetwork;
- return gTestSuite.ensureWifiEnabled(true)
- // Start custom hostapd for testing.
- .then(() => gTestSuite.startHostapds(TESTING_HOSTAPD))
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', TESTING_HOSTAPD.length))
-
- // Request the first scan.
- .then(gTestSuite.requestWifiScan)
- .then(function(networks) {
- firstNetwork = networks[0];
- return gTestSuite.testAssociate(firstNetwork);
- })
-
- // Note that due to Bug 1168285, we need to re-start testing hostapd
- // after wifi has been re-enabled.
-
- // Disable wifi and kill running hostapd.
- .then(() => gTestSuite.requestWifiEnabled(false))
- .then(gTestSuite.killAllHostapd)
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', 0))
-
- // Re-enable wifi.
- .then(() => gTestSuite.requestWifiEnabled(true))
-
- // Restart hostapd.
- .then(() => gTestSuite.startHostapds(TESTING_HOSTAPD))
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', TESTING_HOSTAPD.length))
-
- // Wait for connection automatically.
- .then(() => gTestSuite.waitForConnected(firstNetwork))
-
- // Kill running hostapd.
- .then(gTestSuite.killAllHostapd)
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', 0))
-});
diff --git a/dom/wifi/test/marionette/test_wifi_enable.js b/dom/wifi/test/marionette/test_wifi_enable.js
deleted file mode 100644
index 6a1bec7a2..000000000
--- a/dom/wifi/test/marionette/test_wifi_enable.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-gTestSuite.doTest(function() {
- return Promise.resolve()
- .then(() => gTestSuite.ensureWifiEnabled(false))
- .then(() => gTestSuite.requestWifiEnabled(true));
-}); \ No newline at end of file
diff --git a/dom/wifi/test/marionette/test_wifi_enable_api.js b/dom/wifi/test/marionette/test_wifi_enable_api.js
deleted file mode 100644
index 3728330a2..000000000
--- a/dom/wifi/test/marionette/test_wifi_enable_api.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-gTestSuite.doTest(function() {
- return Promise.resolve()
- .then(() => gTestSuite.ensureWifiEnabled(false, true))
- .then(() => gTestSuite.requestWifiEnabled(true, true))
- .then(() => gTestSuite.requestWifiEnabled(false, true))
- .then(() => gTestSuite.ensureWifiEnabled(true, true));
-});
diff --git a/dom/wifi/test/marionette/test_wifi_manage_pkcs12_certificate.js b/dom/wifi/test/marionette/test_wifi_manage_pkcs12_certificate.js
deleted file mode 100644
index f85ef00c9..000000000
--- a/dom/wifi/test/marionette/test_wifi_manage_pkcs12_certificate.js
+++ /dev/null
@@ -1,338 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-// Binary form of test certificate.
-var testCertInfo = {
- nickname: 'Test Certificate',
- password: '12345678',
- usage: ['UserCert', 'ServerCert'],
- blob: [0x30, 0x82, 0x09, 0xF1, 0x02, 0x01, 0x03, 0x30,
- 0x82, 0x09, 0xB7, 0x06, 0x09, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82,
- 0x09, 0xA8, 0x04, 0x82, 0x09, 0xA4, 0x30, 0x82,
- 0x09, 0xA0, 0x30, 0x82, 0x06, 0x9F, 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07,
- 0x06, 0xA0, 0x82, 0x06, 0x90, 0x30, 0x82, 0x06,
- 0x8C, 0x02, 0x01, 0x00, 0x30, 0x82, 0x06, 0x85,
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x07, 0x01, 0x30, 0x1C, 0x06, 0x0A, 0x2A,
- 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01,
- 0x06, 0x30, 0x0E, 0x04, 0x08, 0x13, 0xB5, 0x2F,
- 0x5A, 0xB9, 0x49, 0xE6, 0x0B, 0x02, 0x02, 0x08,
- 0x00, 0x80, 0x82, 0x06, 0x58, 0x35, 0x77, 0x6B,
- 0xBF, 0x5C, 0x06, 0x09, 0xD8, 0xF0, 0x36, 0x06,
- 0x69, 0x8D, 0xA2, 0x86, 0xCF, 0x6B, 0x73, 0x86,
- 0x14, 0xFA, 0x51, 0x9A, 0x87, 0x73, 0x29, 0x71,
- 0xC5, 0xB1, 0x4F, 0xFB, 0xEC, 0x64, 0x84, 0x20,
- 0xFC, 0x06, 0x4A, 0x93, 0x74, 0x01, 0xFB, 0xEB,
- 0x1F, 0xDC, 0xF8, 0xF7, 0xBB, 0xDC, 0x42, 0xA1,
- 0x4A, 0x71, 0xDE, 0x08, 0x33, 0x7A, 0xCA, 0xD3,
- 0xD8, 0x40, 0x24, 0x47, 0xAE, 0x41, 0x42, 0x8E,
- 0xC8, 0x4E, 0xBE, 0x8B, 0xB3, 0xE5, 0x77, 0xAC,
- 0xBD, 0x98, 0x0C, 0x0E, 0x53, 0xBE, 0x38, 0xB7,
- 0xEA, 0xD2, 0x29, 0x35, 0xD2, 0xC4, 0xF4, 0xC7,
- 0xD8, 0xB1, 0x73, 0x2A, 0x13, 0x11, 0x65, 0xF7,
- 0x0C, 0x8B, 0xC0, 0x43, 0xFB, 0x31, 0x6C, 0xD2,
- 0xE4, 0x43, 0x85, 0x51, 0x16, 0xBF, 0x35, 0xB5,
- 0x05, 0x6B, 0x86, 0x11, 0xEA, 0x78, 0x64, 0x9F,
- 0x42, 0x29, 0xB9, 0x79, 0xAF, 0xB0, 0x7C, 0xBF,
- 0xC0, 0x89, 0xAD, 0xC7, 0x37, 0xD2, 0x30, 0x8C,
- 0xDC, 0xF6, 0x77, 0x5E, 0x1F, 0x26, 0x28, 0x8F,
- 0xAC, 0x19, 0x6C, 0xA0, 0x15, 0xC7, 0x12, 0xA3,
- 0x0A, 0xD5, 0xC6, 0x15, 0x60, 0x58, 0x16, 0xB8,
- 0x30, 0x12, 0x3C, 0x78, 0x3C, 0x93, 0x23, 0xA1,
- 0x56, 0x75, 0x0B, 0x77, 0xAA, 0x0B, 0x0B, 0x2B,
- 0x91, 0xB6, 0x41, 0xAB, 0xF5, 0x09, 0x4C, 0x1E,
- 0x36, 0xC0, 0x88, 0xC3, 0x08, 0xF2, 0x65, 0xCB,
- 0x58, 0x8F, 0x94, 0xB4, 0xB4, 0x05, 0xCC, 0x44,
- 0x49, 0x73, 0x1B, 0x25, 0x6F, 0x5D, 0x83, 0xBD,
- 0xF0, 0x70, 0xD0, 0xE8, 0x0D, 0x18, 0x2E, 0x44,
- 0xD7, 0x89, 0x64, 0x6A, 0xED, 0x23, 0x30, 0xDF,
- 0xAD, 0x84, 0x3B, 0x74, 0x2C, 0x0D, 0x2B, 0x51,
- 0x84, 0xA2, 0xA4, 0x9E, 0x42, 0xC3, 0x81, 0x69,
- 0xFA, 0x56, 0x76, 0x9F, 0xD9, 0x02, 0x64, 0x04,
- 0xFE, 0xF0, 0xD9, 0x01, 0xBC, 0xE2, 0xC9, 0xDD,
- 0x88, 0xAC, 0xFA, 0x24, 0x7E, 0xB1, 0xF8, 0x39,
- 0x27, 0xA2, 0xEB, 0xE4, 0x53, 0xC1, 0xF3, 0xFE,
- 0x2D, 0x9A, 0x49, 0x73, 0xFF, 0x7C, 0x8E, 0x39,
- 0xF7, 0x15, 0x27, 0xB3, 0x47, 0x48, 0x92, 0x8C,
- 0x57, 0x60, 0x9C, 0x97, 0xBA, 0x80, 0xD2, 0x25,
- 0x80, 0x94, 0xCE, 0x2C, 0x0C, 0x00, 0x44, 0x8C,
- 0x8C, 0x37, 0x82, 0x5D, 0x5F, 0x62, 0x8B, 0x05,
- 0x6F, 0xB0, 0x07, 0x34, 0xF9, 0xC3, 0xA1, 0x34,
- 0x3D, 0xE4, 0x90, 0xB0, 0x03, 0x59, 0x97, 0x6E,
- 0xFB, 0xF2, 0x92, 0xE5, 0xB5, 0x30, 0x7C, 0x0D,
- 0x3B, 0x8F, 0x90, 0x8E, 0x04, 0x47, 0x01, 0x0E,
- 0x88, 0x50, 0x4A, 0x88, 0xA0, 0xFF, 0xB7, 0x9E,
- 0x2B, 0x2C, 0x98, 0xD0, 0x3E, 0x16, 0x35, 0x5B,
- 0xD5, 0xEA, 0x54, 0x86, 0xE0, 0xFB, 0x9F, 0x2F,
- 0x62, 0x89, 0x36, 0x36, 0x9D, 0x6E, 0x62, 0xCB,
- 0xC8, 0x6C, 0x62, 0x34, 0x8F, 0x66, 0x07, 0x62,
- 0xA7, 0x00, 0x90, 0x31, 0xFA, 0x5D, 0xDD, 0x12,
- 0x33, 0x69, 0xD0, 0x74, 0x0E, 0x0B, 0x42, 0x9A,
- 0xF3, 0x40, 0x7E, 0x3E, 0x48, 0x1D, 0xF2, 0x5C,
- 0x71, 0x0B, 0x78, 0x7E, 0xD5, 0x15, 0xA4, 0x16,
- 0x1E, 0xBD, 0x71, 0x18, 0x87, 0x3A, 0xC9, 0xE3,
- 0x45, 0xEE, 0x70, 0xA2, 0x4C, 0x50, 0xF5, 0x16,
- 0x5C, 0xF8, 0x76, 0xE6, 0x9F, 0x8D, 0x86, 0x41,
- 0x7E, 0xF8, 0x60, 0x3D, 0x75, 0x6D, 0x55, 0x96,
- 0x9E, 0x43, 0x48, 0x82, 0xF7, 0xB6, 0xAC, 0x98,
- 0x6F, 0x10, 0xAA, 0x20, 0x64, 0xD0, 0x7C, 0x25,
- 0x24, 0xF7, 0xD8, 0xA4, 0xCC, 0x2D, 0xBF, 0x85,
- 0x62, 0x6C, 0x4F, 0xFF, 0x9D, 0x71, 0x04, 0x98,
- 0x61, 0xB0, 0xBC, 0x31, 0xC1, 0xE9, 0xB8, 0x29,
- 0xA5, 0xEB, 0xD1, 0x1D, 0x65, 0x8E, 0xAE, 0x38,
- 0x55, 0x65, 0x22, 0xC7, 0xFD, 0x7E, 0xF2, 0x6A,
- 0xB6, 0xB1, 0x51, 0x37, 0x4B, 0x05, 0x8F, 0xA7,
- 0x2D, 0x3F, 0x5C, 0x04, 0x2B, 0xBA, 0x2C, 0x37,
- 0xCA, 0xDE, 0xD5, 0x3E, 0xA0, 0xA5, 0x86, 0x59,
- 0xA7, 0xD7, 0x38, 0x07, 0xFB, 0x79, 0xF6, 0x2D,
- 0xE1, 0xAA, 0x7C, 0xD1, 0x91, 0xBE, 0x39, 0xDF,
- 0x53, 0x3C, 0xD1, 0x44, 0x2C, 0xF9, 0x12, 0x7D,
- 0xB1, 0xCD, 0xF3, 0x35, 0x1F, 0x85, 0xA6, 0x64,
- 0x2F, 0xFD, 0x28, 0xF2, 0x85, 0xA8, 0xA7, 0x1F,
- 0x7F, 0xD9, 0x79, 0x30, 0x9B, 0xFC, 0x69, 0x3A,
- 0x9B, 0x1F, 0x55, 0x70, 0xC9, 0x60, 0x82, 0x3D,
- 0xE9, 0x5A, 0x37, 0x5F, 0x8C, 0xBD, 0x19, 0x5D,
- 0xCC, 0x1C, 0xBE, 0x26, 0x4A, 0xEA, 0x8B, 0x39,
- 0xCE, 0x0D, 0xBD, 0x63, 0x05, 0x98, 0x75, 0xAB,
- 0x08, 0x79, 0x90, 0xC7, 0x20, 0xFF, 0xE4, 0x0D,
- 0xB1, 0xA0, 0x92, 0x2B, 0x0C, 0x4B, 0x0C, 0xDC,
- 0xB9, 0x72, 0x2A, 0xA4, 0xCC, 0xA6, 0x32, 0xA3,
- 0x57, 0x82, 0xB4, 0xB9, 0x0F, 0x81, 0xC5, 0xD9,
- 0x7C, 0xB8, 0x0F, 0x7D, 0xEA, 0x5D, 0xD3, 0xC4,
- 0x2F, 0x31, 0x79, 0x11, 0xAD, 0x36, 0x56, 0x1F,
- 0xFA, 0xE3, 0xCE, 0xD2, 0x29, 0x23, 0xE8, 0x2C,
- 0xDF, 0x7D, 0x94, 0x28, 0x28, 0x9A, 0x0E, 0x64,
- 0xFC, 0x07, 0x11, 0x96, 0x06, 0x1A, 0x39, 0xCD,
- 0x04, 0x37, 0x37, 0xDB, 0xFE, 0x68, 0x37, 0xF5,
- 0x59, 0x54, 0xBC, 0xEF, 0xDB, 0x0C, 0x80, 0xCD,
- 0xD3, 0x46, 0xA8, 0xA2, 0xBE, 0xE0, 0x63, 0x80,
- 0xA1, 0x5F, 0x5D, 0xF1, 0xFB, 0x96, 0x8C, 0x06,
- 0x38, 0xB6, 0xCB, 0x70, 0xB0, 0xFB, 0xD3, 0x26,
- 0xB3, 0x8B, 0xC6, 0x85, 0x34, 0xB7, 0xAB, 0x5F,
- 0x7E, 0xC6, 0xAA, 0x79, 0x5B, 0x48, 0x11, 0x65,
- 0x9E, 0x2A, 0xCD, 0x6A, 0xF0, 0xB2, 0x93, 0xF5,
- 0x2B, 0x88, 0x45, 0xB7, 0xC9, 0xBE, 0x1A, 0x72,
- 0x60, 0x62, 0xA4, 0xA5, 0x3B, 0xC2, 0x1C, 0xC6,
- 0x21, 0x09, 0xA9, 0x40, 0xF6, 0x58, 0x2B, 0xE5,
- 0x70, 0xDC, 0xFC, 0x47, 0x3B, 0x08, 0xEE, 0xA9,
- 0x94, 0x26, 0x43, 0xFE, 0xA7, 0x75, 0xD6, 0x4E,
- 0x52, 0xF6, 0x46, 0xD1, 0x80, 0xEB, 0x3B, 0x8E,
- 0xBE, 0x54, 0x4F, 0xBD, 0x42, 0x0E, 0x41, 0xF9,
- 0x36, 0x7D, 0xB6, 0x7F, 0x99, 0x20, 0xC9, 0x63,
- 0xE7, 0x93, 0x02, 0x62, 0x59, 0x94, 0xCB, 0xC6,
- 0x62, 0xA9, 0x26, 0xE1, 0x1E, 0x03, 0x5A, 0x41,
- 0x2F, 0x43, 0x28, 0x75, 0xB7, 0x0C, 0x02, 0x9C,
- 0x1E, 0xE0, 0x40, 0xB3, 0xE2, 0x9A, 0xED, 0xC6,
- 0x20, 0x49, 0xEC, 0xDD, 0xC5, 0x64, 0x95, 0x83,
- 0x51, 0xAE, 0x46, 0x9D, 0x70, 0x17, 0xC6, 0x47,
- 0xD3, 0x82, 0xCC, 0x6A, 0x5D, 0x93, 0xB2, 0x85,
- 0x5B, 0x25, 0x05, 0xE7, 0x26, 0x2E, 0xD3, 0xDA,
- 0x1C, 0xD9, 0x06, 0xB6, 0x16, 0x69, 0x8C, 0x7F,
- 0xC8, 0xCF, 0x95, 0x18, 0xB5, 0x98, 0xC0, 0x42,
- 0x61, 0xDE, 0x77, 0x41, 0x3A, 0xF6, 0xE1, 0xB0,
- 0xE8, 0x64, 0x4A, 0xC2, 0x58, 0xBE, 0x27, 0xC6,
- 0x9B, 0x0D, 0x47, 0x1A, 0x09, 0x56, 0x7D, 0x2B,
- 0x19, 0x01, 0x88, 0xC7, 0xFB, 0x1E, 0xCF, 0x5E,
- 0xF6, 0xB0, 0x82, 0x87, 0xC0, 0xBE, 0xD6, 0xA5,
- 0xC3, 0xAC, 0x3A, 0x97, 0x88, 0x25, 0x81, 0xAA,
- 0x3A, 0xCE, 0x66, 0x88, 0x0F, 0xC3, 0x02, 0x50,
- 0x1C, 0xC3, 0x2B, 0xBC, 0x53, 0x52, 0xFE, 0xD2,
- 0x3F, 0x50, 0xC8, 0xB2, 0x19, 0x0A, 0x14, 0xB1,
- 0x73, 0x18, 0xB4, 0xDF, 0xBD, 0xED, 0x43, 0xC5,
- 0x91, 0xF4, 0x91, 0xBA, 0x7E, 0xB0, 0x7E, 0xA9,
- 0x43, 0x67, 0x06, 0xCF, 0x51, 0xC1, 0xBF, 0x63,
- 0x7E, 0x91, 0x76, 0xFF, 0x4F, 0x48, 0x91, 0xCF,
- 0xDF, 0x01, 0x4D, 0x7E, 0x81, 0x22, 0xFB, 0x79,
- 0xFC, 0x1D, 0xE3, 0xA7, 0x45, 0x16, 0xFB, 0xF2,
- 0x83, 0xC7, 0xAE, 0xC6, 0xC5, 0x81, 0xDB, 0xA2,
- 0x9F, 0x2F, 0xEA, 0xE6, 0x8E, 0x12, 0x8D, 0x43,
- 0x14, 0x26, 0x25, 0x0E, 0xB4, 0x18, 0xE8, 0x41,
- 0x84, 0xA3, 0x04, 0xDF, 0x97, 0xFF, 0xAA, 0x45,
- 0xEC, 0x18, 0xAA, 0xB1, 0xFC, 0xDC, 0xB9, 0xAB,
- 0xEE, 0xD1, 0xC4, 0x9E, 0x42, 0x3F, 0x5B, 0x8F,
- 0x9F, 0x22, 0xAF, 0xCC, 0x6F, 0xA0, 0x41, 0x41,
- 0xCB, 0xD3, 0xAC, 0x96, 0x20, 0xF1, 0x63, 0x56,
- 0x65, 0xCE, 0x83, 0xC6, 0x62, 0x04, 0x85, 0x16,
- 0x7F, 0x4E, 0xFB, 0xA0, 0x68, 0x11, 0x85, 0x5B,
- 0x51, 0xB6, 0x9F, 0xA2, 0xF5, 0xA1, 0xCF, 0x01,
- 0x9A, 0x80, 0x68, 0xC3, 0xE9, 0x7F, 0x9E, 0x2E,
- 0x83, 0x84, 0xDC, 0x3C, 0x35, 0xCF, 0x24, 0xBF,
- 0xF5, 0x00, 0x91, 0x45, 0x14, 0x65, 0xE0, 0xC5,
- 0x75, 0xDA, 0xEF, 0x14, 0xBD, 0xDB, 0x28, 0x8D,
- 0x30, 0x96, 0xC9, 0xFE, 0xA8, 0x49, 0x76, 0xC9,
- 0xED, 0x90, 0x4C, 0x2E, 0xF1, 0x14, 0x2C, 0xF7,
- 0x13, 0x7C, 0xF1, 0xCC, 0x67, 0xA5, 0x11, 0x55,
- 0xBD, 0x66, 0x13, 0x8A, 0x76, 0xF9, 0xAC, 0xC9,
- 0x51, 0x8A, 0xBB, 0x5D, 0x29, 0xEF, 0xF6, 0x37,
- 0xA0, 0x3E, 0x99, 0x77, 0x6B, 0xE5, 0xCD, 0x06,
- 0xAC, 0x57, 0x07, 0x37, 0x44, 0x3D, 0x5D, 0xD7,
- 0xB6, 0x5C, 0xCB, 0x77, 0xD0, 0x4C, 0x28, 0x9D,
- 0x12, 0x69, 0x5A, 0x68, 0xD1, 0x15, 0x30, 0xC4,
- 0x30, 0xD2, 0x20, 0xDF, 0xD5, 0x73, 0x9F, 0x83,
- 0xE9, 0x4C, 0x55, 0xF5, 0xAF, 0xAA, 0x37, 0xF8,
- 0x28, 0xB6, 0x3F, 0x99, 0x4B, 0x15, 0x1E, 0x40,
- 0xAB, 0x4F, 0x58, 0x3D, 0x3B, 0x81, 0x7D, 0x62,
- 0x28, 0x6E, 0x73, 0x58, 0x50, 0x36, 0x49, 0x01,
- 0xF7, 0x04, 0x3A, 0x23, 0x28, 0xDA, 0x15, 0xC5,
- 0xE3, 0xF6, 0x6F, 0xE1, 0x79, 0x07, 0xFB, 0xAA,
- 0xFF, 0x44, 0x48, 0x53, 0x9E, 0x7F, 0x8D, 0x89,
- 0x88, 0x1A, 0x9A, 0xF9, 0x47, 0x58, 0x20, 0xBB,
- 0x79, 0x4A, 0x2A, 0x14, 0x03, 0x9B, 0x65, 0x4C,
- 0x67, 0x02, 0x02, 0xFE, 0xEB, 0xCD, 0xCB, 0x84,
- 0xF5, 0xCE, 0x32, 0x59, 0xBC, 0xEA, 0xEC, 0xB1,
- 0x3C, 0x22, 0xCF, 0x9D, 0xB0, 0x34, 0x6D, 0xE6,
- 0x5A, 0x37, 0xC0, 0x22, 0xAA, 0xF3, 0xB5, 0x71,
- 0x90, 0x21, 0xE0, 0xB6, 0x19, 0xE9, 0xB3, 0x10,
- 0xCE, 0x5B, 0xF9, 0xD4, 0x25, 0x30, 0x7D, 0xF6,
- 0x7D, 0xB6, 0x16, 0xFC, 0x20, 0x3C, 0x2F, 0x96,
- 0xD5, 0x79, 0x90, 0x88, 0x24, 0x5D, 0x46, 0x64,
- 0x99, 0xC1, 0xF8, 0x7F, 0x96, 0xA7, 0xB5, 0xA9,
- 0x47, 0xA3, 0x14, 0xED, 0x93, 0xED, 0x30, 0x56,
- 0x58, 0xA5, 0xD4, 0x54, 0x2A, 0xF3, 0x89, 0x27,
- 0x7C, 0x55, 0x41, 0x11, 0x27, 0x9D, 0xF6, 0x4D,
- 0xA6, 0xB1, 0x00, 0xE0, 0xB0, 0xF6, 0x1E, 0xAB,
- 0x20, 0x1F, 0xAE, 0x8A, 0x82, 0xA7, 0x49, 0xFC,
- 0xBB, 0x66, 0xAC, 0x97, 0x95, 0x49, 0x29, 0xCB,
- 0x6F, 0xF4, 0xC1, 0xB7, 0x6B, 0xF9, 0x8C, 0x25,
- 0xC6, 0xF0, 0xB5, 0x81, 0xB0, 0xA2, 0x4D, 0xCC,
- 0x2E, 0xD0, 0x13, 0x5F, 0x96, 0x3F, 0xCD, 0xD0,
- 0x52, 0xD1, 0xFE, 0xF9, 0xC2, 0x7E, 0x9D, 0xAB,
- 0xCB, 0x95, 0x0F, 0x27, 0x01, 0x9E, 0x23, 0x6B,
- 0x19, 0xFF, 0x52, 0x55, 0x71, 0x0A, 0xD4, 0xBB,
- 0x43, 0x65, 0x29, 0x66, 0xBE, 0x2D, 0x6C, 0xE3,
- 0x2A, 0x7C, 0xB4, 0x02, 0x32, 0x59, 0x94, 0x80,
- 0x14, 0xE7, 0x62, 0xE4, 0xCE, 0xB0, 0xCA, 0xCA,
- 0x37, 0xD7, 0x0C, 0x68, 0x29, 0xE2, 0x92, 0xE1,
- 0xEB, 0x91, 0xE5, 0xA1, 0x0C, 0xFC, 0x55, 0xCB,
- 0x56, 0xB3, 0x96, 0xFB, 0x64, 0xD9, 0x53, 0x8E,
- 0x82, 0x2B, 0xDF, 0x7F, 0xCB, 0x2A, 0xF6, 0x3C,
- 0xA7, 0x89, 0x52, 0x13, 0x2C, 0x6A, 0x93, 0xA2,
- 0x74, 0xF5, 0x91, 0x00, 0x17, 0xAA, 0x74, 0x45,
- 0x63, 0x5A, 0xE5, 0xC3, 0x16, 0xFC, 0x0E, 0xF7,
- 0xF3, 0xA4, 0x55, 0x8A, 0xA2, 0x60, 0x24, 0x57,
- 0x25, 0x2C, 0x94, 0xE0, 0xF5, 0x32, 0x54, 0x4A,
- 0x2D, 0x63, 0x5F, 0xD8, 0x35, 0x96, 0xBD, 0xFE,
- 0x90, 0x33, 0x17, 0xF6, 0xB5, 0x81, 0x02, 0xFA,
- 0x5C, 0x94, 0x3A, 0xBE, 0x22, 0xB9, 0xFC, 0x3E,
- 0x09, 0xE4, 0x76, 0xD7, 0x03, 0x38, 0x38, 0xC2,
- 0xC2, 0x0D, 0x66, 0x3C, 0xD0, 0x91, 0x5C, 0xF4,
- 0x0E, 0xC2, 0xDE, 0x46, 0x90, 0x2E, 0xF5, 0x22,
- 0xA9, 0x3D, 0x15, 0x20, 0x5F, 0x17, 0x10, 0x5A,
- 0x54, 0x63, 0x93, 0x7B, 0xC3, 0x00, 0x3D, 0x42,
- 0x73, 0xF1, 0xAD, 0xC1, 0xDE, 0x76, 0x18, 0x9C,
- 0x68, 0x17, 0xBF, 0x3B, 0xE0, 0x30, 0x82, 0x02,
- 0xF9, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x02, 0xEA,
- 0x04, 0x82, 0x02, 0xE6, 0x30, 0x82, 0x02, 0xE2,
- 0x30, 0x82, 0x02, 0xDE, 0x06, 0x0B, 0x2A, 0x86,
- 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01,
- 0x02, 0xA0, 0x82, 0x02, 0xA6, 0x30, 0x82, 0x02,
- 0xA2, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30,
- 0x0E, 0x04, 0x08, 0x34, 0x37, 0x27, 0x5F, 0xE8,
- 0xD6, 0x00, 0x0D, 0x02, 0x02, 0x08, 0x00, 0x04,
- 0x82, 0x02, 0x80, 0xC0, 0xE6, 0xB1, 0x63, 0x73,
- 0xFC, 0xBF, 0x50, 0xFB, 0x54, 0xCF, 0x67, 0x16,
- 0xF8, 0x28, 0x48, 0x13, 0x7F, 0xF2, 0xBD, 0x66,
- 0x70, 0xC7, 0xF6, 0x01, 0xD0, 0x58, 0xF4, 0xA4,
- 0xD9, 0x45, 0xE2, 0x63, 0x92, 0x7F, 0x78, 0x2B,
- 0xB6, 0xDB, 0x16, 0x44, 0x1D, 0x11, 0xCB, 0xC3,
- 0x20, 0xA9, 0x8A, 0x96, 0x13, 0xB8, 0x6E, 0xF3,
- 0xDA, 0x46, 0x05, 0x2C, 0xF9, 0x67, 0xBB, 0x05,
- 0x88, 0xC0, 0xC8, 0x60, 0x09, 0xA3, 0x82, 0x27,
- 0x33, 0xEB, 0xEE, 0x43, 0x98, 0xE9, 0xE2, 0x24,
- 0xA8, 0x06, 0xD5, 0xFF, 0xF5, 0xC0, 0x79, 0x4B,
- 0x06, 0x40, 0xE6, 0x28, 0xC6, 0x6E, 0x4E, 0x03,
- 0xCC, 0x9B, 0xB6, 0xBD, 0xB6, 0x81, 0x88, 0x5C,
- 0x34, 0x6B, 0x8B, 0x15, 0x23, 0x75, 0x21, 0xAC,
- 0x79, 0xFD, 0xDB, 0x80, 0x1D, 0x20, 0x84, 0xF1,
- 0x47, 0xAF, 0x7B, 0x40, 0x6C, 0xD2, 0x64, 0x52,
- 0x11, 0x1B, 0x01, 0x1E, 0xB5, 0xA9, 0x4B, 0xC4,
- 0x51, 0x54, 0x40, 0xE2, 0xC8, 0xEB, 0x20, 0x48,
- 0x2D, 0x40, 0xF8, 0xC6, 0x58, 0x5A, 0xE3, 0x34,
- 0xD8, 0x79, 0x04, 0xD7, 0xD6, 0x07, 0xF2, 0x12,
- 0x66, 0xC8, 0x31, 0x37, 0x71, 0x60, 0xF4, 0x75,
- 0xDC, 0x60, 0x54, 0x19, 0x6A, 0x75, 0x56, 0xC5,
- 0xA9, 0x67, 0x4A, 0x03, 0x7A, 0xFD, 0x12, 0x59,
- 0x2B, 0x74, 0xE6, 0xA5, 0xE2, 0xF8, 0xBB, 0x1E,
- 0x76, 0x96, 0xD4, 0xD4, 0x3F, 0x8B, 0xAD, 0x90,
- 0xAF, 0x04, 0x41, 0xDB, 0xD8, 0xCC, 0x2D, 0x37,
- 0x06, 0x20, 0x9B, 0xE7, 0x98, 0x87, 0x12, 0xAC,
- 0x70, 0xC9, 0xF4, 0x1C, 0x28, 0xFB, 0x2C, 0x9E,
- 0x18, 0xE1, 0x6D, 0x79, 0x34, 0xBC, 0xAC, 0xCB,
- 0x75, 0x92, 0x7E, 0x8E, 0x7C, 0xA9, 0x0B, 0x86,
- 0x4A, 0x88, 0xFB, 0xE8, 0xBE, 0x6A, 0x32, 0xEF,
- 0x58, 0xCC, 0x4C, 0x89, 0x50, 0xEF, 0xDF, 0xE0,
- 0xDD, 0x35, 0x07, 0x8C, 0x01, 0x8B, 0x57, 0x38,
- 0xB5, 0x64, 0xBB, 0x0A, 0xC2, 0xD8, 0xAB, 0xC5,
- 0x45, 0xA6, 0x83, 0xBF, 0xA6, 0xA2, 0xCC, 0x06,
- 0x64, 0xBE, 0x84, 0x04, 0x55, 0x8E, 0xF4, 0x4C,
- 0xB5, 0xBC, 0xE5, 0x97, 0x2B, 0x3C, 0x42, 0x44,
- 0x91, 0x9B, 0xB2, 0x65, 0x70, 0x02, 0xC5, 0xB7,
- 0x71, 0xB3, 0xF0, 0xAA, 0x46, 0x4F, 0x42, 0x40,
- 0x53, 0x65, 0x89, 0xA5, 0x6C, 0xBC, 0xB5, 0x6C,
- 0x0C, 0x3B, 0x50, 0x46, 0x67, 0xFA, 0x14, 0x68,
- 0x01, 0xE7, 0xA6, 0xD4, 0xB5, 0xD0, 0x82, 0x44,
- 0x92, 0x2C, 0xE3, 0x43, 0x5D, 0x34, 0x7C, 0x04,
- 0xA3, 0x4D, 0x2F, 0x5A, 0x75, 0xE7, 0x0B, 0x64,
- 0xD0, 0xAE, 0x7F, 0xCB, 0xDD, 0x7D, 0x05, 0x88,
- 0x4C, 0x34, 0xBB, 0xF4, 0x00, 0xCE, 0x1C, 0x13,
- 0x4E, 0xA3, 0xE3, 0x60, 0x4B, 0x50, 0x4E, 0xE1,
- 0x26, 0x22, 0x51, 0xD4, 0x32, 0x60, 0xC6, 0x3E,
- 0x7D, 0x4A, 0x3E, 0x56, 0x78, 0xBD, 0x5F, 0x23,
- 0x7F, 0x0A, 0xA0, 0xC1, 0x1A, 0x60, 0xA2, 0x7C,
- 0x9E, 0x17, 0x6F, 0xD8, 0x73, 0x0F, 0x1A, 0x1F,
- 0x47, 0x58, 0x44, 0x20, 0x80, 0xC6, 0x5D, 0x6E,
- 0xEC, 0xFF, 0xCA, 0x65, 0xA1, 0xFB, 0xEE, 0xF2,
- 0x56, 0x1A, 0x16, 0x9E, 0x4D, 0xCA, 0x67, 0x81,
- 0x23, 0xDE, 0xBE, 0x5E, 0x31, 0x56, 0xF0, 0x34,
- 0xBA, 0x12, 0xFC, 0x07, 0x03, 0x96, 0xD2, 0x8E,
- 0xCE, 0xA6, 0xF6, 0x74, 0x07, 0x4F, 0x63, 0x40,
- 0x14, 0x0A, 0xD6, 0x45, 0xB4, 0xF1, 0x72, 0x87,
- 0x34, 0x89, 0x5C, 0x06, 0x1B, 0x8C, 0x0E, 0xA2,
- 0x84, 0x50, 0x12, 0xAD, 0x26, 0x5B, 0x4F, 0x6B,
- 0x23, 0x9D, 0x3C, 0xBB, 0x8A, 0xDA, 0x08, 0x4B,
- 0x93, 0x47, 0x02, 0x96, 0x76, 0xD4, 0x87, 0xE9,
- 0x4B, 0x69, 0x82, 0xD6, 0xCC, 0x69, 0x02, 0xC0,
- 0xA4, 0x75, 0x7A, 0x90, 0xFD, 0xF6, 0xD6, 0x9D,
- 0xE2, 0x4C, 0xB6, 0xFA, 0x61, 0xA5, 0x7C, 0x18,
- 0xEA, 0x84, 0xA1, 0x74, 0x85, 0x2E, 0xCA, 0xF9,
- 0x17, 0x29, 0xFF, 0x67, 0x70, 0xC9, 0x6F, 0xF1,
- 0x41, 0xEF, 0xA1, 0x59, 0x54, 0xA0, 0x99, 0x14,
- 0x48, 0x74, 0x5D, 0x14, 0x3E, 0x04, 0xCE, 0xF7,
- 0x16, 0x9F, 0x8A, 0x41, 0xF4, 0xAE, 0xB3, 0x10,
- 0xCE, 0x19, 0xC2, 0x83, 0x7B, 0xD0, 0x26, 0x1E,
- 0x75, 0x8A, 0x0A, 0x40, 0x4A, 0xB8, 0xE0, 0x5C,
- 0x13, 0x8B, 0xCC, 0x6F, 0xF3, 0x00, 0xB3, 0x64,
- 0x1B, 0x3C, 0x3D, 0x08, 0x3B, 0x9F, 0xD0, 0x9B,
- 0xE5, 0x72, 0x45, 0x96, 0x95, 0x4D, 0x66, 0xC7,
- 0x79, 0x5D, 0x3A, 0x1A, 0x94, 0x64, 0x94, 0x07,
- 0x1A, 0xE8, 0x7C, 0xD1, 0x1C, 0xB1, 0x7E, 0x32,
- 0x28, 0x1A, 0x90, 0x22, 0xD9, 0x86, 0x9B, 0x9C,
- 0x9B, 0x0C, 0x04, 0x31, 0x85, 0x10, 0x42, 0x50,
- 0x40, 0x11, 0x72, 0xAB, 0x94, 0x0C, 0xAF, 0xC3,
- 0x22, 0x1A, 0xC1, 0x31, 0x25, 0x30, 0x23, 0x06,
- 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
- 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0xFD, 0x78,
- 0xA7, 0x70, 0x1F, 0x8A, 0xE9, 0x07, 0xB9, 0xCA,
- 0x3C, 0xD1, 0xE8, 0xDC, 0x68, 0xFF, 0x02, 0x61,
- 0x29, 0x97, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09,
- 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05,
- 0x00, 0x04, 0x14, 0x22, 0x7E, 0x99, 0x10, 0xB3,
- 0x99, 0x79, 0xE7, 0x14, 0x7F, 0x91, 0x59, 0x24,
- 0x4F, 0x2F, 0xCF, 0xE8, 0x53, 0x1D, 0x0F, 0x04,
- 0x08, 0x30, 0x1E, 0x5C, 0xE4, 0x3C, 0x66, 0xDF,
- 0xB0, 0x02, 0x02, 0x08, 0x00]
-};
-
-gTestSuite.doTestWithCertificate(
- new Blob([new Uint8Array(testCertInfo.blob)]),
- testCertInfo.password,
- testCertInfo.nickname,
- testCertInfo.usage
-);
diff --git a/dom/wifi/test/marionette/test_wifi_manage_server_certificate.js b/dom/wifi/test/marionette/test_wifi_manage_server_certificate.js
deleted file mode 100644
index dfaf524b2..000000000
--- a/dom/wifi/test/marionette/test_wifi_manage_server_certificate.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-// Binary form of test certificate.
-var testCertInfo = {
- nickname: 'Test Certificate',
- password: '',
- usage: ['ServerCert'],
- blob: [0x30, 0x82, 0x02, 0xae, 0x30, 0x82, 0x02, 0x17,
- 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
- 0x92, 0x49, 0xe2, 0x62, 0x71, 0xf6, 0xc7, 0x92,
- 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
- 0x70, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x54, 0x57, 0x31, 0x0f,
- 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
- 0x06, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x31,
- 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a,
- 0x0c, 0x07, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c,
- 0x61, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x0b, 0x0c, 0x02, 0x51, 0x41, 0x31, 0x0e,
- 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
- 0x05, 0x47, 0x65, 0x72, 0x72, 0x79, 0x31, 0x21,
- 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x67,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x40, 0x6d, 0x6f,
- 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0x2e, 0x63, 0x6f,
- 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30,
- 0x35, 0x32, 0x33, 0x30, 0x39, 0x34, 0x32, 0x33,
- 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x35,
- 0x32, 0x32, 0x30, 0x39, 0x34, 0x32, 0x33, 0x37,
- 0x5a, 0x30, 0x70, 0x31, 0x0b, 0x30, 0x09, 0x06,
- 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, 0x57,
- 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04,
- 0x08, 0x0c, 0x06, 0x54, 0x61, 0x69, 0x70, 0x65,
- 0x69, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
- 0x04, 0x0a, 0x0c, 0x07, 0x4d, 0x6f, 0x7a, 0x69,
- 0x6c, 0x6c, 0x61, 0x31, 0x0b, 0x30, 0x09, 0x06,
- 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x02, 0x51, 0x41,
- 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04,
- 0x03, 0x0c, 0x05, 0x47, 0x65, 0x72, 0x72, 0x79,
- 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
- 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
- 0x12, 0x67, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x40,
- 0x6d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0x2e,
- 0x63, 0x6f, 0x6d, 0x30, 0x81, 0x9f, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
- 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xd3, 0xdb, 0x54, 0xcc, 0xca, 0x0b, 0xee, 0xf9,
- 0x8a, 0x37, 0x0d, 0x06, 0x8b, 0x20, 0x00, 0x4a,
- 0x55, 0x84, 0x90, 0x1a, 0xb7, 0x9c, 0x91, 0xb2,
- 0x38, 0x6b, 0x8b, 0x32, 0x7a, 0x89, 0x9e, 0x79,
- 0x71, 0x88, 0x43, 0x21, 0x94, 0x18, 0xa8, 0xfc,
- 0xe3, 0x7a, 0x8a, 0xb3, 0xa1, 0xf7, 0x23, 0xe7,
- 0x1a, 0xe3, 0xe7, 0x0d, 0xf1, 0x66, 0x21, 0x58,
- 0x21, 0x85, 0x5b, 0x35, 0xec, 0x68, 0xd2, 0xfd,
- 0x44, 0x76, 0x93, 0x05, 0xbb, 0x89, 0x7d, 0x92,
- 0xf9, 0xce, 0x75, 0xa3, 0xeb, 0x39, 0xc1, 0x7d,
- 0x7e, 0x50, 0xf9, 0xb8, 0x60, 0x61, 0xf7, 0x2f,
- 0x54, 0x39, 0xfe, 0x8a, 0x20, 0xb2, 0x0d, 0x48,
- 0x7f, 0x18, 0x0d, 0x02, 0xcc, 0x7b, 0x8e, 0x31,
- 0xe9, 0xbe, 0xfc, 0x96, 0x2e, 0x63, 0x6f, 0xfa,
- 0x4c, 0xc4, 0xcf, 0x8a, 0xe4, 0x13, 0x67, 0xf1,
- 0xec, 0x3e, 0xd8, 0x23, 0xa1, 0xbf, 0x67, 0x71,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30,
- 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
- 0x04, 0x16, 0x04, 0x14, 0x13, 0xe1, 0xac, 0xa4,
- 0x75, 0x3d, 0x2c, 0x5f, 0xe5, 0x41, 0x42, 0x90,
- 0x5a, 0x48, 0x5c, 0x46, 0xbc, 0x24, 0x8e, 0xa1,
- 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
- 0x18, 0x30, 0x16, 0x80, 0x14, 0x13, 0xe1, 0xac,
- 0xa4, 0x75, 0x3d, 0x2c, 0x5f, 0xe5, 0x41, 0x42,
- 0x90, 0x5a, 0x48, 0x5c, 0x46, 0xbc, 0x24, 0x8e,
- 0xa1, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
- 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0xaa, 0x6b, 0x62, 0x53, 0x74, 0x2a,
- 0x20, 0x76, 0xab, 0xd2, 0x60, 0x06, 0xfd, 0x88,
- 0xf5, 0x1c, 0x85, 0xe6, 0x57, 0xf1, 0xf0, 0x18,
- 0x97, 0x7c, 0x70, 0xb8, 0xb4, 0x7c, 0xcc, 0x58,
- 0x8d, 0xf4, 0x7c, 0xb6, 0x34, 0xcc, 0x15, 0x79,
- 0xaf, 0x75, 0xa9, 0x0b, 0xd1, 0xea, 0xf8, 0x85,
- 0x7c, 0xe8, 0x19, 0xe9, 0x13, 0x90, 0x84, 0x5f,
- 0x21, 0x94, 0x0a, 0x4d, 0x15, 0xef, 0xd1, 0x16,
- 0xd4, 0xba, 0x2c, 0x59, 0x1b, 0x83, 0x23, 0xf5,
- 0xa5, 0xcd, 0xbd, 0xda, 0x32, 0x73, 0x46, 0x49,
- 0x98, 0xf3, 0xfb, 0x50, 0x6e, 0x30, 0xd7, 0x3e,
- 0x31, 0xd6, 0xe8, 0x65, 0x2f, 0x5a, 0xf1, 0x0f,
- 0x7b, 0x0a, 0x21, 0x61, 0x8e, 0x45, 0x29, 0x4f,
- 0x7a, 0x04, 0xda, 0x29, 0xfc, 0x6f, 0xc5, 0x5e,
- 0xee, 0xe1, 0x0f, 0xd5, 0x4b, 0xb7, 0xc9, 0x6a,
- 0x8e, 0x7c, 0x19, 0xef, 0x6e, 0x64, 0x98, 0xfe,
- 0xe3, 0x35]
-};
-
-gTestSuite.doTestWithCertificate(
- new Blob([new Uint8Array(testCertInfo.blob)]),
- testCertInfo.password,
- testCertInfo.nickname,
- testCertInfo.usage
-);
diff --git a/dom/wifi/test/marionette/test_wifi_manage_user_certificate.js b/dom/wifi/test/marionette/test_wifi_manage_user_certificate.js
deleted file mode 100644
index 950ceae4e..000000000
--- a/dom/wifi/test/marionette/test_wifi_manage_user_certificate.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-// Binary form of test certificate.
-var testCertInfo = {
- nickname: 'Test Certificate',
- password: '',
- usage: ['UserCert'],
- blob: '-----BEGIN CERTIFICATE-----\n' +
- 'MIICTjCCAbegAwIBAgICNV4wDQYJKoZIhvcNAQEEBQAwgYUxCzAJBgNVBAYTAklU\n' +
- 'MRYwFAYDVQQKEw1aZXJvc2hlbGwubmV0MRAwDgYDVQQLEwdFeGFtcGxlMR0wGwYD\n' +
- 'VQQDExRaZXJvU2hlbGwgRXhhbXBsZSBDQTEtMCsGCSqGSIb3DQEJARYeRnVsdmlv\n' +
- 'LlJpY2NpYXJkaUB6ZXJvc2hlbGwubmV0MB4XDTEzMDMxMTAzMzg1MloXDTE0MDMx\n' +
- 'MTAzMzg1MlowIzEOMAwGA1UECxMFVXNlcnMxETAPBgNVBAMTCGNodWNrbGVlMIGf\n' +
- 'MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvVzFhQAVqAIHW5DlAhp4FEGEei7k7\n' +
- 'uVUeqkH7JAsww6zmDLg9yZlcZAc95N0lkz022gLXehH2M0R1FOR++nkqofzWfc7w\n' +
- 'n79ith+dU2GQMeKq7vPGDYXpgIkEKbYfzKj3fY3129MlTxJQt1UD/ejz38V8HKgw\n' +
- 'qKSuwo0NVeY66QIDAQABoy4wLDALBgNVHQ8EBAMCBLAwHQYDVR0lBBYwFAYIKwYB\n' +
- 'BQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBAUAA4GBAJWgfX5vYSD7MGZk1rTF\n' +
- 'DSziWYGqpR+Moo3qQ+9qLG8m+XVM9hckWpY31A5sWAeCZCe1SSNLFbbgsaOyPZE2\n' +
- 'NqMyvs61Vszpc2mmWAYT6j2OU2tw8p5pcUZd6eIp7Gc3fLymiX/WoSmilZKmrGUZ\n' +
- 'Q15R+TCpclUsaNrUGjybgaw7\n' +
- '-----END CERTIFICATE-----'
-};
-
-gTestSuite.doTestWithCertificate(
- new Blob([testCertInfo.blob]),
- testCertInfo.password,
- testCertInfo.nickname,
- testCertInfo.usage
-);
diff --git a/dom/wifi/test/marionette/test_wifi_scan.js b/dom/wifi/test/marionette/test_wifi_scan.js
deleted file mode 100644
index 4bb7d1a3d..000000000
--- a/dom/wifi/test/marionette/test_wifi_scan.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const SCAN_RETRY_CNT = 5;
-
-/**
- * Test scan with no AP present.
- *
- * The precondition is:
- * 1) Wifi is enabled.
- * 2) All the hostapds are turned off.
- *
- * @return deferred promise.
- */
-function testScanNoAp() {
- return gTestSuite.testWifiScanWithRetry(SCAN_RETRY_CNT, []);
-}
-
-/**
- * Test scan with APs present.
- *
- * The precondition is:
- * 1) Wifi is enabled.
- * 2) All the hostapds are turned off.
- *
- * @return deferred promise.
- */
-function testScanWithAps() {
- return gTestSuite.startHostapds(HOSTAPD_CONFIG_LIST)
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', HOSTAPD_CONFIG_LIST.length))
- .then(() => gTestSuite.testWifiScanWithRetry(SCAN_RETRY_CNT, HOSTAPD_CONFIG_LIST))
- .then(gTestSuite.killAllHostapd)
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', 0));
-}
-
-gTestSuite.doTestWithoutStockAp(function() {
- return gTestSuite.ensureWifiEnabled(true)
- .then(testScanNoAp)
- .then(testScanWithAps);
-});
diff --git a/dom/wifi/test/marionette/test_wifi_static_ip.js b/dom/wifi/test/marionette/test_wifi_static_ip.js
deleted file mode 100644
index 90436b6fe..000000000
--- a/dom/wifi/test/marionette/test_wifi_static_ip.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const STATIC_IP_CONFIG = {
- enabled: true,
- ipaddr: "192.168.111.222",
- proxy: "",
- maskLength: 24,
- gateway: "192.168.111.1",
- dns1: "8.8.8.8",
- dns2: "8.8.4.4",
-};
-
-const TESTING_HOSTAPD = [{ ssid: 'ap0' }];
-
-function testAssociateWithStaticIp(aNetwork, aStaticIpConfig) {
- return gTestSuite.setStaticIpMode(aNetwork, aStaticIpConfig)
- .then(() => gTestSuite.testAssociate(aNetwork))
- // Check ip address and prefix.
- .then(() => gTestSuite.exeAndParseNetcfg())
- .then((aResult) => {
- is(aResult["wlan0"].ip, aStaticIpConfig.ipaddr, "Check ip address");
- is(aResult["wlan0"].prefix, aStaticIpConfig.maskLength, "Check prefix");
- })
- // Check routing.
- .then(() => gTestSuite.exeAndParseIpRoute())
- .then((aResult) => {
- is(aResult["wlan0"].src, aStaticIpConfig.ipaddr, "Check ip address");
- is(aResult["wlan0"].default, true, "Check default route");
- is(aResult["wlan0"].gateway, aStaticIpConfig.gateway, "Check gateway");
- });
-}
-
-function findDesireNetwork(aNetworks) {
- let i = gTestSuite.getFirstIndexBySsid(TESTING_HOSTAPD[0].ssid, aNetworks);
-
- if (-1 !== i) {
- return aNetworks[i];
- }
-
- return aNetworks[0];
-}
-
-// Start test.
-gTestSuite.doTestWithoutStockAp(function() {
- return gTestSuite.ensureWifiEnabled(true)
-
- // Start custom hostapd for testing.
- .then(() => gTestSuite.startHostapds(TESTING_HOSTAPD))
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd',
- TESTING_HOSTAPD.length))
-
- // Perform a wifi scan, and then run the static ip test
- .then(() => gTestSuite.requestWifiScan())
- .then((aNetworks) => findDesireNetwork(aNetworks))
- .then((aNetwork) => testAssociateWithStaticIp(aNetwork,
- STATIC_IP_CONFIG))
-
- // Kill running hostapd.
- .then(gTestSuite.killAllHostapd)
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', 0));
-});
diff --git a/dom/wifi/test/marionette/test_wifi_tethering_wifi_active.js b/dom/wifi/test/marionette/test_wifi_tethering_wifi_active.js
deleted file mode 100644
index af0df01a0..000000000
--- a/dom/wifi/test/marionette/test_wifi_tethering_wifi_active.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const TESTING_HOSTAPD = [{ ssid: 'ap0' }];
-
-function connectToFirstNetwork() {
- let firstNetwork;
- return gTestSuite.requestWifiScan()
- .then(function (networks) {
- firstNetwork = networks[0];
- return gTestSuite.testAssociate(firstNetwork);
- })
- .then(() => firstNetwork);
-}
-
-gTestSuite.doTestTethering(function() {
- let firstNetwork;
-
- return gTestSuite.ensureWifiEnabled(true)
- // Start custom hostapd for testing.
- .then(() => gTestSuite.startHostapds(TESTING_HOSTAPD))
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', TESTING_HOSTAPD.length))
-
- // Connect to the testing AP and wait for data becoming disconnected.
- .then(function () {
- return Promise.all([
- // 1) Set up the event listener first:
- // RIL data should become disconnected after connecting to wifi.
- gTestSuite.waitForRilDataConnected(false),
-
- // 2) Connect to the first scanned network.
- connectToFirstNetwork()
- .then(aFirstNetwork => firstNetwork = aFirstNetwork)
- ]);
- })
- .then(function() {
- return Promise.all([
- // 1) Set up the event listeners first:
- // Wifi should be turned off and RIL data should be connected.
- gTestSuite.waitForWifiManagerEventOnce('disabled'),
- gTestSuite.waitForRilDataConnected(true),
-
- // 2) Start wifi tethering.
- gTestSuite.requestTetheringEnabled(true)
- ]);
- })
- .then(function() {
- return Promise.all([
- // 1) Set up the event listeners first:
- // Wifi should be enabled, RIL data should become disconnected and
- // we should connect to an wifi AP.
- gTestSuite.waitForWifiManagerEventOnce('enabled'),
-
- // Due to Bug 1168285, after re-enablin wifi, the remembered network
- // will not be connected automatically. Leave "auto connect test"
- // covered by test_wifi_auto_connect.js.
- //gTestSuite.waitForRilDataConnected(false),
- //gTestSuite.waitForConnected(firstNetwork),
-
- // 2) Stop wifi tethering.
- gTestSuite.requestTetheringEnabled(false)
- ]);
- })
- // Remove wlan0 from default route by disabling wifi. Otherwise,
- // it will cause the subsequent test cases loading page error.
- .then(() => gTestSuite.requestWifiEnabled(false))
-
- // Kill running hostapd.
- .then(gTestSuite.killAllHostapd)
- .then(() => gTestSuite.verifyNumOfProcesses('hostapd', 0));
-}); \ No newline at end of file
diff --git a/dom/wifi/test/marionette/test_wifi_tethering_wifi_disabled.js b/dom/wifi/test/marionette/test_wifi_tethering_wifi_disabled.js
deleted file mode 100644
index 860a91cf6..000000000
--- a/dom/wifi/test/marionette/test_wifi_tethering_wifi_disabled.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-gTestSuite.doTestTethering(function() {
- return gTestSuite.ensureWifiEnabled(false)
- .then(() => gTestSuite.requestTetheringEnabled(true))
- .then(() => gTestSuite.requestTetheringEnabled(false))
-});
diff --git a/dom/wifi/test/marionette/test_wifi_tethering_wifi_inactive.js b/dom/wifi/test/marionette/test_wifi_tethering_wifi_inactive.js
deleted file mode 100644
index 2de6ab667..000000000
--- a/dom/wifi/test/marionette/test_wifi_tethering_wifi_inactive.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-gTestSuite.doTestTethering(function() {
- return gTestSuite.ensureWifiEnabled(true)
- .then(function() {
- return Promise.all([
- gTestSuite.waitForWifiManagerEventOnce('disabled'),
- gTestSuite.requestTetheringEnabled(true)
- ]);
- })
- .then(function() {
- return Promise.all([
- gTestSuite.waitForWifiManagerEventOnce('enabled'),
- gTestSuite.requestTetheringEnabled(false)
- ]);
- });
-});
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
index 1739f3d31..e1910536f 100644
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -587,7 +587,7 @@ ContentSecurityPolicyAllows(JSContext* aCx)
new LogViolationDetailsRunnable(worker, fileName, lineNum);
ErrorResult rv;
- runnable->Dispatch(rv);
+ runnable->Dispatch(Killing, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
}
@@ -2811,13 +2811,6 @@ WorkerThreadPrimaryRunnable::Run()
}
{
-#ifdef MOZ_ENABLE_PROFILER_SPS
- PseudoStack* stack = mozilla_get_pseudo_stack();
- if (stack) {
- stack->sampleContext(cx);
- }
-#endif
-
{
JSAutoRequest ar(cx);
@@ -2829,12 +2822,6 @@ WorkerThreadPrimaryRunnable::Run()
}
BackgroundChild::CloseForCurrentThread();
-
-#ifdef MOZ_ENABLE_PROFILER_SPS
- if (stack) {
- stack->sampleContext(nullptr);
- }
-#endif
}
// There may still be runnables on the debugger event queue that hold a
diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp
index 46545e737..56b18441e 100644
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -2118,12 +2118,16 @@ LoadAllScripts(WorkerPrivate* aWorkerPrivate,
aWorkerPrivate->AssertIsOnWorkerThread();
NS_ASSERTION(!aLoadInfos.IsEmpty(), "Bad arguments!");
- AutoSyncLoopHolder syncLoop(aWorkerPrivate);
+ AutoSyncLoopHolder syncLoop(aWorkerPrivate, Terminating);
+ nsCOMPtr<nsIEventTarget> syncLoopTarget = syncLoop.GetEventTarget();
+ if (!syncLoopTarget) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
RefPtr<ScriptLoaderRunnable> loader =
- new ScriptLoaderRunnable(aWorkerPrivate, syncLoop.EventTarget(),
- aLoadInfos, aIsMainScript, aWorkerScriptType,
- aRv);
+ new ScriptLoaderRunnable(aWorkerPrivate, syncLoopTarget, aLoadInfos,
+ aIsMainScript, aWorkerScriptType, aRv);
NS_ASSERTION(aLoadInfos.IsEmpty(), "Should have swapped!");
@@ -2184,7 +2188,7 @@ ChannelFromScriptURLWorkerThread(JSContext* aCx,
new ChannelGetterRunnable(aParent, aScriptURL, aChannel);
ErrorResult rv;
- getter->Dispatch(rv);
+ getter->Dispatch(Terminating, rv);
if (rv.Failed()) {
NS_ERROR("Failed to dispatch!");
return rv.StealNSResult();
diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp
index 09b09a24b..1f79e2c92 100644
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -12,6 +12,7 @@
#include "nsINetworkInterceptController.h"
#include "nsIOutputStream.h"
#include "nsIScriptError.h"
+#include "nsITimedChannel.h"
#include "nsIUnicodeDecoder.h"
#include "nsIUnicodeEncoder.h"
#include "nsContentPolicyUtils.h"
@@ -108,6 +109,12 @@ NS_IMETHODIMP
CancelChannelRunnable::Run()
{
MOZ_ASSERT(NS_IsMainThread());
+
+ // TODO: When bug 1204254 is implemented, this time marker should be moved to
+ // the point where the body of the network request is complete.
+ mChannel->SetHandleFetchEventEnd(TimeStamp::Now());
+ mChannel->SaveTimeStampsToUnderlyingChannel();
+
mChannel->Cancel(mStatus);
mRegistration->MaybeScheduleUpdate();
return NS_OK;
@@ -230,6 +237,9 @@ public:
return NS_OK;
}
+ mChannel->SetHandleFetchEventEnd(TimeStamp::Now());
+ mChannel->SaveTimeStampsToUnderlyingChannel();
+
nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
if (obsService) {
obsService->NotifyObservers(underlyingChannel, "service-worker-synthesized-response", nullptr);
@@ -948,10 +958,8 @@ ExtendableEvent::GetPromise()
}
JSContext* cx = jsapi.cx();
- GlobalObject global(cx, globalObj->GetGlobalJSObject());
-
ErrorResult result;
- RefPtr<Promise> p = Promise::All(global, Move(mPromises), result);
+ RefPtr<Promise> p = Promise::All(cx, Move(mPromises), result);
if (NS_WARN_IF(result.MaybeSetPendingException(cx))) {
return nullptr;
}
diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp
index eaa548f95..24b2e11e6 100644
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -13,6 +13,7 @@
#include "nsINetworkInterceptController.h"
#include "nsIPushErrorReporter.h"
#include "nsISupportsImpl.h"
+#include "nsITimedChannel.h"
#include "nsIUploadChannel2.h"
#include "nsNetUtil.h"
#include "nsProxyRelease.h"
@@ -1255,6 +1256,7 @@ class FetchEventRunnable : public ExtendableFunctionalEventWorkerRunnable
nsCString mMethod;
nsString mClientId;
bool mIsReload;
+ bool mMarkLaunchServiceWorkerEnd;
RequestCache mCacheMode;
RequestMode mRequestMode;
RequestRedirect mRequestRedirect;
@@ -1273,13 +1275,15 @@ public:
const nsACString& aScriptSpec,
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration,
const nsAString& aDocumentId,
- bool aIsReload)
+ bool aIsReload,
+ bool aMarkLaunchServiceWorkerEnd)
: ExtendableFunctionalEventWorkerRunnable(
aWorkerPrivate, aKeepAliveToken, aRegistration)
, mInterceptedChannel(aChannel)
, mScriptSpec(aScriptSpec)
, mClientId(aDocumentId)
, mIsReload(aIsReload)
+ , mMarkLaunchServiceWorkerEnd(aMarkLaunchServiceWorkerEnd)
, mCacheMode(RequestCache::Default)
, mRequestMode(RequestMode::No_cors)
, mRequestRedirect(RequestRedirect::Follow)
@@ -1417,6 +1421,12 @@ public:
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
MOZ_ASSERT(aWorkerPrivate);
+
+ if (mMarkLaunchServiceWorkerEnd) {
+ mInterceptedChannel->SetLaunchServiceWorkerEnd(TimeStamp::Now());
+ }
+
+ mInterceptedChannel->SetDispatchFetchEventEnd(TimeStamp::Now());
return DispatchFetchEvent(aCx, aWorkerPrivate);
}
@@ -1445,6 +1455,10 @@ private:
NS_IMETHOD Run() override
{
AssertIsOnMainThread();
+
+ mChannel->SetHandleFetchEventEnd(TimeStamp::Now());
+ mChannel->SaveTimeStampsToUnderlyingChannel();
+
nsresult rv = mChannel->ResetInterception();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to resume intercepted network request");
@@ -1520,6 +1534,8 @@ private:
event->PostInit(mInterceptedChannel, mRegistration, mScriptSpec);
event->SetTrusted(true);
+ mInterceptedChannel->SetHandleFetchEventStart(TimeStamp::Now());
+
RefPtr<EventTarget> target = do_QueryObject(aWorkerPrivate->GlobalScope());
nsresult rv2 = target->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv2)) || !event->WaitToRespond()) {
@@ -1614,9 +1630,21 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
nsCOMPtr<nsIRunnable> failRunnable =
NewRunnableMethod(aChannel, &nsIInterceptedChannel::ResetInterception);
- nsresult rv = SpawnWorkerIfNeeded(FetchEvent, failRunnable, aLoadGroup);
+ aChannel->SetLaunchServiceWorkerStart(TimeStamp::Now());
+ aChannel->SetDispatchFetchEventStart(TimeStamp::Now());
+
+ bool newWorkerCreated = false;
+ nsresult rv = SpawnWorkerIfNeeded(FetchEvent,
+ failRunnable,
+ &newWorkerCreated,
+ aLoadGroup);
+
NS_ENSURE_SUCCESS(rv, rv);
+ if (!newWorkerCreated) {
+ aChannel->SetLaunchServiceWorkerEnd(TimeStamp::Now());
+ }
+
nsMainThreadPtrHandle<nsIInterceptedChannel> handle(
new nsMainThreadPtrHolder<nsIInterceptedChannel>(aChannel, false));
@@ -1646,7 +1674,7 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
RefPtr<FetchEventRunnable> r =
new FetchEventRunnable(mWorkerPrivate, token, handle,
mInfo->ScriptSpec(), regInfo,
- aDocumentId, aIsReload);
+ aDocumentId, aIsReload, newWorkerCreated);
rv = r->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -1669,6 +1697,7 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
nsresult
ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
nsIRunnable* aLoadFailedRunnable,
+ bool* aNewWorkerCreated,
nsILoadGroup* aLoadGroup)
{
AssertIsOnMainThread();
@@ -1679,6 +1708,12 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
// the overriden load group when intercepting a fetch.
MOZ_ASSERT_IF(aWhy == FetchEvent, aLoadGroup);
+ // Defaults to no new worker created, but if there is one, we'll set the value
+ // to true at the end of this function.
+ if (aNewWorkerCreated) {
+ *aNewWorkerCreated = false;
+ }
+
if (mWorkerPrivate) {
mWorkerPrivate->UpdateOverridenLoadGroup(aLoadGroup);
RenewKeepAliveToken(aWhy);
@@ -1762,6 +1797,10 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
RenewKeepAliveToken(aWhy);
+ if (aNewWorkerCreated) {
+ *aNewWorkerCreated = true;
+ }
+
return NS_OK;
}
diff --git a/dom/workers/ServiceWorkerPrivate.h b/dom/workers/ServiceWorkerPrivate.h
index 8d59ea1d0..911b07a11 100644
--- a/dom/workers/ServiceWorkerPrivate.h
+++ b/dom/workers/ServiceWorkerPrivate.h
@@ -189,6 +189,7 @@ private:
nsresult
SpawnWorkerIfNeeded(WakeUpReason aWhy,
nsIRunnable* aLoadFailedRunnable,
+ bool* aNewWorkerCreated = nullptr,
nsILoadGroup* aLoadGroup = nullptr);
~ServiceWorkerPrivate();
diff --git a/dom/workers/WorkerNavigator.cpp b/dom/workers/WorkerNavigator.cpp
index 682c7a22c..f79896881 100644
--- a/dom/workers/WorkerNavigator.cpp
+++ b/dom/workers/WorkerNavigator.cpp
@@ -152,7 +152,7 @@ WorkerNavigator::GetUserAgent(nsString& aUserAgent, ErrorResult& aRv) const
RefPtr<GetUserAgentRunnable> runnable =
new GetUserAgentRunnable(workerPrivate, aUserAgent);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
uint64_t
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index bd8a33032..612090027 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -2419,8 +2419,6 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
MOZ_ASSERT_IF(mIsChromeWorker, mIsSecureContext);
MOZ_ASSERT(IsDedicatedWorker());
- mNowBaseTimeStamp = aParent->NowBaseTimeStamp();
- mNowBaseTimeHighRes = aParent->NowBaseTime();
if (aParent->mParentFrozen) {
Freeze(nullptr);
@@ -2451,18 +2449,6 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
.creationOptions().setSecureContext(true);
}
- if (IsDedicatedWorker() && mLoadInfo.mWindow &&
- mLoadInfo.mWindow->GetPerformance()) {
- mNowBaseTimeStamp = mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()->
- GetNavigationStartTimeStamp();
- mNowBaseTimeHighRes =
- mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()->
- GetNavigationStartHighRes();
- } else {
- mNowBaseTimeStamp = CreationTimeStamp();
- mNowBaseTimeHighRes = CreationTime();
- }
-
// Our parent can get suspended after it initiates the async creation
// of a new worker thread. In this case suspend the new worker as well.
if (mLoadInfo.mWindow && mLoadInfo.mWindow->IsSuspended()) {
@@ -5460,10 +5446,18 @@ WorkerPrivate::CancelAllTimeouts()
}
already_AddRefed<nsIEventTarget>
-WorkerPrivate::CreateNewSyncLoop()
+WorkerPrivate::CreateNewSyncLoop(Status aFailStatus)
{
AssertIsOnWorkerThread();
+ {
+ MutexAutoLock lock(mMutex);
+
+ if (mStatus >= aFailStatus) {
+ return nullptr;
+ }
+ }
+
nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(NS_GetCurrentThread());
MOZ_ASSERT(thread);
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
index 465c0f9a3..20a530205 100644
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -216,8 +216,6 @@ private:
WorkerType mWorkerType;
TimeStamp mCreationTimeStamp;
DOMHighResTimeStamp mCreationTimeHighRes;
- TimeStamp mNowBaseTimeStamp;
- DOMHighResTimeStamp mNowBaseTimeHighRes;
protected:
// The worker is owned by its thread, which is represented here. This is set
@@ -579,14 +577,11 @@ public:
return mCreationTimeHighRes;
}
- TimeStamp NowBaseTimeStamp() const
+ DOMHighResTimeStamp TimeStampToDOMHighRes(const TimeStamp& aTimeStamp) const
{
- return mNowBaseTimeStamp;
- }
-
- DOMHighResTimeStamp NowBaseTime() const
- {
- return mNowBaseTimeHighRes;
+ MOZ_ASSERT(!aTimeStamp.IsNull());
+ TimeDuration duration = aTimeStamp - mCreationTimeStamp;
+ return duration.ToMilliseconds();
}
nsIPrincipal*
@@ -1447,8 +1442,11 @@ private:
memcpy(aPreferences, mPreferences, WORKERPREF_COUNT * sizeof(bool));
}
+ // If the worker shutdown status is equal or greater then aFailStatus, this
+ // operation will fail and nullptr will be returned. See WorkerHolder.h for
+ // more information about the correct value to use.
already_AddRefed<nsIEventTarget>
- CreateNewSyncLoop();
+ CreateNewSyncLoop(Status aFailStatus);
bool
RunCurrentSyncLoop();
@@ -1523,9 +1521,11 @@ class AutoSyncLoopHolder
uint32_t mIndex;
public:
- explicit AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate)
+ // See CreateNewSyncLoop() for more information about the correct value to use
+ // for aFailStatus.
+ AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate, Status aFailStatus)
: mWorkerPrivate(aWorkerPrivate)
- , mTarget(aWorkerPrivate->CreateNewSyncLoop())
+ , mTarget(aWorkerPrivate->CreateNewSyncLoop(aFailStatus))
, mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1)
{
aWorkerPrivate->AssertIsOnWorkerThread();
@@ -1533,7 +1533,7 @@ public:
~AutoSyncLoopHolder()
{
- if (mWorkerPrivate) {
+ if (mWorkerPrivate && mTarget) {
mWorkerPrivate->AssertIsOnWorkerThread();
mWorkerPrivate->StopSyncLoop(mTarget, false);
mWorkerPrivate->DestroySyncLoop(mIndex);
@@ -1552,8 +1552,9 @@ public:
}
nsIEventTarget*
- EventTarget() const
+ GetEventTarget() const
{
+ // This can be null if CreateNewSyncLoop() fails.
return mTarget;
}
};
diff --git a/dom/workers/WorkerRunnable.cpp b/dom/workers/WorkerRunnable.cpp
index 1e16d7254..6bbe40f66 100644
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -568,15 +568,20 @@ WorkerMainThreadRunnable::WorkerMainThreadRunnable(WorkerPrivate* aWorkerPrivate
}
void
-WorkerMainThreadRunnable::Dispatch(ErrorResult& aRv)
+WorkerMainThreadRunnable::Dispatch(Status aFailStatus, ErrorResult& aRv)
{
mWorkerPrivate->AssertIsOnWorkerThread();
TimeStamp startTime = TimeStamp::NowLoRes();
- AutoSyncLoopHolder syncLoop(mWorkerPrivate);
+ AutoSyncLoopHolder syncLoop(mWorkerPrivate, aFailStatus);
- mSyncLoopTarget = syncLoop.EventTarget();
+ mSyncLoopTarget = syncLoop.GetEventTarget();
+ if (!mSyncLoopTarget) {
+ // SyncLoop creation can fail if the worker is shutting down.
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
DebugOnly<nsresult> rv = mWorkerPrivate->DispatchToMainThread(this);
MOZ_ASSERT(NS_SUCCEEDED(rv),
@@ -621,7 +626,7 @@ bool
WorkerCheckAPIExposureOnMainThreadRunnable::Dispatch()
{
ErrorResult rv;
- WorkerMainThreadRunnable::Dispatch(rv);
+ WorkerMainThreadRunnable::Dispatch(Terminating, rv);
bool ok = !rv.Failed();
rv.SuppressException();
return ok;
diff --git a/dom/workers/WorkerRunnable.h b/dom/workers/WorkerRunnable.h
index c65060f44..8249a8053 100644
--- a/dom/workers/WorkerRunnable.h
+++ b/dom/workers/WorkerRunnable.h
@@ -401,9 +401,12 @@ protected:
public:
// Dispatch the runnable to the main thread. If dispatch to main thread
- // fails, or if the worker is shut down while dispatching, an error will be
- // reported on aRv. In that case the error MUST be propagated out to script.
- void Dispatch(ErrorResult& aRv);
+ // fails, or if the worker is in a state equal or greater of aFailStatus, an
+ // error will be reported on aRv. Normally you want to use 'Terminating' for
+ // aFailStatus, except if you want an infallible runnable. In this case, use
+ // 'Killing'.
+ // In that case the error MUST be propagated out to script.
+ void Dispatch(Status aFailStatus, ErrorResult& aRv);
private:
NS_IMETHOD Run() override;
diff --git a/dom/workers/test/serviceworkers/chrome.ini b/dom/workers/test/serviceworkers/chrome.ini
index e064e7fd0..6d7dbebd0 100644
--- a/dom/workers/test/serviceworkers/chrome.ini
+++ b/dom/workers/test/serviceworkers/chrome.ini
@@ -3,6 +3,8 @@ skip-if = os == 'android'
support-files =
chrome_helpers.js
empty.js
+ fetch.js
+ hello.html
serviceworker.html
serviceworkerinfo_iframe.html
serviceworkermanager_iframe.html
@@ -10,6 +12,7 @@ support-files =
worker.js
worker2.js
+[test_devtools_serviceworker_interception.html]
[test_privateBrowsing.html]
[test_serviceworkerinfo.xul]
[test_serviceworkermanager.xul]
diff --git a/dom/workers/test/serviceworkers/fetch_event_worker.js b/dom/workers/test/serviceworkers/fetch_event_worker.js
index 1caef71e8..895128e2c 100644
--- a/dom/workers/test/serviceworkers/fetch_event_worker.js
+++ b/dom/workers/test/serviceworkers/fetch_event_worker.js
@@ -148,28 +148,21 @@ onfetch = function(ev) {
}
else if (ev.request.url.includes("navigate.html")) {
- var navigateModeCorrectlyChecked = false;
var requests = [ // should not throw
new Request(ev.request),
new Request(ev.request, undefined),
new Request(ev.request, null),
new Request(ev.request, {}),
new Request(ev.request, {someUnrelatedProperty: 42}),
+ new Request(ev.request, {method: "GET"}),
];
- try {
- var request3 = new Request(ev.request, {method: "GET"}); // should throw
- } catch(e) {
- navigateModeCorrectlyChecked = requests[0].mode == "navigate";
- }
- if (navigateModeCorrectlyChecked) {
- ev.respondWith(Promise.resolve(
- new Response("<script>window.frameElement.test_result = true;</script>", {
- headers : {
- "Content-Type": "text/html"
- }
- })
- ));
- }
+ ev.respondWith(Promise.resolve(
+ new Response("<script>window.frameElement.test_result = true;</script>", {
+ headers : {
+ "Content-Type": "text/html"
+ }
+ })
+ ));
}
else if (ev.request.url.includes("nonexistent_worker_script.js")) {
diff --git a/dom/workers/test/serviceworkers/test_devtools_serviceworker_interception.html b/dom/workers/test/serviceworkers/test_devtools_serviceworker_interception.html
new file mode 100644
index 000000000..d49ebb2c9
--- /dev/null
+++ b/dom/workers/test/serviceworkers/test_devtools_serviceworker_interception.html
@@ -0,0 +1,168 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug 1168875 - test devtools serviceworker interception.</title>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet"
+ type="text/css"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+// Constants
+const Ci = Components.interfaces;
+const workerScope = "http://mochi.test:8888/chrome/dom/workers/test/serviceworkers/";
+const workerURL = workerScope + "fetch.js";
+const contentPage = workerScope + "hello.html";
+
+function createTestWindow(aURL) {
+ var mainwindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShellTreeItem)
+ .rootTreeItem
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow);
+ var win = mainwindow.OpenBrowserWindow(contentPage);
+
+ return new Promise(aResolve => {
+ win.addEventListener("DOMContentLoaded", function callback() {
+ if (win.content.location.href != aURL) {
+ win.gBrowser.loadURI(aURL);
+ return;
+ }
+
+ win.removeEventListener("DOMContentLoaded", callback);
+ aResolve(win.content);
+ });
+ });
+}
+
+function executeTest(aWindow) {
+ var registration;
+
+ return Promise.resolve()
+ // Should not be intercepted.
+ .then(_ => fetchAndCheckTimedChannel(aWindow, false, true, "hello.html"))
+
+ // Regist a service worker.
+ .then(_ => register(aWindow, workerURL, workerScope))
+ .then(r => registration = r)
+
+ // Should be intercpeted and synthesized.
+ .then(_ => fetchAndCheckTimedChannel(aWindow, true, false, "fake.html"))
+
+ // Should be intercepted but still fetch from network.
+ .then(_ => fetchAndCheckTimedChannel(aWindow, true, true,
+ "hello.html?ForBypassingHttpCache"))
+
+ // Tear down
+ .then(_ => registration.unregister());
+}
+
+function register(aWindow, aURL, aScope) {
+ return aWindow.navigator.serviceWorker.register(aURL, {scope: aScope})
+ .then(r => {
+ var worker = r.installing;
+ return new Promise(function(aResolve) {
+ worker.onstatechange = function() {
+ if (worker.state == "activated") {
+ aResolve(r);
+ }
+ }
+ });
+ });
+}
+
+function fetchAndCheckTimedChannel(aWindow, aIntercepted, aFetch, aURL) {
+ var resolveFunction;
+ var promise = new Promise(aResolve => resolveFunction = aResolve);
+
+ var topic = aFetch ? "http-on-examine-response"
+ : "service-worker-synthesized-response";
+
+ function observer(aSubject) {
+ var channel = aSubject.QueryInterface(Ci.nsIChannel);
+ ok(channel.URI.spec.endsWith(aURL));
+
+ var tc = aSubject.QueryInterface(Ci.nsITimedChannel);
+
+ // Check service worker related timings.
+ var serviceWorkerTimings = [{start: tc.launchServiceWorkerStartTime,
+ end: tc.launchServiceWorkerEndTime},
+ {start: tc.dispatchFetchEventStartTime,
+ end: tc.dispatchFetchEventEndTime},
+ {start: tc.handleFetchEventStartTime,
+ end: tc.handleFetchEventEndTime}];
+ if (aIntercepted) {
+ serviceWorkerTimings.reduce((aPreviousTimings, aCurrentTimings) => {
+ ok(aPreviousTimings.start <= aCurrentTimings.start,
+ "Start time order check.");
+ ok(aPreviousTimings.end <= aCurrentTimings.end,
+ "End time order check.");
+ ok(aCurrentTimings.start <= aCurrentTimings.end,
+ "Start time should be smaller than end time.");
+ return aCurrentTimings;
+ });
+ } else {
+ serviceWorkerTimings.forEach(aTimings => {
+ is(aTimings.start, 0);
+ is(aTimings.end, 0);
+ });
+ }
+
+ // Check network related timings.
+ var networkTimings = [tc.domainLookupStartTime,
+ tc.domainLookupEndTime,
+ tc.connectStartTime,
+ tc.connectEndTime,
+ tc.requestStartTime,
+ tc.responseStartTime,
+ tc.responseEndTime];
+ if (aFetch) {
+ networkTimings.reduce((aPreviousTiming, aCurrentTiming) => {
+ ok(aPreviousTiming <= aCurrentTiming);
+ return aCurrentTiming;
+ });
+ } else {
+ networkTimings.forEach(aTiming => is(aTiming, 0));
+ }
+
+ SpecialPowers.removeObserver(observer, topic);
+ resolveFunction();
+ }
+
+ SpecialPowers.addObserver(observer, topic, false);
+
+ // return promise;
+ return Promise.all([aWindow.fetch(aURL), promise]);
+}
+
+function runTest() {
+ return Promise.resolve()
+ .then(_ => createTestWindow(contentPage))
+ .then(w => executeTest(w))
+ .catch(e => ok(false, "Some test failed with error " + e))
+ .then(_ => SimpleTest.finish());
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [
+ ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+ ["dom.serviceWorkers.enabled", true],
+ ["dom.serviceWorkers.testing.enabled", true],
+]}, runTest);
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
index 9dbfcc099..b337b13ba 100644
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
@@ -38,7 +38,7 @@ var ecmaGlobals =
"Int32Array",
"Int8Array",
"InternalError",
- {name: "Intl", android: false},
+ "Intl",
"Iterator",
"JSON",
"Map",
@@ -172,9 +172,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceMeasure",
// IMPORTANT: Do not change this list without review from a DOM peer!
- { name: "PerformanceObserver", nightly: true },
+ "PerformanceObserver",
// IMPORTANT: Do not change this list without review from a DOM peer!
- { name: "PerformanceObserverEntryList", nightly: true },
+ "PerformanceObserverEntryList",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Request",
// IMPORTANT: Do not change this list without review from a DOM peer!
diff --git a/dom/workers/test/test_worker_interfaces.js b/dom/workers/test/test_worker_interfaces.js
index e0647682c..159278f9a 100644
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -38,7 +38,7 @@ var ecmaGlobals =
"Int32Array",
"Int8Array",
"InternalError",
- {name: "Intl", android: false},
+ "Intl",
"Iterator",
"JSON",
"Map",
@@ -163,9 +163,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceMeasure",
// IMPORTANT: Do not change this list without review from a DOM peer!
- { name: "PerformanceObserver", nightly: true },
+ "PerformanceObserver",
// IMPORTANT: Do not change this list without review from a DOM peer!
- { name: "PerformanceObserverEntryList", nightly: true },
+ "PerformanceObserverEntryList",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Request",
// IMPORTANT: Do not change this list without review from a DOM peer!
diff --git a/dom/xbl/nsXBLBinding.cpp b/dom/xbl/nsXBLBinding.cpp
index 6ae17c4c0..d9a2aacc5 100644
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -1014,7 +1014,17 @@ nsXBLBinding::DoInitJSClass(JSContext *cx,
NS_ENSURE_TRUE(xblScope, NS_ERROR_UNEXPECTED);
JS::Rooted<JSObject*> parent_proto(cx);
- if (!JS_GetPrototype(cx, obj, &parent_proto)) {
+ {
+ JS::RootedObject wrapped(cx, obj);
+ JSAutoCompartment ac(cx, xblScope);
+ if (!JS_WrapObject(cx, &wrapped)) {
+ return NS_ERROR_FAILURE;
+ }
+ if (!JS_GetPrototype(cx, wrapped, &parent_proto)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ if (!JS_WrapObject(cx, &parent_proto)) {
return NS_ERROR_FAILURE;
}
diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp
index a47a01aa0..4fd34a993 100644
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -1081,10 +1081,75 @@ XMLHttpRequestMainThread::CloseRequestWithError(const ProgressEventType aType)
}
void
-XMLHttpRequestMainThread::Abort(ErrorResult& arv)
+XMLHttpRequestMainThread::RequestErrorSteps(const ProgressEventType aEventType,
+ const nsresult aOptionalException,
+ ErrorResult& aRv)
+{
+ // Step 1
+ mState = State::done;
+
+ StopProgressEventTimer();
+
+ // Step 2
+ mFlagSend = false;
+
+ // Step 3
+ ResetResponse();
+
+ // If we're in the destructor, don't risk dispatching an event.
+ if (mFlagDeleted) {
+ mFlagSyncLooping = false;
+ return;
+ }
+
+ // Step 4
+ if (mFlagSynchronous && NS_FAILED(aOptionalException)) {
+ aRv.Throw(aOptionalException);
+ return;
+ }
+
+ // Step 5
+ FireReadystatechangeEvent();
+
+ // Step 6
+ if (mUpload && !mUploadComplete) {
+
+ // Step 6-1
+ mUploadComplete = true;
+
+ // Step 6-2
+ if (mFlagHadUploadListenersOnSend) {
+
+ // Steps 6-3, 6-4 (loadend is fired for us)
+ DispatchProgressEvent(mUpload, aEventType, 0, -1);
+ }
+ }
+
+ // Steps 7 and 8 (loadend is fired for us)
+ DispatchProgressEvent(this, aEventType, 0, -1);
+}
+
+void
+XMLHttpRequestMainThread::Abort(ErrorResult& aRv)
{
mFlagAborted = true;
- CloseRequestWithError(ProgressEventType::abort);
+
+ // Step 1
+ CloseRequest();
+
+ // Step 2
+ if ((mState == State::opened && mFlagSend) ||
+ mState == State::headers_received ||
+ mState == State::loading) {
+ RequestErrorSteps(ProgressEventType::abort, NS_OK, aRv);
+ }
+
+ // Step 3
+ if (mState == State::done) {
+ ChangeState(State::unsent, false); // no ReadystateChange event
+ }
+
+ mFlagSyncLooping = false;
}
NS_IMETHODIMP
diff --git a/dom/xhr/XMLHttpRequestMainThread.h b/dom/xhr/XMLHttpRequestMainThread.h
index c9bcddf99..68499874a 100644
--- a/dom/xhr/XMLHttpRequestMainThread.h
+++ b/dom/xhr/XMLHttpRequestMainThread.h
@@ -397,6 +397,11 @@ public:
}
void
+ RequestErrorSteps(const ProgressEventType aEventType,
+ const nsresult aOptionalException,
+ ErrorResult& aRv);
+
+ void
Abort() {
ErrorResult rv;
Abort(rv);
diff --git a/dom/xhr/XMLHttpRequestWorker.cpp b/dom/xhr/XMLHttpRequestWorker.cpp
index 93b93a2b1..c9e892f26 100644
--- a/dom/xhr/XMLHttpRequestWorker.cpp
+++ b/dom/xhr/XMLHttpRequestWorker.cpp
@@ -208,9 +208,9 @@ public:
}
void
- Dispatch(ErrorResult& aRv)
+ Dispatch(Status aFailStatus, ErrorResult& aRv)
{
- WorkerMainThreadRunnable::Dispatch(aRv);
+ WorkerMainThreadRunnable::Dispatch(aFailStatus, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -1633,11 +1633,10 @@ XMLHttpRequestWorker::ReleaseProxy(ReleaseType aType)
new SyncTeardownRunnable(mWorkerPrivate, mProxy);
mProxy = nullptr;
- ErrorResult forAssertionsOnly;
- runnable->Dispatch(forAssertionsOnly);
- if (forAssertionsOnly.Failed()) {
- NS_ERROR("Failed to dispatch teardown runnable!");
- }
+ IgnoredErrorResult forAssertionsOnly;
+ // This runnable _must_ be executed.
+ runnable->Dispatch(Dead, forAssertionsOnly);
+ MOZ_DIAGNOSTIC_ASSERT(!forAssertionsOnly.Failed());
}
}
}
@@ -1669,7 +1668,9 @@ XMLHttpRequestWorker::MaybeDispatchPrematureAbortEvents(ErrorResult& aRv)
// Only send readystatechange event when state changed.
bool isStateChanged = false;
- if (mStateData.mReadyState != 4) {
+ if ((mStateData.mReadyState == 1 && mStateData.mFlagSend) ||
+ mStateData.mReadyState == 2 ||
+ mStateData.mReadyState == 3) {
isStateChanged = true;
mStateData.mReadyState = 4;
}
@@ -1802,8 +1803,12 @@ XMLHttpRequestWorker::SendInternal(SendRunnable* aRunnable,
nsCOMPtr<nsIEventTarget> syncLoopTarget;
bool isSyncXHR = mProxy->mIsSyncXHR;
if (isSyncXHR) {
- autoSyncLoop.emplace(mWorkerPrivate);
- syncLoopTarget = autoSyncLoop->EventTarget();
+ autoSyncLoop.emplace(mWorkerPrivate, Terminating);
+ syncLoopTarget = autoSyncLoop->GetEventTarget();
+ if (!syncLoopTarget) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
}
mProxy->mOuterChannelId++;
@@ -1811,7 +1816,9 @@ XMLHttpRequestWorker::SendInternal(SendRunnable* aRunnable,
aRunnable->SetSyncLoopTarget(syncLoopTarget);
aRunnable->SetHaveUploadListeners(hasUploadListeners);
- aRunnable->Dispatch(aRv);
+ mStateData.mFlagSend = true;
+
+ aRunnable->Dispatch(Terminating, aRv);
if (aRv.Failed()) {
// Dispatch() may have spun the event loop and we may have already unrooted.
// If so we don't want autoUnpin to try again.
@@ -1837,6 +1844,7 @@ XMLHttpRequestWorker::SendInternal(SendRunnable* aRunnable,
if (!autoSyncLoop->Run() && !aRv.Failed()) {
aRv.Throw(NS_ERROR_FAILURE);
}
+ mStateData.mFlagSend = false;
}
bool
@@ -1884,7 +1892,7 @@ XMLHttpRequestWorker::Open(const nsACString& aMethod,
mTimeout, mResponseType);
++mProxy->mOpenCount;
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
if (aRv.Failed()) {
if (mProxy && !--mProxy->mOpenCount) {
ReleaseProxy();
@@ -1921,7 +1929,7 @@ XMLHttpRequestWorker::SetRequestHeader(const nsACString& aHeader,
RefPtr<SetRequestHeaderRunnable> runnable =
new SetRequestHeaderRunnable(mWorkerPrivate, mProxy, aHeader, aValue);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
void
@@ -1944,7 +1952,7 @@ XMLHttpRequestWorker::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
RefPtr<SetTimeoutRunnable> runnable =
new SetTimeoutRunnable(mWorkerPrivate, mProxy, aTimeout);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
void
@@ -1967,7 +1975,7 @@ XMLHttpRequestWorker::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv
RefPtr<SetWithCredentialsRunnable> runnable =
new SetWithCredentialsRunnable(mWorkerPrivate, mProxy, aWithCredentials);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
void
@@ -1992,7 +2000,7 @@ XMLHttpRequestWorker::SetMozBackgroundRequest(bool aBackgroundRequest,
RefPtr<SetBackgroundRequestRunnable> runnable =
new SetBackgroundRequestRunnable(mWorkerPrivate, mProxy,
aBackgroundRequest);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
XMLHttpRequestUpload*
@@ -2260,7 +2268,7 @@ XMLHttpRequestWorker::Abort(ErrorResult& aRv)
mProxy->mOuterEventStreamId++;
RefPtr<AbortRunnable> runnable = new AbortRunnable(mWorkerPrivate, mProxy);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
void
@@ -2283,7 +2291,7 @@ XMLHttpRequestWorker::GetResponseHeader(const nsACString& aHeader,
RefPtr<GetResponseHeaderRunnable> runnable =
new GetResponseHeaderRunnable(mWorkerPrivate, mProxy, aHeader,
responseHeader);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
if (aRv.Failed()) {
return;
}
@@ -2309,7 +2317,7 @@ XMLHttpRequestWorker::GetAllResponseHeaders(nsACString& aResponseHeaders,
nsCString responseHeaders;
RefPtr<GetAllResponseHeadersRunnable> runnable =
new GetAllResponseHeadersRunnable(mWorkerPrivate, mProxy, responseHeaders);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
if (aRv.Failed()) {
return;
}
@@ -2341,7 +2349,7 @@ XMLHttpRequestWorker::OverrideMimeType(const nsAString& aMimeType, ErrorResult&
RefPtr<OverrideMimeTypeRunnable> runnable =
new OverrideMimeTypeRunnable(mWorkerPrivate, mProxy, aMimeType);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
}
void
@@ -2377,7 +2385,7 @@ XMLHttpRequestWorker::SetResponseType(XMLHttpRequestResponseType aResponseType,
RefPtr<SetResponseTypeRunnable> runnable =
new SetResponseTypeRunnable(mWorkerPrivate, mProxy, aResponseType);
- runnable->Dispatch(aRv);
+ runnable->Dispatch(Terminating, aRv);
if (aRv.Failed()) {
return;
}
diff --git a/dom/xhr/XMLHttpRequestWorker.h b/dom/xhr/XMLHttpRequestWorker.h
index 90232fe85..c6647f8f3 100644
--- a/dom/xhr/XMLHttpRequestWorker.h
+++ b/dom/xhr/XMLHttpRequestWorker.h
@@ -34,15 +34,16 @@ public:
uint32_t mStatus;
nsCString mStatusText;
uint16_t mReadyState;
+ bool mFlagSend;
JS::Heap<JS::Value> mResponse;
nsresult mResponseTextResult;
nsresult mStatusResult;
nsresult mResponseResult;
StateData()
- : mStatus(0), mReadyState(0), mResponse(JS::UndefinedValue()),
- mResponseTextResult(NS_OK), mStatusResult(NS_OK),
- mResponseResult(NS_OK)
+ : mStatus(0), mReadyState(0), mFlagSend(false),
+ mResponse(JS::UndefinedValue()), mResponseTextResult(NS_OK),
+ mStatusResult(NS_OK), mResponseResult(NS_OK)
{ }
void trace(JSTracer* trc);
diff --git a/dom/xhr/tests/mochitest.ini b/dom/xhr/tests/mochitest.ini
index 35ba1e3db..a2a52787a 100644
--- a/dom/xhr/tests/mochitest.ini
+++ b/dom/xhr/tests/mochitest.ini
@@ -68,13 +68,11 @@ support-files =
[test_bug1300552.html]
[test_html_in_xhr.html]
[test_relativeLoad.html]
-skip-if = buildapp == 'b2g' # b2g(Failed to load script: relativeLoad_import.js) b2g-debug(Failed to load script: relativeLoad_import.js) b2g-desktop(Failed to load script: relativeLoad_import.js)
[test_sync_xhr_timer.xhtml]
skip-if = toolkit == 'android'
[test_sync_xhr_unload.html]
[test_temporaryFileBlob.html]
[test_worker_terminateSyncXHR.html]
-skip-if = buildapp == 'b2g'
[test_worker_xhr.html]
[test_worker_xhr2.html]
[test_worker_xhr_3rdparty.html]
@@ -82,7 +80,6 @@ skip-if = buildapp == 'b2g'
[test_worker_xhr_headers.html]
[test_worker_xhr_implicit_cancel.html]
[test_worker_xhr_parameters.html]
-skip-if = buildapp == 'b2g'
[test_worker_xhr_responseURL.html]
[test_worker_xhr_system.html]
[test_worker_xhr_timeout.html]
@@ -96,17 +93,13 @@ skip-if = toolkit == 'android'
[test_XHR_header.html]
[test_XHR_onuploadprogress.html]
[test_xhr_overridemimetype_throws_on_invalid_state.html]
-skip-if = buildapp == 'b2g' # Requires webgl support
[test_XHR_parameters.html]
-skip-if = buildapp == 'b2g' # b2g(86 total, 4 failing - testing mozAnon - got false, expected true) b2g-debug(86 total, 4 failing - testing mozAnon - got false, expected true) b2g-desktop(86 total, 4 failing - testing mozAnon - got false, expected true)
[test_xhr_progressevents.html]
skip-if = toolkit == 'android'
[test_xhr_send.html]
[test_xhr_send_readystate.html]
[test_XHR_system.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(12 total, 2 failing - .mozSystem == true - got false, expected true + ) b2g-desktop(12 total, 2 failing - .mozSystem == true - got false, expected true + )
[test_XHR_timeout.html]
-skip-if = buildapp == 'b2g' || (android_version == '18' && debug) # b2g(flaky on B2G, bug 960743) b2g-debug(flaky on B2G, bug 960743) b2g-desktop(flaky on B2G, bug 960743)
support-files = test_XHR_timeout.js
[test_xhr_withCredentials.html]
[test_XHRDocURI.html]
diff --git a/dom/xslt/xpath/txXPCOMExtensionFunction.cpp b/dom/xslt/xpath/txXPCOMExtensionFunction.cpp
index 4913702aa..032161722 100644
--- a/dom/xslt/xpath/txXPCOMExtensionFunction.cpp
+++ b/dom/xslt/xpath/txXPCOMExtensionFunction.cpp
@@ -322,7 +322,7 @@ public:
void trace(JSTracer* trc) {
for (uint8_t i = 0; i < mCount; ++i) {
if (mArray[i].type == nsXPTType::T_JSVAL) {
- JS::UnsafeTraceRoot(trc, &mArray[i].val.j, "txParam value");
+ JS::UnsafeTraceRoot(trc, &mArray[i].val.j.asValueRef(), "txParam value");
}
}
}
diff --git a/dom/xslt/xslt/txFormatNumberFunctionCall.cpp b/dom/xslt/xslt/txFormatNumberFunctionCall.cpp
index a4d4b8fb0..674fb553c 100644
--- a/dom/xslt/xslt/txFormatNumberFunctionCall.cpp
+++ b/dom/xslt/xslt/txFormatNumberFunctionCall.cpp
@@ -265,6 +265,12 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext,
value = fabs(value) * multiplier;
+ // Make sure the multiplier didn't push value to infinity.
+ if (value == mozilla::PositiveInfinity<double>()) {
+ return aContext->recycler()->getStringResult(format->mInfinity,
+ aResult);
+ }
+
// Prefix
nsAutoString res(prefix);