fix(frontend): Chromeのパスワードマネージャーにあらゆる入力欄がパスワード扱いをさせる問題を回避 (MisskeyIO#392)

1. inputタグにタイプ別に違うクラスを割り当て、ヒューリスティックアルゴリズムが違うものであることを区別できるように
2. `pw`のフィールドだと判定される要素を一つでも減らせる
This commit is contained in:
まっちゃとーにゅ 2024-02-01 10:31:00 +09:00 committed by GitHub
parent 8befa531a5
commit 6cd4ea548a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 21 additions and 18 deletions

View file

@ -11,6 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
ref="inputEl" ref="inputEl"
v-model="v" v-model="v"
v-adaptive-border v-adaptive-border
class="mk-input-color"
:class="$style.inputCore" :class="$style.inputCore"
type="color" type="color"
:disabled="disabled" :disabled="disabled"

View file

@ -90,7 +90,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkLoading v-if="fetching"/> <MkLoading v-if="fetching"/>
</div> </div>
<div v-if="draghover" :class="$style.dropzone"></div> <div v-if="draghover" :class="$style.dropzone"></div>
<input ref="fileInput" style="display: none;" type="file" accept="*/*" multiple tabindex="-1" @change="onChangeFileInput"/> <input ref="fileInput" style="display: none;" class="mk-input-file" type="file" accept="*/*" multiple tabindex="-1" @change="onChangeFileInput"/>
</div> </div>
</template> </template>

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div class="omfetrab" :class="['s' + size, 'w' + width, 'h' + height, { asDrawer, asWindow }]" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"> <div class="omfetrab" :class="['s' + size, 'w' + width, 'h' + height, { asDrawer, asWindow }]" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }">
<input ref="searchEl" :value="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" autocapitalize="off" @input="input()" @paste.stop="paste" @keydown.stop.prevent.enter="onEnter"> <input ref="searchEl" :value="q" class="mk-input-search search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" autocapitalize="off" @input="input()" @paste.stop="paste" @keydown.stop.prevent.enter="onEnter">
<!-- FirefoxのTabフォーカスが想定外の挙動となるためtabindex="-1"を追加 https://github.com/misskey-dev/misskey/issues/10744 --> <!-- FirefoxのTabフォーカスが想定外の挙動となるためtabindex="-1"を追加 https://github.com/misskey-dev/misskey/issues/10744 -->
<div ref="emojisEl" class="emojis" tabindex="-1"> <div ref="emojisEl" class="emojis" tabindex="-1">
<section class="result"> <section class="result">

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="$style.root"> <div :class="$style.root">
<input v-model="query" :class="$style.input" type="search" :placeholder="q"> <input v-model="query" class="mk-input-search" :class="$style.input" type="search" :placeholder="q">
<button :class="$style.button" @click="search"><i class="ti ti-search"></i> {{ i18n.ts.searchByGoogle }}</button> <button :class="$style.button" @click="search"><i class="ti ti-search"></i> {{ i18n.ts.searchByGoogle }}</button>
</div> </div>
</template> </template>

View file

@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
ref="inputEl" ref="inputEl"
v-model="v" v-model="v"
v-adaptive-border v-adaptive-border
:class="[$style.inputCore, { _monospace: code }]" :class="[`mk-input-${type}`, $style.inputCore, { _monospace: code }]"
:type="type" :type="type"
:disabled="disabled" :disabled="disabled"
:required="required" :required="required"

View file

@ -159,15 +159,15 @@ onMounted(() => {
lightbox.on('uiRegister', () => { lightbox.on('uiRegister', () => {
lightbox?.pswp?.ui?.registerElement({ lightbox?.pswp?.ui?.registerElement({
name: 'altText', name: 'altText',
className: 'pwsp__alt-text-container', className: 'pswp__alt-text-container',
appendTo: 'wrapper', appendTo: 'wrapper',
onInit: (el, pwsp) => { onInit: (el, pswp) => {
let textBox = document.createElement('p'); let textBox = document.createElement('p');
textBox.className = 'pwsp__alt-text _acrylic'; textBox.className = 'pswp__alt-text _acrylic';
el.appendChild(textBox); el.appendChild(textBox);
pwsp.on('change', () => { pswp.on('change', () => {
textBox.textContent = pwsp.currSlide?.data.comment; textBox.textContent = pswp.currSlide?.data.comment;
}); });
}, },
}); });
@ -298,7 +298,7 @@ const previewable = (file: Misskey.entities.DriveFile): boolean => {
backdrop-filter: var(--modalBgFilter); backdrop-filter: var(--modalBgFilter);
} }
.pwsp__alt-text-container { .pswp__alt-text-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -312,7 +312,7 @@ const previewable = (file: Misskey.entities.DriveFile): boolean => {
max-width: 800px; max-width: 800px;
} }
.pwsp__alt-text { .pswp__alt-text {
color: var(--fg); color: var(--fg);
margin: 0 auto; margin: 0 auto;
text-align: center; text-align: center;

View file

@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :style="sliderBgWhite ? '--sliderBg: rgba(255,255,255,.25);' : '--sliderBg: var(--scrollbarHandle);'"> <div :style="sliderBgWhite ? '--sliderBg: rgba(255,255,255,.25);' : '--sliderBg: var(--scrollbarHandle);'">
<div :class="$style.controlsSeekbar"> <div :class="$style.controlsSeekbar">
<progress v-if="buffer !== undefined" :class="$style.buffer" :value="isNaN(buffer) ? 0 : buffer" min="0" max="1">{{ Math.round(buffer * 100) }}% buffered</progress> <progress v-if="buffer !== undefined" :class="$style.buffer" :value="isNaN(buffer) ? 0 : buffer" min="0" max="1">{{ Math.round(buffer * 100) }}% buffered</progress>
<input v-model="model" :class="$style.seek" :style="`--value: ${modelValue * 100}%;`" type="range" min="0" max="1" step="any" @change="emit('dragEnded', modelValue)"/> <input v-model="model" class="mk-input-range" :class="$style.seek" :style="`--value: ${modelValue * 100}%;`" type="range" min="0" max="1" step="any" @change="emit('dragEnded', modelValue)"/>
</div> </div>
</div> </div>
</template> </template>

View file

@ -65,13 +65,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
</div> </div>
<MkInfo v-if="hasNotSpecifiedMentions" warn :class="$style.hasNotSpecifiedMentions">{{ i18n.ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ i18n.ts.add }}</button></MkInfo> <MkInfo v-if="hasNotSpecifiedMentions" warn :class="$style.hasNotSpecifiedMentions">{{ i18n.ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ i18n.ts.add }}</button></MkInfo>
<input v-show="useCw" ref="cwInputEl" v-model="cw" :class="$style.cw" :placeholder="i18n.ts.annotation" @keydown="onKeydown"> <input v-show="useCw" ref="cwInputEl" v-model="cw" class="mk-input-text" :class="$style.cw" :placeholder="i18n.ts.annotation" @keydown="onKeydown">
<div :class="[$style.textOuter, { [$style.withCw]: useCw }]"> <div :class="[$style.textOuter, { [$style.withCw]: useCw }]">
<div v-if="channel" :class="$style.colorBar" :style="{ background: channel.color }"></div> <div v-if="channel" :class="$style.colorBar" :style="{ background: channel.color }"></div>
<textarea ref="textareaEl" v-model="text" :class="[$style.text]" :disabled="posting || posted" :readonly="textAreaReadOnly" :placeholder="placeholder" data-cy-post-form-text @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd"/> <textarea ref="textareaEl" v-model="text" :class="[$style.text]" :disabled="posting || posted" :readonly="textAreaReadOnly" :placeholder="placeholder" data-cy-post-form-text @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd"/>
<div v-if="maxTextLength - textLength < 100" :class="['_acrylic', $style.textCount, { [$style.textOver]: textLength > maxTextLength }]">{{ maxTextLength - textLength }}</div> <div v-if="maxTextLength - textLength < 100" :class="['_acrylic', $style.textCount, { [$style.textOver]: textLength > maxTextLength }]">{{ maxTextLength - textLength }}</div>
</div> </div>
<input v-show="withHashtags" ref="hashtagsInputEl" v-model="hashtags" :class="$style.hashtags" :placeholder="i18n.ts.hashtags" list="hashtags"> <input v-show="withHashtags" ref="hashtagsInputEl" v-model="hashtags" class="mk-input-text" :class="$style.hashtags" :placeholder="i18n.ts.hashtags" list="hashtags">
<MkInfo v-if="files.length > 0" warn :class="$style.guidelineInfo" :rounded="false"><Mfm :text="i18n.tsx._postForm.guidelineInfo({ tosUrl: instance.tosUrl, nsfwGuideUrl })"/></MkInfo> <MkInfo v-if="files.length > 0" warn :class="$style.guidelineInfo" :rounded="false"><Mfm :text="i18n.tsx._postForm.guidelineInfo({ tosUrl: instance.tosUrl, nsfwGuideUrl })"/></MkInfo>
<XPostFormAttaches v-model="files" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName" @replaceFile="replaceFile"/> <XPostFormAttaches v-model="files" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName" @replaceFile="replaceFile"/>
<MkPollEditor v-if="poll" v-model="poll" @destroyed="poll = null"/> <MkPollEditor v-if="poll" v-model="poll" @destroyed="poll = null"/>

View file

@ -14,6 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<input <input
type="radio" type="radio"
:disabled="disabled" :disabled="disabled"
class="mk-input-radio"
:class="$style.input" :class="$style.input"
> >
<span :class="$style.button"> <span :class="$style.button">

View file

@ -7,6 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="[$style.root, { [$style.disabled]: disabled }]"> <div :class="[$style.root, { [$style.disabled]: disabled }]">
<input <input
ref="input" ref="input"
class="mk-input-checkbox"
type="checkbox" type="checkbox"
:disabled="disabled" :disabled="disabled"
:class="$style.input" :class="$style.input"

View file

@ -56,7 +56,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._ad.timezoneinfo }} {{ i18n.ts._ad.timezoneinfo }}
<div v-for="(day, index) in daysOfWeek" :key="index"> <div v-for="(day, index) in daysOfWeek" :key="index">
<input <input
:id="`ad${ad.id}-${index}`" type="checkbox" :checked="(ad.dayOfWeek & (1 << index)) !== 0" :id="`ad${ad.id}-${index}`" class="mk-input-checkbox" type="checkbox" :checked="(ad.dayOfWeek & (1 << index)) !== 0"
@change="toggleDayOfWeek(ad, index)" @change="toggleDayOfWeek(ad, index)"
> >
<label :for="`ad${ad.id}-${index}`">{{ day }}</label> <label :for="`ad${ad.id}-${index}`">{{ day }}</label>

View file

@ -18,8 +18,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="name">{{ i18n.tsx._auth.shareAccess({ name }) }}</div> <div v-if="name">{{ i18n.tsx._auth.shareAccess({ name }) }}</div>
<div v-else>{{ i18n.ts._auth.shareAccessAsk }}</div> <div v-else>{{ i18n.ts._auth.shareAccessAsk }}</div>
<form :class="$style.buttons" action="/oauth/decision" accept-charset="utf-8" method="post"> <form :class="$style.buttons" action="/oauth/decision" accept-charset="utf-8" method="post">
<input name="login_token" type="hidden" :value="$i.token"/> <input name="login_token" class="mk-input-token-hidden" type="hidden" :value="$i.token"/>
<input name="transaction_id" type="hidden" :value="transactionIdMeta?.content"/> <input name="transaction_id" class="mk-input-tr-id-hidden" type="hidden" :value="transactionIdMeta?.content"/>
<MkButton inline name="cancel" value="cancel">{{ i18n.ts.cancel }}</MkButton> <MkButton inline name="cancel" value="cancel">{{ i18n.ts.cancel }}</MkButton>
<MkButton inline primary>{{ i18n.ts.accept }}</MkButton> <MkButton inline primary>{{ i18n.ts.accept }}</MkButton>
</form> </form>

View file

@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-adaptive-border class="rfqxtzch _panel"> <div v-adaptive-border class="rfqxtzch _panel">
<div class="toggle"> <div class="toggle">
<div class="toggleWrapper"> <div class="toggleWrapper">
<input id="dn" v-model="darkMode" type="checkbox" class="dn"/> <input id="dn" v-model="darkMode" class="mk-input-checkbox dn" type="checkbox"/>
<label for="dn" class="toggle"> <label for="dn" class="toggle">
<span class="before">{{ i18n.ts.light }}</span> <span class="before">{{ i18n.ts.light }}</span>
<span class="after">{{ i18n.ts.dark }}</span> <span class="after">{{ i18n.ts.dark }}</span>