diff --git a/interface/resources/avatar/animations/emote_agree_acknowledge.fbx b/interface/resources/avatar/animations/emote_agree_acknowledge.fbx index 9b1984b7cd..822cb3605c 100644 Binary files a/interface/resources/avatar/animations/emote_agree_acknowledge.fbx and b/interface/resources/avatar/animations/emote_agree_acknowledge.fbx differ diff --git a/interface/resources/avatar/animations/emote_agree_headnod.fbx b/interface/resources/avatar/animations/emote_agree_headnod.fbx index f380f7887c..4fdbc20030 100644 Binary files a/interface/resources/avatar/animations/emote_agree_headnod.fbx and b/interface/resources/avatar/animations/emote_agree_headnod.fbx differ diff --git a/interface/resources/avatar/animations/emote_agree_headnodyes.fbx b/interface/resources/avatar/animations/emote_agree_headnodyes.fbx index c8bb90c021..4676a6e9f3 100644 Binary files a/interface/resources/avatar/animations/emote_agree_headnodyes.fbx and b/interface/resources/avatar/animations/emote_agree_headnodyes.fbx differ diff --git a/interface/resources/avatar/animations/emote_agree_longheadnod.fbx b/interface/resources/avatar/animations/emote_agree_longheadnod.fbx index 01aa806b77..60f8927c18 100644 Binary files a/interface/resources/avatar/animations/emote_agree_longheadnod.fbx and b/interface/resources/avatar/animations/emote_agree_longheadnod.fbx differ diff --git a/interface/resources/avatar/animations/emote_agree_thoughtfulheadnod.fbx b/interface/resources/avatar/animations/emote_agree_thoughtfulheadnod.fbx index dcdba0a721..775da34245 100644 Binary files a/interface/resources/avatar/animations/emote_agree_thoughtfulheadnod.fbx and b/interface/resources/avatar/animations/emote_agree_thoughtfulheadnod.fbx differ diff --git a/interface/resources/avatar/animations/emote_clap01_all.fbx b/interface/resources/avatar/animations/emote_clap01_all.fbx index f04046280b..6120e714ed 100644 Binary files a/interface/resources/avatar/animations/emote_clap01_all.fbx and b/interface/resources/avatar/animations/emote_clap01_all.fbx differ diff --git a/interface/resources/avatar/animations/emote_clap02_all.fbx b/interface/resources/avatar/animations/emote_clap02_all.fbx index caf673f28a..7474b49763 100644 Binary files a/interface/resources/avatar/animations/emote_clap02_all.fbx and b/interface/resources/avatar/animations/emote_clap02_all.fbx differ diff --git a/interface/resources/avatar/animations/emote_clap03_all.fbx b/interface/resources/avatar/animations/emote_clap03_all.fbx index c214bce859..317c03c197 100644 Binary files a/interface/resources/avatar/animations/emote_clap03_all.fbx and b/interface/resources/avatar/animations/emote_clap03_all.fbx differ diff --git a/interface/resources/avatar/animations/emote_disagree_annoyedheadshake.fbx b/interface/resources/avatar/animations/emote_disagree_annoyedheadshake.fbx index 3d7b61a468..01c9e5f79e 100644 Binary files a/interface/resources/avatar/animations/emote_disagree_annoyedheadshake.fbx and b/interface/resources/avatar/animations/emote_disagree_annoyedheadshake.fbx differ diff --git a/interface/resources/avatar/animations/emote_disagree_drophead.fbx b/interface/resources/avatar/animations/emote_disagree_drophead.fbx index 39ffa7e591..e82c2fb269 100644 Binary files a/interface/resources/avatar/animations/emote_disagree_drophead.fbx and b/interface/resources/avatar/animations/emote_disagree_drophead.fbx differ diff --git a/interface/resources/avatar/animations/emote_disagree_thoughtfulheadshake.fbx b/interface/resources/avatar/animations/emote_disagree_thoughtfulheadshake.fbx index c25a717c4a..214b5a3cd8 100644 Binary files a/interface/resources/avatar/animations/emote_disagree_thoughtfulheadshake.fbx and b/interface/resources/avatar/animations/emote_disagree_thoughtfulheadshake.fbx differ diff --git a/interface/resources/avatar/animations/emote_point01_all.fbx b/interface/resources/avatar/animations/emote_point01_all.fbx index 8fe7c951d6..c14f2d7531 100644 Binary files a/interface/resources/avatar/animations/emote_point01_all.fbx and b/interface/resources/avatar/animations/emote_point01_all.fbx differ diff --git a/interface/resources/avatar/animations/emote_raisehand01_all.fbx b/interface/resources/avatar/animations/emote_raisehand01_all.fbx index 428bf1179b..85f57014d1 100644 Binary files a/interface/resources/avatar/animations/emote_raisehand01_all.fbx and b/interface/resources/avatar/animations/emote_raisehand01_all.fbx differ diff --git a/interface/resources/avatar/animations/emote_raisehand03_all.fbx b/interface/resources/avatar/animations/emote_raisehand03_all.fbx index ef17293e24..6de262c1ac 100644 Binary files a/interface/resources/avatar/animations/emote_raisehand03_all.fbx and b/interface/resources/avatar/animations/emote_raisehand03_all.fbx differ diff --git a/interface/resources/avatar/animations/emote_raisehand04_all.fbx b/interface/resources/avatar/animations/emote_raisehand04_all.fbx index 0ad740441d..262ba1badb 100644 Binary files a/interface/resources/avatar/animations/emote_raisehand04_all.fbx and b/interface/resources/avatar/animations/emote_raisehand04_all.fbx differ diff --git a/interface/resources/avatar/animations/fly.fbx b/interface/resources/avatar/animations/fly.fbx index 5d8fcce23b..5f0fa1ecd7 100644 Binary files a/interface/resources/avatar/animations/fly.fbx and b/interface/resources/avatar/animations/fly.fbx differ diff --git a/interface/resources/avatar/animations/idle.fbx b/interface/resources/avatar/animations/idle.fbx index a2cbb9b43b..e5a08ec600 100644 Binary files a/interface/resources/avatar/animations/idle.fbx and b/interface/resources/avatar/animations/idle.fbx differ diff --git a/interface/resources/avatar/animations/idle02.fbx b/interface/resources/avatar/animations/idle02.fbx index c18162dda1..7ec151ac21 100644 Binary files a/interface/resources/avatar/animations/idle02.fbx and b/interface/resources/avatar/animations/idle02.fbx differ diff --git a/interface/resources/avatar/animations/idle03.fbx b/interface/resources/avatar/animations/idle03.fbx index 5349c49a31..641659cc17 100644 Binary files a/interface/resources/avatar/animations/idle03.fbx and b/interface/resources/avatar/animations/idle03.fbx differ diff --git a/interface/resources/avatar/animations/idle04.fbx b/interface/resources/avatar/animations/idle04.fbx index c0676a7980..8207b7eaeb 100644 Binary files a/interface/resources/avatar/animations/idle04.fbx and b/interface/resources/avatar/animations/idle04.fbx differ diff --git a/interface/resources/avatar/animations/idleWS_all.fbx b/interface/resources/avatar/animations/idleWS_all.fbx index 3605ecfcf4..d56b6f578b 100644 Binary files a/interface/resources/avatar/animations/idleWS_all.fbx and b/interface/resources/avatar/animations/idleWS_all.fbx differ diff --git a/interface/resources/avatar/animations/idle_LFF_all.fbx b/interface/resources/avatar/animations/idle_LFF_all.fbx index 66b82914ba..416bba001e 100644 Binary files a/interface/resources/avatar/animations/idle_LFF_all.fbx and b/interface/resources/avatar/animations/idle_LFF_all.fbx differ diff --git a/interface/resources/avatar/animations/idle_RFF_all.fbx b/interface/resources/avatar/animations/idle_RFF_all.fbx index 80277ec9a6..925e6ad4f9 100644 Binary files a/interface/resources/avatar/animations/idle_RFF_all.fbx and b/interface/resources/avatar/animations/idle_RFF_all.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_fidget.fbx b/interface/resources/avatar/animations/idle_once_fidget.fbx index 2270614901..af5d6167a7 100644 Binary files a/interface/resources/avatar/animations/idle_once_fidget.fbx and b/interface/resources/avatar/animations/idle_once_fidget.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_headtilt.fbx b/interface/resources/avatar/animations/idle_once_headtilt.fbx index eeae4604aa..f6bd8fe770 100644 Binary files a/interface/resources/avatar/animations/idle_once_headtilt.fbx and b/interface/resources/avatar/animations/idle_once_headtilt.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_lookaround.fbx b/interface/resources/avatar/animations/idle_once_lookaround.fbx index b638191654..cf793b55b5 100644 Binary files a/interface/resources/avatar/animations/idle_once_lookaround.fbx and b/interface/resources/avatar/animations/idle_once_lookaround.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_lookleftright.fbx b/interface/resources/avatar/animations/idle_once_lookleftright.fbx index 72aee7931e..c8e9516cc9 100644 Binary files a/interface/resources/avatar/animations/idle_once_lookleftright.fbx and b/interface/resources/avatar/animations/idle_once_lookleftright.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_neckstretch.fbx b/interface/resources/avatar/animations/idle_once_neckstretch.fbx index 5ee4a99d65..8eaa5f337b 100644 Binary files a/interface/resources/avatar/animations/idle_once_neckstretch.fbx and b/interface/resources/avatar/animations/idle_once_neckstretch.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_shiftheelpivot.fbx b/interface/resources/avatar/animations/idle_once_shiftheelpivot.fbx index 073b4343aa..79ce27ab89 100644 Binary files a/interface/resources/avatar/animations/idle_once_shiftheelpivot.fbx and b/interface/resources/avatar/animations/idle_once_shiftheelpivot.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_slownod.fbx b/interface/resources/avatar/animations/idle_once_slownod.fbx index 7a27add7bf..23f93a3978 100644 Binary files a/interface/resources/avatar/animations/idle_once_slownod.fbx and b/interface/resources/avatar/animations/idle_once_slownod.fbx differ diff --git a/interface/resources/avatar/animations/jog_bwd.fbx b/interface/resources/avatar/animations/jog_bwd.fbx index b3eb8c919d..2f52d3a71e 100644 Binary files a/interface/resources/avatar/animations/jog_bwd.fbx and b/interface/resources/avatar/animations/jog_bwd.fbx differ diff --git a/interface/resources/avatar/animations/jog_fwd.fbx b/interface/resources/avatar/animations/jog_fwd.fbx index 9d38caacab..784482445a 100644 Binary files a/interface/resources/avatar/animations/jog_fwd.fbx and b/interface/resources/avatar/animations/jog_fwd.fbx differ diff --git a/interface/resources/avatar/animations/jog_left.fbx b/interface/resources/avatar/animations/jog_left.fbx index 7732050201..a875da6d69 100644 Binary files a/interface/resources/avatar/animations/jog_left.fbx and b/interface/resources/avatar/animations/jog_left.fbx differ diff --git a/interface/resources/avatar/animations/jog_right.fbx b/interface/resources/avatar/animations/jog_right.fbx index 9b419b6eec..e3b0f379cd 100644 Binary files a/interface/resources/avatar/animations/jog_right.fbx and b/interface/resources/avatar/animations/jog_right.fbx differ diff --git a/interface/resources/avatar/animations/jump_running_launch_land_all.fbx b/interface/resources/avatar/animations/jump_running_launch_land_all.fbx index 71dae6bcc5..4d17a6b72a 100644 Binary files a/interface/resources/avatar/animations/jump_running_launch_land_all.fbx and b/interface/resources/avatar/animations/jump_running_launch_land_all.fbx differ diff --git a/interface/resources/avatar/animations/jump_standing_apex_all.fbx b/interface/resources/avatar/animations/jump_standing_apex_all.fbx index 5d5873c39a..bd52dfad0d 100644 Binary files a/interface/resources/avatar/animations/jump_standing_apex_all.fbx and b/interface/resources/avatar/animations/jump_standing_apex_all.fbx differ diff --git a/interface/resources/avatar/animations/jump_standing_land_settle_all.fbx b/interface/resources/avatar/animations/jump_standing_land_settle_all.fbx index ef8e83be34..e371f36022 100644 Binary files a/interface/resources/avatar/animations/jump_standing_land_settle_all.fbx and b/interface/resources/avatar/animations/jump_standing_land_settle_all.fbx differ diff --git a/interface/resources/avatar/animations/jump_standing_launch_all.fbx b/interface/resources/avatar/animations/jump_standing_launch_all.fbx index e10e428579..e75c85431b 100644 Binary files a/interface/resources/avatar/animations/jump_standing_launch_all.fbx and b/interface/resources/avatar/animations/jump_standing_launch_all.fbx differ diff --git a/interface/resources/avatar/animations/run_bwd.fbx b/interface/resources/avatar/animations/run_bwd.fbx index 60ade1f2ac..95cfe695f4 100644 Binary files a/interface/resources/avatar/animations/run_bwd.fbx and b/interface/resources/avatar/animations/run_bwd.fbx differ diff --git a/interface/resources/avatar/animations/run_fast_fwd.fbx b/interface/resources/avatar/animations/run_fast_fwd.fbx index cb964d57d8..c227428985 100644 Binary files a/interface/resources/avatar/animations/run_fast_fwd.fbx and b/interface/resources/avatar/animations/run_fast_fwd.fbx differ diff --git a/interface/resources/avatar/animations/run_fast_left.fbx b/interface/resources/avatar/animations/run_fast_left.fbx index 5078d0cb22..40ab6220df 100644 Binary files a/interface/resources/avatar/animations/run_fast_left.fbx and b/interface/resources/avatar/animations/run_fast_left.fbx differ diff --git a/interface/resources/avatar/animations/run_fast_right.fbx b/interface/resources/avatar/animations/run_fast_right.fbx index ddf081bef6..dde651d18d 100644 Binary files a/interface/resources/avatar/animations/run_fast_right.fbx and b/interface/resources/avatar/animations/run_fast_right.fbx differ diff --git a/interface/resources/avatar/animations/settle_to_idle_small.fbx b/interface/resources/avatar/animations/settle_to_idle_small.fbx index 3d79d1930c..9161a95d95 100644 Binary files a/interface/resources/avatar/animations/settle_to_idle_small.fbx and b/interface/resources/avatar/animations/settle_to_idle_small.fbx differ diff --git a/interface/resources/avatar/animations/side_step_left.fbx b/interface/resources/avatar/animations/side_step_left.fbx index b74fe9074a..ee1169b8ad 100644 Binary files a/interface/resources/avatar/animations/side_step_left.fbx and b/interface/resources/avatar/animations/side_step_left.fbx differ diff --git a/interface/resources/avatar/animations/side_step_left_fast.fbx b/interface/resources/avatar/animations/side_step_left_fast.fbx index f4c997345f..a00949d749 100644 Binary files a/interface/resources/avatar/animations/side_step_left_fast.fbx and b/interface/resources/avatar/animations/side_step_left_fast.fbx differ diff --git a/interface/resources/avatar/animations/side_step_short_left.fbx b/interface/resources/avatar/animations/side_step_short_left.fbx index 8f55364b17..f3b4091420 100644 Binary files a/interface/resources/avatar/animations/side_step_short_left.fbx and b/interface/resources/avatar/animations/side_step_short_left.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_agree_cheer.fbx b/interface/resources/avatar/animations/sitting_emote_agree_cheer.fbx index 799bf721a4..c7518a450f 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_agree_cheer.fbx and b/interface/resources/avatar/animations/sitting_emote_agree_cheer.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_agree_headnod.fbx b/interface/resources/avatar/animations/sitting_emote_agree_headnod.fbx index 9d31e777e8..1bc297ba60 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_agree_headnod.fbx and b/interface/resources/avatar/animations/sitting_emote_agree_headnod.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_agree_headnodyes.fbx b/interface/resources/avatar/animations/sitting_emote_agree_headnodyes.fbx index bf956f50d6..c69cbbe805 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_agree_headnodyes.fbx and b/interface/resources/avatar/animations/sitting_emote_agree_headnodyes.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_agree_longheadnod.fbx b/interface/resources/avatar/animations/sitting_emote_agree_longheadnod.fbx index 5dc4cc126f..aea11137cc 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_agree_longheadnod.fbx and b/interface/resources/avatar/animations/sitting_emote_agree_longheadnod.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_clap02_all.fbx b/interface/resources/avatar/animations/sitting_emote_clap02_all.fbx index 5034d13fd5..de53589a19 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_clap02_all.fbx and b/interface/resources/avatar/animations/sitting_emote_clap02_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_clap_all.fbx b/interface/resources/avatar/animations/sitting_emote_clap_all.fbx index 947ef4541a..8121f2907b 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_clap_all.fbx and b/interface/resources/avatar/animations/sitting_emote_clap_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_disagree_disbelief.fbx b/interface/resources/avatar/animations/sitting_emote_disagree_disbelief.fbx index fce96a23ae..ad1a63019f 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_disagree_disbelief.fbx and b/interface/resources/avatar/animations/sitting_emote_disagree_disbelief.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_disagree_drophead.fbx b/interface/resources/avatar/animations/sitting_emote_disagree_drophead.fbx index 6e13b29ccf..daf847bdf5 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_disagree_drophead.fbx and b/interface/resources/avatar/animations/sitting_emote_disagree_drophead.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_disagree_headshake.fbx b/interface/resources/avatar/animations/sitting_emote_disagree_headshake.fbx index 45ebdcedc3..4735ea050c 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_disagree_headshake.fbx and b/interface/resources/avatar/animations/sitting_emote_disagree_headshake.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_point_all.fbx b/interface/resources/avatar/animations/sitting_emote_point_all.fbx index f850c8e9b3..9ce17a3783 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_point_all.fbx and b/interface/resources/avatar/animations/sitting_emote_point_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_raisehand02_all.fbx b/interface/resources/avatar/animations/sitting_emote_raisehand02_all.fbx index e66e6b942a..48c21e32bc 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_raisehand02_all.fbx and b/interface/resources/avatar/animations/sitting_emote_raisehand02_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_raisehand_all.fbx b/interface/resources/avatar/animations/sitting_emote_raisehand_all.fbx index 5d1f493d3a..f60f49b2fc 100644 Binary files a/interface/resources/avatar/animations/sitting_emote_raisehand_all.fbx and b/interface/resources/avatar/animations/sitting_emote_raisehand_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_idle.fbx b/interface/resources/avatar/animations/sitting_idle.fbx index 156abc133a..877ce024d2 100644 Binary files a/interface/resources/avatar/animations/sitting_idle.fbx and b/interface/resources/avatar/animations/sitting_idle.fbx differ diff --git a/interface/resources/avatar/animations/sitting_idle02.fbx b/interface/resources/avatar/animations/sitting_idle02.fbx index 5303a1e1ab..8cf3d22fc6 100644 Binary files a/interface/resources/avatar/animations/sitting_idle02.fbx and b/interface/resources/avatar/animations/sitting_idle02.fbx differ diff --git a/interface/resources/avatar/animations/sitting_idle03.fbx b/interface/resources/avatar/animations/sitting_idle03.fbx index b25968f183..0dee5b128d 100644 Binary files a/interface/resources/avatar/animations/sitting_idle03.fbx and b/interface/resources/avatar/animations/sitting_idle03.fbx differ diff --git a/interface/resources/avatar/animations/sitting_talk02.fbx b/interface/resources/avatar/animations/sitting_talk02.fbx index 7e6a071c0e..9742e69489 100644 Binary files a/interface/resources/avatar/animations/sitting_talk02.fbx and b/interface/resources/avatar/animations/sitting_talk02.fbx differ diff --git a/interface/resources/avatar/animations/sitting_talk03.fbx b/interface/resources/avatar/animations/sitting_talk03.fbx index 73dff2e900..8e0d45e954 100644 Binary files a/interface/resources/avatar/animations/sitting_talk03.fbx and b/interface/resources/avatar/animations/sitting_talk03.fbx differ diff --git a/interface/resources/avatar/animations/sitting_talk04.fbx b/interface/resources/avatar/animations/sitting_talk04.fbx index ee920672fa..6738e88b1d 100644 Binary files a/interface/resources/avatar/animations/sitting_talk04.fbx and b/interface/resources/avatar/animations/sitting_talk04.fbx differ diff --git a/interface/resources/avatar/animations/talk.fbx b/interface/resources/avatar/animations/talk.fbx index 6cc34049be..133a16641a 100644 Binary files a/interface/resources/avatar/animations/talk.fbx and b/interface/resources/avatar/animations/talk.fbx differ diff --git a/interface/resources/avatar/animations/talk02.fbx b/interface/resources/avatar/animations/talk02.fbx index a502ff261b..de30b7e9fe 100644 Binary files a/interface/resources/avatar/animations/talk02.fbx and b/interface/resources/avatar/animations/talk02.fbx differ diff --git a/interface/resources/avatar/animations/talk03.fbx b/interface/resources/avatar/animations/talk03.fbx index da95717540..9bcad7b4af 100644 Binary files a/interface/resources/avatar/animations/talk03.fbx and b/interface/resources/avatar/animations/talk03.fbx differ diff --git a/interface/resources/avatar/animations/talk04.fbx b/interface/resources/avatar/animations/talk04.fbx index 9e5505b969..2fb1811405 100644 Binary files a/interface/resources/avatar/animations/talk04.fbx and b/interface/resources/avatar/animations/talk04.fbx differ diff --git a/interface/resources/avatar/animations/talk_armsdown.fbx b/interface/resources/avatar/animations/talk_armsdown.fbx index e069811f7c..66d69e70e1 100644 Binary files a/interface/resources/avatar/animations/talk_armsdown.fbx and b/interface/resources/avatar/animations/talk_armsdown.fbx differ diff --git a/interface/resources/avatar/animations/talk_lefthand.fbx b/interface/resources/avatar/animations/talk_lefthand.fbx index d7fd1d5e07..08299fd14b 100644 Binary files a/interface/resources/avatar/animations/talk_lefthand.fbx and b/interface/resources/avatar/animations/talk_lefthand.fbx differ diff --git a/interface/resources/avatar/animations/talk_righthand.fbx b/interface/resources/avatar/animations/talk_righthand.fbx index 332afcc1e7..99dd70e308 100644 Binary files a/interface/resources/avatar/animations/talk_righthand.fbx and b/interface/resources/avatar/animations/talk_righthand.fbx differ diff --git a/interface/resources/avatar/animations/teleport.fbx b/interface/resources/avatar/animations/teleport.fbx index 99c950ced6..eeeb48596b 100644 Binary files a/interface/resources/avatar/animations/teleport.fbx and b/interface/resources/avatar/animations/teleport.fbx differ diff --git a/interface/resources/avatar/animations/turn_left.fbx b/interface/resources/avatar/animations/turn_left.fbx index b7cadf7a66..a58036499d 100644 Binary files a/interface/resources/avatar/animations/turn_left.fbx and b/interface/resources/avatar/animations/turn_left.fbx differ diff --git a/interface/resources/avatar/animations/turn_right.fbx b/interface/resources/avatar/animations/turn_right.fbx index 4ee3d52daf..c28ac2a62f 100644 Binary files a/interface/resources/avatar/animations/turn_right.fbx and b/interface/resources/avatar/animations/turn_right.fbx differ diff --git a/interface/resources/avatar/animations/walk_bwd.fbx b/interface/resources/avatar/animations/walk_bwd.fbx index 9daa769885..786ad67db9 100644 Binary files a/interface/resources/avatar/animations/walk_bwd.fbx and b/interface/resources/avatar/animations/walk_bwd.fbx differ diff --git a/interface/resources/avatar/animations/walk_bwd_fast.fbx b/interface/resources/avatar/animations/walk_bwd_fast.fbx index af22d0d0b0..cc872d7f09 100644 Binary files a/interface/resources/avatar/animations/walk_bwd_fast.fbx and b/interface/resources/avatar/animations/walk_bwd_fast.fbx differ diff --git a/interface/resources/avatar/animations/walk_fwd.fbx b/interface/resources/avatar/animations/walk_fwd.fbx index f86a8744c9..d128b4228e 100644 Binary files a/interface/resources/avatar/animations/walk_fwd.fbx and b/interface/resources/avatar/animations/walk_fwd.fbx differ diff --git a/interface/resources/avatar/animations/walk_fwd_fast.fbx b/interface/resources/avatar/animations/walk_fwd_fast.fbx index 8d2becf4b8..b387b237d3 100644 Binary files a/interface/resources/avatar/animations/walk_fwd_fast.fbx and b/interface/resources/avatar/animations/walk_fwd_fast.fbx differ diff --git a/interface/resources/avatar/animations/walk_left.fbx b/interface/resources/avatar/animations/walk_left.fbx index f35d4f6a77..a492c79e06 100644 Binary files a/interface/resources/avatar/animations/walk_left.fbx and b/interface/resources/avatar/animations/walk_left.fbx differ diff --git a/interface/resources/avatar/animations/walk_left_fast.fbx b/interface/resources/avatar/animations/walk_left_fast.fbx index 8414ee6805..7c502aae82 100644 Binary files a/interface/resources/avatar/animations/walk_left_fast.fbx and b/interface/resources/avatar/animations/walk_left_fast.fbx differ diff --git a/interface/resources/avatar/animations/walk_right.fbx b/interface/resources/avatar/animations/walk_right.fbx index 5fe005f96c..03c9705b3d 100644 Binary files a/interface/resources/avatar/animations/walk_right.fbx and b/interface/resources/avatar/animations/walk_right.fbx differ diff --git a/interface/resources/avatar/animations/walk_right_fast.fbx b/interface/resources/avatar/animations/walk_right_fast.fbx index 37b7bbbb62..5453399fd6 100644 Binary files a/interface/resources/avatar/animations/walk_right_fast.fbx and b/interface/resources/avatar/animations/walk_right_fast.fbx differ diff --git a/interface/resources/avatar/animations/walk_short_fwd.fbx b/interface/resources/avatar/animations/walk_short_fwd.fbx index b52371869b..63a44138e0 100644 Binary files a/interface/resources/avatar/animations/walk_short_fwd.fbx and b/interface/resources/avatar/animations/walk_short_fwd.fbx differ diff --git a/interface/resources/qml/hifi/tablet/DynamicWebview.qml b/interface/resources/qml/hifi/tablet/DynamicWebview.qml new file mode 100644 index 0000000000..4343e71e64 --- /dev/null +++ b/interface/resources/qml/hifi/tablet/DynamicWebview.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 +import "../../controls" as Controls + +Controls.WebView { + id: root + function fromScript(message) { + root.url = message.url; + } +} + + diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4c232a0585..b318f07d8f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -139,6 +139,7 @@ #include #include #include +#include #include #include #include @@ -3285,6 +3286,9 @@ void Application::initializeUi() { } return result.toPoint(); }); + + // BUGZ-1365 - the root context should explicitly default to being unable to load local HTML content + ContextAwareProfile::restrictContext(offscreenUi->getSurfaceContext(), true); offscreenUi->resume(); #endif connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){ @@ -7457,7 +7461,7 @@ void Application::addingEntityWithCertificate(const QString& certificateID, cons ledger->updateLocation(certificateID, placeName); } -void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointer scriptEngine) { +void Application::registerScriptEngineWithApplicationServices(const ScriptEnginePointer& scriptEngine) { scriptEngine->setEmitScriptUpdatesFunction([this]() { SharedNodePointer entityServerNode = DependencyManager::get()->soloNodeOfType(NodeType::EntityServer); @@ -7496,9 +7500,19 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue, RayToOverlayIntersectionResultFromScriptValue); + bool clientScript = scriptEngine->isClientScript(); + #if !defined(DISABLE_QML) scriptEngine->registerGlobalObject("OffscreenFlags", getOffscreenUI()->getFlags()); - scriptEngine->registerGlobalObject("Desktop", DependencyManager::get().data()); + if (clientScript) { + scriptEngine->registerGlobalObject("Desktop", DependencyManager::get().data()); + } else { + auto desktopScriptingInterface = new DesktopScriptingInterface(nullptr, true); + scriptEngine->registerGlobalObject("Desktop", desktopScriptingInterface); + if (QThread::currentThread() != thread()) { + desktopScriptingInterface->moveToThread(thread()); + } + } #endif qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, wrapperFromScriptValue); @@ -7523,7 +7537,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, LocationScriptingInterface::locationSetter); - bool clientScript = scriptEngine->isClientScript(); scriptEngine->registerFunction("OverlayWindow", clientScript ? QmlWindowClass::constructor : QmlWindowClass::restricted_constructor); #if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML) scriptEngine->registerFunction("OverlayWebWindow", clientScript ? QmlWebWindowClass::constructor : QmlWebWindowClass::restricted_constructor); diff --git a/interface/src/Application.h b/interface/src/Application.h index 20abbf2baf..cd867598c0 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -252,7 +252,7 @@ public: NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; } virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } - virtual void registerScriptEngineWithApplicationServices(ScriptEnginePointer scriptEngine) override; + virtual void registerScriptEngineWithApplicationServices(const ScriptEnginePointer& scriptEngine) override; virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override { copyDisplayViewFrustum(viewOut); } virtual QThread* getMainThread() override { return thread(); } diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index a1c8e4fc6c..874b3fa42d 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -52,6 +52,9 @@ static const QVariantMap DOCK_AREA { { "RIGHT", DockArea::RIGHT } }; +DesktopScriptingInterface::DesktopScriptingInterface(QObject* parent, bool restricted) + : QObject(parent), _restricted(restricted) { } + int DesktopScriptingInterface::getWidth() { QSize size = qApp->getWindow()->windowHandle()->screen()->virtualSize(); return size.width(); @@ -128,7 +131,7 @@ InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& return nullptr; } - return new InteractiveWindow(sourceUrl, properties); + return new InteractiveWindow(sourceUrl, properties, _restricted); } InteractiveWindowPointer DesktopScriptingInterface::createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread) { @@ -139,7 +142,7 @@ InteractiveWindowPointer DesktopScriptingInterface::createWindowOnThread(const Q if (!urlValidator(sourceUrl)) { return nullptr; } - InteractiveWindowPointer window = new InteractiveWindow(sourceUrl, properties); + InteractiveWindowPointer window = new InteractiveWindow(sourceUrl, properties, _restricted); window->moveToThread(targetThread); return window; } diff --git a/interface/src/scripting/DesktopScriptingInterface.h b/interface/src/scripting/DesktopScriptingInterface.h index 525fd7c803..e562a32543 100644 --- a/interface/src/scripting/DesktopScriptingInterface.h +++ b/interface/src/scripting/DesktopScriptingInterface.h @@ -54,6 +54,8 @@ class DesktopScriptingInterface : public QObject, public Dependency { Q_PROPERTY(int CLOSE_BUTTON_HIDES READ flagCloseButtonHides CONSTANT FINAL) public: + DesktopScriptingInterface(QObject* parent= nullptr, bool restricted = false); + /**jsdoc * Sets the opacity of the HUD surface. * @function Desktop.setHUDAlpha @@ -106,6 +108,7 @@ private: static QVariantMap getDockArea(); Q_INVOKABLE static QVariantMap getPresentationMode(); + const bool _restricted; }; diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 9145b12d30..e63c392a47 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -18,6 +18,9 @@ #include #include +#include +#include +#include #include #include #include @@ -134,7 +137,7 @@ void InteractiveWindow::emitMainWindowResizeEvent() { * Set at window creation. Possible flag values are provided as {@link Desktop|Desktop.ALWAYS_ON_TOP} and {@link Desktop|Desktop.CLOSE_BUTTON_HIDES}. * Additional flag values can be found on Qt's website at https://doc.qt.io/qt-5/qt.html#WindowType-enum. */ -InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap& properties) { +InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap& properties, bool restricted) { InteractiveWindowPresentationMode presentationMode = InteractiveWindowPresentationMode::Native; if (properties.contains(PRESENTATION_MODE_PROPERTY)) { @@ -228,9 +231,16 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap _dockWidget->setObjectName("DockedWidget"); mainWindow->addDockWidget(dockArea, _dockWidget.get()); } else { - auto offscreenUi = DependencyManager::get(); - // Build the event bridge and wrapper on the main thread - offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, [&](QQmlContext* context, QObject* object) { + auto contextInitLambda = [&](QQmlContext* context) { + // If the restricted flag is on, the web content will not be able to access local files + ContextAwareProfile::restrictContext(context, restricted); +#if !defined(Q_OS_ANDROID) + FileTypeProfile::registerWithContext(context); + HFWebEngineProfile::registerWithContext(context); +#endif + }; + + auto objectInitLambda = [&](QQmlContext* context, QObject* object) { _qmlWindowProxy = std::shared_ptr(new QmlWindowProxy(object, nullptr), qmlWindowProxyDeleter); context->setContextProperty(EVENT_BRIDGE_PROPERTY, _interactiveWindowProxy.get()); if (properties.contains(ADDITIONAL_FLAGS_PROPERTY)) { @@ -286,7 +296,11 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap } object->setObjectName("InteractiveWindow"); object->setProperty(SOURCE_PROPERTY, sourceURL); - }); + }; + auto offscreenUi = DependencyManager::get(); + + // Build the event bridge and wrapper on the main thread + offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, objectInitLambda, contextInitLambda); } } diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index cc7536af85..70077a27b0 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -126,7 +126,7 @@ class InteractiveWindow : public QObject { Q_PROPERTY(int presentationMode READ getPresentationMode WRITE setPresentationMode) public: - InteractiveWindow(const QString& sourceUrl, const QVariantMap& properties); + InteractiveWindow(const QString& sourceUrl, const QVariantMap& properties, bool restricted); ~InteractiveWindow(); private: diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index 43cd5de213..729aa9ef7e 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -26,9 +26,8 @@ [request setValue:@USER_AGENT_STRING forHTTPHeaderField:@"User-Agent"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; - // We're using an ephermeral session here to ensure the tags api response is never cached. - NSURLSession* session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration]; - NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData; + NSURLSessionDataTask* dataTask = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSLog(@"Latest Build Request error: %@", error); NSLog(@"Latest Build Request Data: %@", data); NSHTTPURLResponse* ne = (NSHTTPURLResponse *)response; diff --git a/libraries/script-engine/src/AbstractScriptingServicesInterface.h b/libraries/script-engine/src/AbstractScriptingServicesInterface.h index e7a8d11562..ac26b166b6 100644 --- a/libraries/script-engine/src/AbstractScriptingServicesInterface.h +++ b/libraries/script-engine/src/AbstractScriptingServicesInterface.h @@ -18,7 +18,7 @@ class AbstractScriptingServicesInterface { public: /// Registers application specific services with a script engine. - virtual void registerScriptEngineWithApplicationServices(ScriptEnginePointer scriptEngine) = 0; + virtual void registerScriptEngineWithApplicationServices(const ScriptEnginePointer& scriptEngine) = 0; }; diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index d738b13ecc..7300f52f9b 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -351,8 +351,10 @@ public: Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler); /**jsdoc - * Starts running another script in Interface. - *
Available in:Interface ScriptsAvatar Scripts
+ * Starts running another script in Interface, if it isn't already running. The script is not automatically loaded next + * time Interface starts. + *

Supported Script Types: Interface Scripts • Avatar Scripts

+ *

See also, {@link ScriptDiscoveryService.loadScript}.

* @function Script.load * @param {string} filename - The URL of the script to load. This can be relative to the current script's URL. * @example Load a script from another script. @@ -754,8 +756,8 @@ signals: void cleanupMenuItem(const QString& menuItemString); /**jsdoc - * Triggered when a script prints a message to the program log via {@link Script.print}, {@link print}, - * {@link console.log}, {@link console.info}, {@link console.warn}, {@link console.error}, or {@link console.debug}. + * Triggered when the script prints a message to the program log via {@link print}, {@link Script.print}, + * {@link console.log}, or {@link console.debug}. * @function Script.printedMessage * @param {string} message - The message. * @param {string} scriptName - The name of the script that generated the message. @@ -764,7 +766,7 @@ signals: void printedMessage(const QString& message, const QString& scriptName); /**jsdoc - * Triggered when a script generates an error or {@link console.error} is called. + * Triggered when the script generates an error or {@link console.error} is called. * @function Script.errorMessage * @param {string} message - The error message. * @param {string} scriptName - The name of the script that generated the error message. @@ -773,7 +775,7 @@ signals: void errorMessage(const QString& message, const QString& scriptName); /**jsdoc - * Triggered when a script generates a warning or {@link console.warn} is called. + * Triggered when the script generates a warning or {@link console.warn} is called. * @function Script.warningMessage * @param {string} message - The warning message. * @param {string} scriptName - The name of the script that generated the warning message. @@ -782,7 +784,7 @@ signals: void warningMessage(const QString& message, const QString& scriptName); /**jsdoc - * Triggered when a script generates an information message or {@link console.info} is called. + * Triggered when the script generates an information message or {@link console.info} is called. * @function Script.infoMessage * @param {string} message - The information message. * @param {string} scriptName - The name of the script that generated the information message. @@ -845,8 +847,9 @@ signals: * @param {Uuid} entityID - The ID of the entity that the script is running in. * @returns {Signal} * @example Get the ID of the entity that a client entity script is running in. - * var entityScript = (function () { + * var entityScript = function () { * this.entityID = Uuid.NULL; + * }; * * Script.entityScriptPreloadFinished.connect(function (entityID) { * this.entityID = entityID; diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 69455294d6..508a26302e 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -209,6 +209,18 @@ void ScriptEngines::shutdownScripting() { qCDebug(scriptengine) << "DONE Stopping all scripts...."; } +/**jsdoc + * Information on a public script, i.e., a script that's included in the Interface installation. + * @typedef {object} ScriptDiscoveryService.PublicScript + * @property {string} name - The script's file name. + * @property {string} type - "script" or "folder". + *

Deprecated: This property is deprecated and will be removed. It currently always has the value, + * "script".

+ * @property {ScriptDiscoveryService.PublicScript[]} [children] - Only present if type == "folder". + *

Deprecated: This property is deprecated and will be removed. It currently is never present. + * @property {string} [url] - The full URL of the script — including the "file:///" scheme at the start. + *

Only present if type == "script".

+ */ QVariantList getPublicChildNodes(TreeNodeFolder* parent) { QVariantList result; QList treeNodes = getScriptsModel().getFolderNodes(parent); @@ -240,6 +252,13 @@ QVariantList ScriptEngines::getPublic() { return getPublicChildNodes(NULL); } +/**jsdoc + * Information on a local script. + * @typedef {object} ScriptDiscoveryService.LocalScript + * @property {string} name - The script's file name. + * @property {string} path - The script's path. + * @deprecated This type is deprecated and will be removed. + */ QVariantList ScriptEngines::getLocal() { QVariantList result; QList treeNodes = getScriptsModel().getFolderNodes(NULL); @@ -260,6 +279,15 @@ QVariantList ScriptEngines::getLocal() { return result; } +/**jsdoc + * Information on a running script. + * @typedef {object} ScriptDiscoveryService.RunningScript + * @property {boolean} local - true if the script is a local file (i.e., the scheme is "file"), false + * if it isn't (e.g., the scheme is "http"). + * @property {string} name - The script's file name. + * @property {string} path - The script's path and file name — excluding the scheme if a local file. + * @property {string} url - The full URL of the script — including the scheme if a local file. + */ QVariantList ScriptEngines::getRunning() { QVariantList result; auto runningScripts = getRunningScripts(); diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index de836a3e09..484ccd8932 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -28,18 +28,26 @@ class ScriptEngine; /**jsdoc + * The ScriptDiscoveryService API provides facilities to work with Interface scripts. + * * @namespace ScriptDiscoveryService * * @hifi-interface - * @hifi-client-entity * @hifi-avatar + * @hifi-client-entity * - * @property {string} debugScriptUrl - * @property {string} defaultScriptsPath - * @property {ScriptsModel} scriptsModel - * @property {ScriptsModelFilter} scriptsModelFilter + * @property {string} debugScriptUrl="" - The path and name of a script to debug using the "API Debugger" developer tool + * (currentAPI.js). If set, the API Debugger dialog displays the objects and values exposed by the script using + * {@link Script.registerValue} and similar. + * @property {string} defaultScriptsPath - The path where the default scripts are located in the Interface installation. + * Read-only. + * @property {ScriptsModel} scriptsModel - Information on the scripts that are in the default scripts directory of the + * Interface installation. + * Read-only. + * @property {ScriptsModelFilter} scriptsModelFilter - Sorted and filtered information on the scripts that are in the default + * scripts directory of the Interface installation. + * Read-only. */ - class NativeScriptInitializers : public ScriptInitializerMixin { public: bool registerNativeScriptInitializer(NativeScriptInitializer initializer) override; @@ -77,61 +85,92 @@ public: QString getDefaultScriptsLocation() const; /**jsdoc + * Starts running an Interface script, if it isn't already running. The script is automatically loaded next time Interface + * starts. + *

This is a synonym for calling {@link ScriptDiscoveryService.loadScript|loadScript} with just the script URL.

+ *

Supported Script Types: Interface Scripts • Avatar Scripts

+ *

See also, {@link Script.load}.

* @function ScriptDiscoveryService.loadOneScript - * @param {string} filename + * @param {string} url - The path and name of the script. If a local file, including the "file:///" scheme is + * optional. */ Q_INVOKABLE void loadOneScript(const QString& scriptFilename); /**jsdoc + * Starts running an Interface script, if it isn't already running. + *

Supported Script Types: Interface Scripts • Avatar Scripts

+ *

See also, {@link Script.load}.

* @function ScriptDiscoveryService.loadScript - * @param {string} [filename=""] - * @param {boolean} [isUserLoaded=true] - * @param {boolean} [loadScriptFromEditor=false] - * @param {boolean} [activateMainWindow=false] - * @param {boolean} [reload=false] - * @param {boolean} [quitWhenFinished=false] - * @returns {boolean} + * @param {string} [url=""] - The path and name of the script. If a local file, including the "file:///" + * scheme is optional. + * @param {boolean} [isUserLoaded=true] - true if the user specifically loaded it, false if not + * (e.g., a script loaded it). If false, the script is not automatically loaded next time Interface starts. + * @param {boolean} [loadScriptFromEditor=false] - Not used. + * @param {boolean} [activateMainWindow=false] - Not used. + * @param {boolean} [reload=false] - true to redownload the script, false to use the copy from + * the cache if available. + * @param {boolean} [quitWhenFinished=false] - true to close Interface when the script finishes, + * false to not close Interface. + * @returns {object} An empty object, {}. */ Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(), bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false, bool quitWhenFinished = false); /**jsdoc + * Stops or restarts an Interface script. * @function ScriptDiscoveryService.stopScript - * @param {string} scriptHash - * @param {boolean} [restart=false] - * @returns {boolean} + * @param {string} url - The path and name of the script. If a local file, including the "file:///" scheme is + * optional. + * @param {boolean} [restart=false] - true to redownload and restart the script, false to stop + * it. + * @returns {boolean} true if the script was successfully stopped or restarted, false if it + * wasn't (e.g., the script couldn't be found). */ Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false); /**jsdoc - * @function ScriptDiscoveryService.reloadAllScripts - */ + * Restarts all Interface, avatar, and client entity scripts after clearing the scripts cache. + * @function ScriptDiscoveryService.reloadAllScripts + */ Q_INVOKABLE void reloadAllScripts(); /**jsdoc + * Stops or restarts all Interface scripts. The scripts cache is not cleared. If restarting, avatar and client entity + * scripts are also restarted. * @function ScriptDiscoveryService.stopAllScripts - * @param {boolean} [restart=false] + * @param {boolean} [restart=false] - true to restart the scripts, false to stop them. */ Q_INVOKABLE void stopAllScripts(bool restart = false); /**jsdoc + * Gets a list of all Interface scripts that are currently running. * @function ScriptDiscoveryService.getRunning - * @returns {object[]} + * @returns {ScriptDiscoveryService.RunningScript[]} All Interface scripts that are currently running. + * @example Report all running scripts. + * var runningScripts = ScriptDiscoveryService.getRunning(); + * print("Running scripts:"); + * for (var i = 0; i < runningScripts.length; i++) { + * print(JSON.stringify(runningScripts[i])); + * } */ Q_INVOKABLE QVariantList getRunning(); /**jsdoc + * Gets a list of all script files that are in the default scripts directory of the Interface installation. * @function ScriptDiscoveryService.getPublic - * @returns {object[]} + * @returns {ScriptDiscoveryService.PublicScript[]} All scripts in the "scripts" directory of the Interface + * installation. */ Q_INVOKABLE QVariantList getPublic(); /**jsdoc * @function ScriptDiscoveryService.getLocal - * @returns {object[]} + * @returns {ScriptDiscoveryService.LocalScript[]} Local scripts. + * @deprecated This function is deprecated and will be removed. */ + // Deprecated because there is no longer a notion of a "local" scripts folder where you would put your personal scripts. Q_INVOKABLE QVariantList getLocal(); // FIXME: Move to other Q_PROPERTY declarations. @@ -148,65 +187,82 @@ public: signals: /**jsdoc + * Triggered when the number of Interface scripts running changes. * @function ScriptDiscoveryService.scriptCountChanged * @returns {Signal} + * @example Report when the number of running scripts changes. + * ScriptDiscoveryService.scriptCountChanged.connect(function () { + * print("Scripts count changed: " + ScriptDiscoveryService.getRunning().length); + * }); */ void scriptCountChanged(); /**jsdoc + * Triggered when Interface, avatar, and client entity scripts are restarting as a result of + * {@link ScriptDiscoveryService.reloadAllScripts|reloadAllScripts} or + * {@link ScriptDiscoveryService.stopAllScripts|stopAllScripts}. * @function ScriptDiscoveryService.scriptsReloading * @returns {Signal} */ void scriptsReloading(); /**jsdoc + * Triggered when a script could not be loaded. * @function ScriptDiscoveryService.scriptLoadError - * @param {string} filename - * @param {string} error + * @param {string} url - The path and name of the script that could not be loaded. + * @param {string} error - "" always. * @returns {Signal} */ void scriptLoadError(const QString& filename, const QString& error); /**jsdoc + * Triggered when any script prints a message to the program log via {@link print}, {@link Script.print}, + * {@link console.log}, or {@link console.debug}. * @function ScriptDiscoveryService.printedMessage - * @param {string} message - * @param {string} engineName + * @param {string} message - The message. + * @param {string} scriptName - The name of the script that generated the message. * @returns {Signal} */ void printedMessage(const QString& message, const QString& engineName); /**jsdoc + * Triggered when any script generates an error or {@link console.error} is called. * @function ScriptDiscoveryService.errorMessage - * @param {string} message - * @param {string} engineName + * @param {string} message - The error message. + * @param {string} scriptName - The name of the script that generated the error message. * @returns {Signal} */ void errorMessage(const QString& message, const QString& engineName); /**jsdoc + * Triggered when any script generates a warning or {@link console.warn} is called. * @function ScriptDiscoveryService.warningMessage - * @param {string} message - * @param {string} engineName + * @param {string} message - The warning message. + * @param {string} scriptName - The name of the script that generated the warning message. * @returns {Signal} */ void warningMessage(const QString& message, const QString& engineName); /**jsdoc + * Triggered when any script generates an information message or {@link console.info} is called. * @function ScriptDiscoveryService.infoMessage - * @param {string} message - * @param {string} engineName + * @param {string} message - The information message. + * @param {string} scriptName - The name of the script that generated the informaton message. * @returns {Signal} */ void infoMessage(const QString& message, const QString& engineName); /**jsdoc * @function ScriptDiscoveryService.errorLoadingScript - * @param {string} url + * @param {string} url - URL. * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ + // Deprecated because never emitted. void errorLoadingScript(const QString& url); /**jsdoc + * Triggered when the Debug Window is cleared. * @function ScriptDiscoveryService.clearDebugWindow * @returns {Signal} */ @@ -216,50 +272,64 @@ public slots: /**jsdoc * @function ScriptDiscoveryService.onPrintedMessage - * @param {string} message - * @param {string} scriptName + * @param {string} message - Message. + * @param {string} scriptName - Script name. + * @deprecated This function is deprecated and will be removed. */ + // Deprecated because only use is to emit a signal. void onPrintedMessage(const QString& message, const QString& scriptName); /**jsdoc * @function ScriptDiscoveryService.onErrorMessage - * @param {string} message - * @param {string} scriptName + * @param {string} message - Message. + * @param {string} scriptName - Script name. + * @deprecated This function is deprecated and will be removed. */ + // Deprecated because only use is to emit a signal. void onErrorMessage(const QString& message, const QString& scriptName); /**jsdoc * @function ScriptDiscoveryService.onWarningMessage - * @param {string} message - * @param {string} scriptName + * @param {string} message - Message. + * @param {string} scriptName - Script name. + * @deprecated This function is deprecated and will be removed. */ + // Deprecated because only use is to emit a signal. void onWarningMessage(const QString& message, const QString& scriptName); /**jsdoc * @function ScriptDiscoveryService.onInfoMessage - * @param {string} message - * @param {string} scriptName + * @param {string} message - Message. + * @param {string} scriptName - Script name. + * @deprecated This function is deprecated and will be removed. */ + // Deprecated because only use is to emit a signal. void onInfoMessage(const QString& message, const QString& scriptName); /**jsdoc * @function ScriptDiscoveryService.onErrorLoadingScript - * @param {string} url + * @param {string} url - URL. + * @deprecated This function is deprecated and will be removed. */ + // Deprecated because only use is to emit a signal. And it isn't used. void onErrorLoadingScript(const QString& url); /**jsdoc * @function ScriptDiscoveryService.onClearDebugWindow + * @deprecated This function is deprecated and will be removed. */ + // Deprecated because only use is to emit a signal. void onClearDebugWindow(); protected slots: /**jsdoc * @function ScriptDiscoveryService.onScriptFinished - * @param {string} filename - * @param {object} engine + * @param {string} scriptName - Script name. + * @param {object} engine - Engine. + * @deprecated This function is deprecated and will be removed. */ + // Deprecated because it wasn't intended to be in the API. void onScriptFinished(const QString& fileNameString, ScriptEnginePointer engine); protected: diff --git a/libraries/script-engine/src/ScriptsModel.h b/libraries/script-engine/src/ScriptsModel.h index adfb15affc..bd6c9687c1 100644 --- a/libraries/script-engine/src/ScriptsModel.h +++ b/libraries/script-engine/src/ScriptsModel.h @@ -64,14 +64,60 @@ public: }; /**jsdoc - *

Provided as a property of {@link ScriptDiscoveryService}.

- *

Has properties and functions below in addition to those of - * http://doc.qt.io/qt-5/qabstractitemmodel.html.

+ * Information on the scripts that are in the default scripts directory of the Interface installation. This is provided as a + * property of {@link ScriptDiscoveryService}. + * + *

The information provided reflects the subdirectory structure. Methods and signals are per QT's + * QAbstractItemModel class, with the following details:

+ *
    + *
  • A single column of data: columnCount(index) returns 1.
  • + *
  • Data is provided for the following roles: + * + * + * + * + * + * + * + * + *
    RoleValueDescription
    Display0The directory or script file name.
    Path256The path and filename of the data item if it is a script, + * undefined if it is a directory.
    + *
  • + *
  • Use null for the root directory's index.
  • + *
+ * * @class ScriptsModel + + * @hideconstructor * * @hifi-interface * @hifi-client-entity * @hifi-avatar + * + * @example List the first 2 levels of the scripts directory. + * var MAX_DIRECTORY_LEVEL = 1; + * var DISPLAY_ROLE = 0; + * var PATH_ROLE = 256; + * + * function printDirectory(parentIndex, directoryLevel, indent) { + * var numRows = ScriptDiscoveryService.scriptsModel.rowCount(parentIndex); + * for (var i = 0; i < numRows; i++) { + * var rowIndex = ScriptDiscoveryService.scriptsModel.index(i, 0, parentIndex); + * + * var name = ScriptDiscoveryService.scriptsModel.data(rowIndex, DISPLAY_ROLE); + * var hasChildren = ScriptDiscoveryService.scriptsModel.hasChildren(rowIndex); + * var path = hasChildren ? "" : ScriptDiscoveryService.scriptsModel.data(rowIndex, PATH_ROLE); + * + * print(indent + "- " + name + (hasChildren ? "" : " - " + path)); + * + * if (hasChildren && directoryLevel < MAX_DIRECTORY_LEVEL) { + * printDirectory(rowIndex, directoryLevel + 1, indent + " "); + * } + * } + * } + * + * print("Scripts:"); + * printDirectory(null, 0, ""); // null index for the root directory. */ class ScriptsModel : public QAbstractItemModel { Q_OBJECT @@ -79,56 +125,25 @@ public: ScriptsModel(QObject* parent = NULL); ~ScriptsModel(); - /**jsdoc - * @function ScriptsModel.index - * @param {number} row - * @param {number} column - * @param {QModelIndex} parent - * @returns {QModelIndex} - */ + // No JSDoc because the particulars of the parent class is provided in the @class description. QModelIndex index(int row, int column, const QModelIndex& parent) const override; - /**jsdoc - * @function ScriptsModel.parent - * @param {QModelIndex} child - * @returns {QModelIndex} - */ + // No JSDoc because the particulars of the parent class is provided in the @class description. QModelIndex parent(const QModelIndex& child) const override; - /**jsdoc - * @function ScriptsModel.data - * @param {QModelIndex} index - * @param {number} [role=0] - * returns {string} - */ + // No JSDoc because the particulars of the parent class is provided in the @class description. QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - /**jsdoc - * @function ScriptsModel.rowCount - * @param {QmodelIndex} [parent=null] - * @returns {number} - */ + // No JSDoc because the particulars of the parent class is provided in the @class description. int rowCount(const QModelIndex& parent = QModelIndex()) const override; - /**jsdoc - * @function ScriptsModel.columnCount - * @param {QmodelIndex} [parent=null] - * @returns {number} - */ + // No JSDoc because the particulars of the parent class is provided in the @class description. int columnCount(const QModelIndex& parent = QModelIndex()) const override; - /**jsdoc - * @function ScriptsModel.getTreeNodeFromIndex - * @param {QmodelIndex} index - * @returns {TreeNodeBase} - */ + // Not exposed in the API because no conversion between TreeNodeBase and QScriptValue is provided. TreeNodeBase* getTreeNodeFromIndex(const QModelIndex& index) const; - /**jsdoc - * @function ScriptsModel.getFolderNodes - * @param {TreeNodeFolder} parent - * @returns {TreeNodeBase[]} - */ + // Not exposed in the API because no conversion between TreeNodeBase and QScriptValue is provided. QList getFolderNodes(TreeNodeFolder* parent) const; enum Role { @@ -136,9 +151,30 @@ public: }; protected slots: + + /**jsdoc + * @function ScriptsModel.updateScriptsLocation + * @param {string} newPath - New path. + * @deprecated This method is deprecated and will be removed from the API. + */ void updateScriptsLocation(const QString& newPath); + + /**jsdoc + * @function ScriptsModel.downloadFinished + * @deprecated This method is deprecated and will be removed from the API. + */ void downloadFinished(); + + /**jsdoc + * @function ScriptsModel.reloadLocalFiles + * @deprecated This method is deprecated and will be removed from the API. + */ void reloadLocalFiles(); + + /**jsdoc + * @function ScriptsModel.reloadDefaultFiles + * @deprecated This method is deprecated and will be removed from the API. + */ void reloadDefaultFiles(); protected: diff --git a/libraries/script-engine/src/ScriptsModelFilter.h b/libraries/script-engine/src/ScriptsModelFilter.h index 81ae4c1226..eb7495e7d4 100644 --- a/libraries/script-engine/src/ScriptsModelFilter.h +++ b/libraries/script-engine/src/ScriptsModelFilter.h @@ -16,14 +16,60 @@ #include /**jsdoc - *

Provided as a property of {@link ScriptDiscoveryService}.

- *

Has properties and functions per - * http://doc.qt.io/qt-5/qsortfilterproxymodel.html.

+ * Sorted and filtered information on the scripts that are in the default scripts directory of the Interface installation. This + * is provided as a property of {@link ScriptDiscoveryService}. + * + *

The information provided reflects the subdirectory structure. Properties, methods, and signals are per QT's + * QSortFilterProxyModel class, with the following details:

+ *
    + *
  • The rows are sorted per directory and file names.
  • + *
  • A single column of data: columnCount(index) returns 1.
  • + *
  • Data is provided for the following roles: + * + * + * + * + * + * + * + * + *
    RoleValueDescription
    Display0The directory or script file name.
    Path256The path and filename of the data item if it is a script, + * undefined if it is a directory.
    + *
  • + *
  • Use null for the root directory's index.
  • + *
+ * * @class ScriptsModelFilter + * @hideconstructor * * @hifi-interface * @hifi-client-entity * @hifi-avatar + * + * @example List all scripts that include "edit" in their name. + * var DISPLAY_ROLE = 0; + * var PATH_ROLE = 256; + * + * function printDirectory(parentIndex, directoryLevel, indent) { + * var numRows = ScriptDiscoveryService.scriptsModelFilter.rowCount(parentIndex); + * for (var i = 0; i < numRows; i++) { + * var rowIndex = ScriptDiscoveryService.scriptsModelFilter.index(i, 0, parentIndex); + * + * var name = ScriptDiscoveryService.scriptsModelFilter.data(rowIndex, DISPLAY_ROLE); + * var hasChildren = ScriptDiscoveryService.scriptsModelFilter.hasChildren(rowIndex); + * var path = hasChildren ? "" : ScriptDiscoveryService.scriptsModelFilter.data(rowIndex, PATH_ROLE); + * + * print(indent + "- " + name + (hasChildren ? "" : " - " + path)); + * + * if (hasChildren) { + * printDirectory(rowIndex, directoryLevel + 1, indent + " "); + * } + * } + * } + * + * ScriptDiscoveryService.scriptsModelFilter.filterRegExp = new RegExp("^.*edit.*$", "i"); // Set the filter. + * print("Edit scripts:"); + * printDirectory(null, 0, ""); // null index for the root directory. */ class ScriptsModelFilter : public QSortFilterProxyModel { Q_OBJECT diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 1140dbb079..abce5479c4 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -136,13 +136,9 @@ void QmlWindowClass::initQml(QVariantMap properties) { #if !defined(Q_OS_ANDROID) // If the restricted flag is on, override the FileTypeProfile and HFWebEngineProfile objects in the // QML surface root context with local ones - qDebug() << "Context initialization lambda"; - if (_restricted) { - qDebug() << "Restricting web content"; - ContextAwareProfile::restrictContext(context); - FileTypeProfile::registerWithContext(context); - HFWebEngineProfile::registerWithContext(context); - } + ContextAwareProfile::restrictContext(context, _restricted); + FileTypeProfile::registerWithContext(context); + HFWebEngineProfile::registerWithContext(context); #endif }; diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.cpp b/libraries/ui/src/ui/types/ContextAwareProfile.cpp index 98cc94ec10..f74e8754c9 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.cpp +++ b/libraries/ui/src/ui/types/ContextAwareProfile.cpp @@ -11,22 +11,47 @@ #include "ContextAwareProfile.h" -#if !defined(Q_OS_ANDROID) - +#include +#include #include +#include +#include + static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess"; -ContextAwareProfile::ContextAwareProfile(QQmlContext* parent) : - QQuickWebEngineProfile(parent), _context(parent) { } - - -void ContextAwareProfile::restrictContext(QQmlContext* context) { - context->setContextProperty(RESTRICTED_FLAG_PROPERTY, true); +ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : + ContextAwareProfileParent(context), _context(context) { + assert(context); } -bool ContextAwareProfile::isRestricted(QQmlContext* context) { - return context->contextProperty(RESTRICTED_FLAG_PROPERTY).toBool(); + +void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) { + context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict); } -#endif \ No newline at end of file +bool ContextAwareProfile::isRestrictedInternal() { + if (QThread::currentThread() != thread()) { + bool restrictedResult = false; + BLOCKING_INVOKE_METHOD(this, "isRestrictedInternal", Q_RETURN_ARG(bool, restrictedResult)); + return restrictedResult; + } + + QVariant variant = _context->contextProperty(RESTRICTED_FLAG_PROPERTY); + if (variant.isValid()) { + return variant.toBool(); + } + + // BUGZ-1365 - we MUST defalut to restricted mode in the absence of a flag, or it's too easy for someone to make + // a new mechanism for loading web content that fails to restrict access to local files + return true; +} + +bool ContextAwareProfile::isRestricted() { + auto now = usecTimestampNow(); + if (now > _cacheExpiry) { + _cachedValue = isRestrictedInternal(); + _cacheExpiry = now + MAX_CACHE_AGE; + } + return _cachedValue; +} diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.h b/libraries/ui/src/ui/types/ContextAwareProfile.h index 8fa5b98878..3192d2be54 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.h +++ b/libraries/ui/src/ui/types/ContextAwareProfile.h @@ -17,26 +17,40 @@ #include #include +using ContextAwareProfileParent = QQuickWebEngineProfile; +using RequestInterceptorParent = QWebEngineUrlRequestInterceptor; +#else +#include + +using ContextAwareProfileParent = QObject; +using RequestInterceptorParent = QObject; +#endif + +#include + class QQmlContext; -class ContextAwareProfile : public QQuickWebEngineProfile { +class ContextAwareProfile : public ContextAwareProfileParent { + Q_OBJECT public: - static void restrictContext(QQmlContext* context); - static bool isRestricted(QQmlContext* context); - QQmlContext* getContext() const { return _context; } + static void restrictContext(QQmlContext* context, bool restrict = true); + bool isRestricted(); + Q_INVOKABLE bool isRestrictedInternal(); protected: - class RequestInterceptor : public QWebEngineUrlRequestInterceptor { + class RequestInterceptor : public RequestInterceptorParent { public: - RequestInterceptor(ContextAwareProfile* parent) : QWebEngineUrlRequestInterceptor(parent), _profile(parent) {} - QQmlContext* getContext() const { return _profile->getContext(); } + RequestInterceptor(ContextAwareProfile* parent) : RequestInterceptorParent(parent), _profile(parent) { } + bool isRestricted() { return _profile->isRestricted(); } protected: ContextAwareProfile* _profile; }; ContextAwareProfile(QQmlContext* parent); - QQmlContext* _context; + QQmlContext* _context{ nullptr }; + bool _cachedValue{ false }; + quint64 _cacheExpiry{ 0 }; + constexpr static quint64 MAX_CACHE_AGE = MSECS_PER_SECOND; }; -#endif #endif // hifi_FileTypeProfile_h diff --git a/libraries/ui/src/ui/types/FileTypeProfile.cpp b/libraries/ui/src/ui/types/FileTypeProfile.cpp index 073460903e..615e80b85c 100644 --- a/libraries/ui/src/ui/types/FileTypeProfile.cpp +++ b/libraries/ui/src/ui/types/FileTypeProfile.cpp @@ -29,8 +29,8 @@ FileTypeProfile::FileTypeProfile(QQmlContext* parent) : } void FileTypeProfile::RequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - RequestFilters::interceptHFWebEngineRequest(info, getContext()); - RequestFilters::interceptFileType(info, getContext()); + RequestFilters::interceptHFWebEngineRequest(info, isRestricted()); + RequestFilters::interceptFileType(info); } void FileTypeProfile::registerWithContext(QQmlContext* context) { diff --git a/libraries/ui/src/ui/types/HFWebEngineProfile.cpp b/libraries/ui/src/ui/types/HFWebEngineProfile.cpp index ef1d009f09..3c5701cc52 100644 --- a/libraries/ui/src/ui/types/HFWebEngineProfile.cpp +++ b/libraries/ui/src/ui/types/HFWebEngineProfile.cpp @@ -28,7 +28,7 @@ HFWebEngineProfile::HFWebEngineProfile(QQmlContext* parent) : Parent(parent) } void HFWebEngineProfile::RequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - RequestFilters::interceptHFWebEngineRequest(info, getContext()); + RequestFilters::interceptHFWebEngineRequest(info, isRestricted()); } void HFWebEngineProfile::registerWithContext(QQmlContext* context) { diff --git a/libraries/ui/src/ui/types/RequestFilters.cpp b/libraries/ui/src/ui/types/RequestFilters.cpp index a3b3b7dc57..3fa1cd0bd9 100644 --- a/libraries/ui/src/ui/types/RequestFilters.cpp +++ b/libraries/ui/src/ui/types/RequestFilters.cpp @@ -63,8 +63,8 @@ namespace { } } -void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, QQmlContext* context) { - if (ContextAwareProfile::isRestricted(context) && blockLocalFiles(info)) { +void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, bool restricted) { + if (restricted && blockLocalFiles(info)) { return; } @@ -90,7 +90,7 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); } -void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info, QQmlContext* context) { +void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); if (isScript(filename) || isJSON(filename)) { static const QString CONTENT_HEADER = "Accept"; diff --git a/libraries/ui/src/ui/types/RequestFilters.h b/libraries/ui/src/ui/types/RequestFilters.h index 8fde94a1b4..0c25bbb354 100644 --- a/libraries/ui/src/ui/types/RequestFilters.h +++ b/libraries/ui/src/ui/types/RequestFilters.h @@ -24,8 +24,8 @@ class QQmlContext; class RequestFilters : public QObject { public: - static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, QQmlContext* context); - static void interceptFileType(QWebEngineUrlRequestInfo& info, QQmlContext* context); + static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, bool restricted); + static void interceptFileType(QWebEngineUrlRequestInfo& info); }; #endif diff --git a/scripts/developer/tests/ui/testLocalFileAccess.js b/scripts/developer/tests/ui/testLocalFileAccess.js new file mode 100644 index 0000000000..0141d5a95f --- /dev/null +++ b/scripts/developer/tests/ui/testLocalFileAccess.js @@ -0,0 +1,55 @@ +"use strict"; + +// Created by Bradley Austin Davis on 2019/08/29 +// Copyright 2013-2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ + +(function() { // BEGIN LOCAL_SCOPE + + +var QML_URL = "qrc:/qml/hifi/tablet/DynamicWebview.qml" +var LOCAL_FILE_URL = "file:///C:/test-file.html" + +var TABLET_BUTTON_NAME = "SCRIPT"; +var ICONS = { + icon: "icons/tablet-icons/menu-i.svg", + activeIcon: "icons/tablet-icons/meni-a.svg" +}; + + +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var button = tablet.addButton({ + icon: ICONS.icon, + activeIcon: ICONS.activeIcon, + text: TABLET_BUTTON_NAME, + sortOrder: 1 +}); + +function onClicked() { + var window = Desktop.createWindow(QML_URL, { + title: "Local file access test", + additionalFlags: Desktop.ALWAYS_ON_TOP, + presentationMode: Desktop.PresentationMode.NATIVE, + size: { x: 640, y: 480 }, + visible: true, + position: { x: 100, y: 100 }, + }); + window.sendToQml({ url: LOCAL_FILE_URL }); +} + +button.clicked.connect(onClicked); + +Script.scriptEnding.connect(function () { + button.clicked.disconnect(onClicked); + tablet.removeButton(button); +}); + +}()); // END LOCAL_SCOPE + + + diff --git a/scripts/developer/tests/ui/testLocalFileAccessServer.js b/scripts/developer/tests/ui/testLocalFileAccessServer.js new file mode 100644 index 0000000000..74fd52a216 --- /dev/null +++ b/scripts/developer/tests/ui/testLocalFileAccessServer.js @@ -0,0 +1,30 @@ +"use strict"; + +// Created by Bradley Austin Davis on 2019/08/29 +// Copyright 2013-2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function () { + var QML_URL = "qrc:/qml/hifi/tablet/DynamicWebview.qml" + var LOCAL_FILE_URL = "file:///C:/test-file.html" + + var _this = this; + _this.preload = function (pEntityID) { + var window = Desktop.createWindow(QML_URL, { + title: "Local file access test", + additionalFlags: Desktop.ALWAYS_ON_TOP, + presentationMode: Desktop.PresentationMode.NATIVE, + size: { x: 640, y: 480 }, + visible: true, + position: { x: 100, y: 100 }, + }); + window.sendToQml({ url: LOCAL_FILE_URL }); + }; + + _this.unload = function () { + console.log("QQQ on preload"); + }; +}); diff --git a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js index c064e2d138..2b401c5bc5 100644 --- a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js +++ b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js @@ -64,7 +64,9 @@ function simplifiedStatusIndicator(properties) { queryParamString += "&displayName=" + displayNameToSend; queryParamString += "&status=" + currentStatus; - queryParamString += "&organization=" + location.hostname; + var domainID = location.domainID; + domainID = domainID.substring(1, domainID.length - 1); + queryParamString += "&organization=" + domainID; var uri = REQUEST_URL + "?" + queryParamString; diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl index 451ed4d01a..2a5e863d6d 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl @@ -92,7 +92,13 @@ - + + + + +

Example 1? 's':'' ?>

+ +

Description