앱 매니페스트 설정

개방형 웹앱의 매니페스트는 웹 브라우저가 앱과 상호 작용하는데 필요한 정보를 포함하는 기본 설정 파일입니다. 매니페스트는 개방형 웹앱을 웹 사이트와 구별하게 하는 중요한 포인트의 하나입니다. 앱의 명칭과 설명을 설명한 JSON 파일로, 앱의 생성원, 아이콘, 그 앱에 필요한 허가 설정등을 포함할 수도 있습니다. 매니페스트를 취급하는 브라우저는 웹 런타임에 이 기능을 넣어야 합니다.

자신이 관리하는 페이지에서 앱를 자주 배포하는 경우는 (예를 들면 버튼에서 navigator.mozApps.install()를 호출하는 것으로) 앱의 설치을 실행합니다. 스토어나 마켓프레이스에서 앱를 배포하는 경우는 그 스토어가 게재 앱의 매니페스트의 URL를 브라우저에 제공하는 것으로 설치를 실행합니다.

앱 매니페스트에 관한 자주 하는 질문도 참조해 주십시오.

매니페스트 예제 파일

아래가 최소한의 매니페스트입니다. 이것을 텍스트 파일에 복사하고 각각의 값을 원하는 정보로 바꾸면 됩니다.

주의: 여러분의 앱에는 아마 더 이상의 정보가 필요하며, 매니페스트의 모든 항목에 대해서는 아래 문서를 참조해 주십시오.

{
  "name": "My App",
  "description": "My elevator pitch goes here",
  "launch_path": "/",
  "icons": {
    "128": "/img/icon-128.png"
  },
  "developer": {
    "name": "Your name or organization",
    "url": "http://your-homepage-here.org"
  },
  "default_locale": "en"
}

매니페스트 항목

매니페스트에는 아래 항목을 포함할 수 있습니다. 필수 항목은 namedescription의 2 개 뿐입니다. 특정의 항목을 사용하는 경우에 필요한 다른 항목도 있습니다. 그것들은이 문서에 주석 첨부로 쓰여져 있습니다.

매니페스트 안의 항목은 순서를 묻지 않습니다. 여기에 쓰여지지 않은 항목이 매니페스트에 포함되어 있어도 무시됩니다.

activities

(Firefox OS만 사용. 선택) 앱이 대응하고 있는 일련의 Web Activities를 지정합니다. 이 항목의 각 속성는 액티비티입니다. 액티비티명은 자유 형식 텍스트로, 각 액티버티는 오브젝트로 나타내집니다. 이하는 share 라는 액티버티를 하나 포함한 액티버티 항목의 예입니다.

"activities": {
 "share": {
 "filters": {
  "type": [ "image/png", "image/gif" ]
 },
 "href": "foo.html",
 "disposition": "window"
 }
}

이 예에서는 share 액티버티의 오브젝트는 filters, href, disposition 라는 3 가지 속성를 가지고 있습니다. 각각의 의미는Activity 핸들러 소개를 참고하세요.

appcache_path

(옵션) 애플리케이션 캐시 (AppCache) 매니페스트 절대 경로. 개방형 웹앱을 설치 할 때, 이 AppCache 매니페스트가 취득 및 해석되어 CACHE 헤더 아래 정적 파일이 캐시됩니다.

"appcache_path": "/cache.manifest"

csp

(옵션) 앱의 Content Security Policy를 지정합니다. 이 정책은  앱의 모든 페이지에 적용됩니다. CSP의 구문은 앱 CSP 정보을 참고하세요.

덧붙여 특별 권한 앱와 인증 앱에 대해서는 이 속성를 사용하지 않아도, 상시 적용되는 기존의 CSP가 있습니다. 그러한 앱에서는 이 속성를 사용해 CSP 정책을 지정했을 경우, 두 가지 정책이 통합됩니다. 즉, 모든 액션은 기존의 정책과 속성의 정책 양쪽 모두로 허가 해야 합니다.

특별 권한 앱와 인증 앱에 적용되는 기존의 CSP는 이하와 같습니다.

특별 권한 앱
"default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"
인증 앱
"default-src *; script-src 'self'; object-src 'none'; style-src 'self'"

default_locale

(locales가 있는 경우는 필수) 매니페스트의 사용 언어를 나타내는 언어 태그 (RFC 4646)입니다. 여기서 이용한 언어 태그는 locales 항목에 포함하지 말아 주십시오. locales를 설명하지 않는 경우에서도 default_locale를 정의해 두는 것이 좋을 것입니다. Firefox OS Marketplace 에서는이 값에서 매니페스트의 사용 언어가 인식되어 번역된 항목에 적절한 로케일 값을 사용합니다. default_locale가 정의되어 있지 않은 경우, Marketplace는 전달 로케일에 근거해 언어를 추정하지 해야 합니다. default_locale는 앱를 설치 하는 단말에서는 사용하지 않습니다.

영어의 예:

"default_locale": "en"

description

(필수)  앱의 설명 (최장 1024 문자).

developer

(옵션) 앱의 개발자에 관한 정보.아래 속성를 가집니다.

  • name - 개발자의 이름.
  • url - 앱의 개발자에 대한 자세한 정보를 설명한 사이트의 URL. 이 URL는 원래 사용자가 대시 보드 (혹은 브라우저) 내에서 앱의 상세 정보를 표시하고 앱 개발자의 이름을 클릭했을 때에 열립니다.

* 주의: Firefox Marketplace에 등록되는 모든 앱은 이 정보를 포함해야 합니다.

fullscreen

(Firefox OS에서만 사용. 옵션) 이것을 true 혹은 false 로 설정하는 것으로 런타임이 그 앱를 전체화면 모드로 시작할지를 나타냅니다. 예제:

"fullscreen": "true"

icons

(옵션) 아이콘의 URI에 대한 아이콘 크기를 나타내는 맵 (절대 경로, data URI). 아이콘은 정사각형으로 앱를 시각적으로 나타내는 것을 목적으로 한 것입니다. 아이콘에는 그 이미지의 네 가지 모퉁이 모두에 배경을 깔아서는 안됩니다.  그리고 시작되는 경로는 앱의 생성원으에서의 상대 경로로 해서 해석됩니다.

Windows 7에서 Android 에서는 아래 아이콘 크기에 대응하고 있습니다.

  • 16 x 16
  • 32 x 32
  • 48 x 48
  • 64 x 64
  • 128 x 128
  • 256 x 256

Firefox OS 에서는 아이콘은 아래 크기로 그림자나 둥근 배경을 붙이지 않고 제공 해야 합니다.

  • 30 x 30
  • 60 x 60

자세한 것은 Firefox OS의 앱 아이콘 가이드 라인을 참조해 주십시오.

주의: Firefox OS Marketplace 에서는 등록하는 모든 앱에 대해서 최소로 128 x 128의 아이콘을 준비할 필요가 있습니다.

복수의 아이콘은 아래 예의 같게 지정할 수 있습니다.

"icons": {
  "16": "/img/icon-16.png",
  "48": "/img/icon-48.png",
  "128": "/img/icon-128.png"
}

installs_allowed_from

(옵션)이 앱의 설치 실행을 허가하는 생성원의 사이트 목록. 이 항목은 과금을 시행하는 경우 상업적인 앱스토어 사이의 비지니스를 위해 제공하는 것으로 무료 앱을 제공한다면 이 설정을 빼거나 *로 설정하는 것을 추천합니다.

이 데이터는 웹 사이트 배열로서 (schema+도메인, 예를 들면 https://marketplace.example.com). 이 항목으로 표시합니다.

배열을 ["*"] 과 같은 형식으로 했을 경우,이 앱의 설치는 모든 사이트에 허가됩니다. 이것이 기본 값입니다. 덧붙여[] 로 했을 경우, 자신의 사이트를 포함해 모든 사이트에서의 설치을 금지하게 됩니다. 이하는 모든 사이트에서의 설치을 허가하는 예입니다.

"installs_allowed_from": ["*"]

주의: 배열내의 URL 말미에는 slash를 붙이지 말아 주십시오. 예를 들면 https://marketplace.example.com/는 올바르지는 않습니다. 말미에 slash를 붙이면 설치에 실패합니다. 이 문제에 관한 버그는 이것입니다.

참고: URL 중 하나가 Firefox OS Marketplace의 경우는 https://marketplace.firefox.com/ 라고 지정해 주십시오.

launch_path

(옵션, 패키지형 앱에는 필수) 앱의 시작시에 읽히는 앱의 생성원내에서의 경로. 지정되어 있지 않은 경우, 앱의 생성원이 시작 도메인 URL 로서 다루어집니다. 경로 처리도 참조해 주십시오.

패키지형 앱에서는 이 항목은 그 패키지형 앱를 포함한 ZIP 파일을 기점으로 하는 내용의 시작점을 지정합니다. 예를 들면, launch_path/myApp/index.html 라는 값이 지정되었을 경우, 패키지형 앱는 시작시에 /myApp/index.html 파일을 엽니다.

locales

(옵션) 매니페스트에 포함되는 데이터의 언어 고유의 덧쓰기를 나타내는 맵.  단말의 로케일에 근거해 UI가 지역화된 보기를 제공하는데 사용합니다. 예를 들면, 이탈리아어권의 사용자가 앱를 설치 했을 경우는 아마 이탈리아어의 UI 텍스트를 제공하고 싶겠지요. 각 로케일 항목는 언어 태그 (RFC 4646)를 키로 하고 매니페스트 표현을 포함합니다. locale 항목내에 존재하는 모든 항목이 매니페스트 안에서 일치하는 항목을 덧쓰기합니다. default_locale, locales 자체, installs_allowed_from는 덧쓰기할 수 없습니다. 이러한 항목을 덧쓰기하는 매니페스트는 맞지 않다고 인식합니다. locales가 존재하는 경우는 default_locale 도 존재 해야 합니다.

스페인어와 이탈리아어의 예:

"locales": {
 "es": {
 "description": "Accin abierta emocionante del desarrollo del Web!",
 "developer": {
  "url": "http://es.mozillalabs.com/"
 }
 },
 "it": {
 "description": "Azione aperta emozionante di sviluppo di fotoricettore!",
 "developer": {
  "url": "http://it.mozillalabs.com/"
 }
 }
}

 

messages

(Firefox OS만, 옵션) 앱이 접근할 수 있는 시스템 메시지에 대한 목록. 시스템 메시지와 이와 연결된 웹 페이지 사이의 조합으로 표시되며 아래의 방식으로 지정합니다. 

"messages": [
  { "telephony-new-call": "/dialer/index.html#keyboard-view" },
  { "bluetooth-dialer-command": "/dialer/index.html#keyboard-view" },
  { "headset-button": "/dialer/index.html#keyboard-view" },
  { "notification": "/dialer/index.html#keyboard-view" },
  { "alarm": "/facebook/fb_sync.html" }
]

예를 들면, telephony-new-call(전화가 걸려오면)가 요청되면 단말기는 /dialer/index.html에서도#keyboard-view로 이동합니다. 그 페이지에서는 사용자가 뭔가 행동을 할 수 있는 (즉, 전화를 받을 수 있는) 방법을 제공해야 합니다.

name

(필수)  앱의 명칭 (최장 128 문자).

주의: Marketplace의 승인 후에 앱의 명칭을 변경했을 경우, 다시 승인을 신청할 필요가 있습니다.

orientation

(Android와 Firefox OS에만 사용, 옵션) 단말의 방향이 바뀌었을 경우에서도 앱를 고정하는 방향을 정의하는 배열. 배열내의 각 항목는 portrait, landscape, portrait-primary, landscape-primary, portrait-secondary, landscape-secondary의 어느쪽이든을 선택할 수 있습니다. 프라이머리와 세컨더리를 포함한 옵션은 단말의 방향이 바뀌었을 경우에서도 하나의 단말의 방향을 고정합니다. 프라이머리와 세컨더리를 포함하지 않는 옵션은 프라이머리와 세컨더리의 양쪽 모두 규칙을 조합합니다. 추가로 -secondary 라는 접미어를 붙인 옵션은 접미어가 없는 옵션에서 180 도의 회전을 암시합니다. 예를 들면, 스마트폰을 역상에 가지는 것 (그런데도 아직 높이보다 폭이 작다고 하는 경우)는 portrait-secondary의 방향이라는 의미가 됩니다. 이 항목이 적절한 값의 경우, 단말의 방향이 바뀌었을 경우에서도 런타임은 앱의 표시 방향을 바꾸지 않습니다.

"orientation": ["portrait","landscape-secondary"]

permissions

(옵션) 앱이 필요로 하는 일련의 허가 설정. 앱은 사용자의 허가를 필요로 하고 사용하려고 하는 모든 API를 목록을 표시 해야 합니다. 앱에서 API 항목내의 대응하는 항목없이 사용하려고 했을 경우, 오류로 표시 됩니다.

주의: 이러한 허가 설정의 상당수는 특별 권한 앱와 인증 앱에게만 필요한 것으로, 호스트형 앱에는 의미가 없습니다.

허가 설정 항목은객체 속성 마다 하나의 허가를 지정합니다. 각 API 항목에는 description 속성를 포함할 필요가 있습니다. 일부의 API는 access 속성도 필요합니다. permissions 항목의 예는 이하와 같습니다.

"permissions": {
 "contacts": {
 "description": "Required for autocompletion in the share screen",
 "access": "readcreate"
 },
 "alarms": {
 "description": "Required to schedule notifications"
 }
}
  • description - API의 사용을 요구하려는 의도를 명기한 문자열. 이 속성은 필수입니다.
  • access - 허가에 필요한 접근의 종류를 지정하는 문자열. 이 속성은 일부의 API에 필요합니다. 취할 수 있는 값은 read, readwrite, readcreate, createonly 입니다.

아래는 허가 설정 API의 목록입니다. API가 access 속성를 필요로 하는 경우는 그 취지 주기되어 있습니다. 이러한 허가 설정이 대응하는 기능에 대한 자세한 정보는 앱의 허가 설정을 참조해 주십시오.

  • alarms - 알람 예정 추가하거나 혹은 애플리케이션이 시작할 예정을 추가한다.
  • browser - 브라우저의 구현을 유효화한다.
  • contacts - 단말상의 주소장내의 연락처 추가, 읽기, 편집과 SIM 에서 연락처 읽기. access 속성 필수: readonly, readwrite, readcreate, createonly.
  • device-storage: music/device-storage: videos/device-storage:pictures/device-storage:sdcard - 단말상의 중심적인 장소에 저장되어 있는 파일의 추가, 읽기, 편집. access 속성 필수: readonly, readwrite, readcreate, createonly 추후 지원
  • fmradio - FM 라디오 제어.
  • geolocation - 사용자의 현재 위치 취득.
  • storage - 크기의 제약을 받지 않는 localStorageIndexedDB의 사용.
  • network-http - 생성원의 제약을 받지 않는 HTTP 요청의 발행.
  • network-tcp - TCP 소켓의 작성을 및 통신.
  • wake-lock-screen - 디스플레이의 표시와 잠금 스크린의 표시.
  • wifi-manage - 사용 가능한 WiFi 네트워크의 열거, 시그널 강도 취득, 네트워크에의 접속.

이하는 공인 앱만이 이용할 수 있는 특별한 속성입니다.

  • backgroundservice - 웹 앱의 백그라운드에서의 실행, 동기화나 착신 메세지의 답신이라는 작업 실행을 가능하게 한다.
  • bluetooth - Bluetooth 하드웨어 저레벨 접근.
  • camera - 사진이나 동영상의 촬영, 카메라의 제어. 이것이 인증 앱로 한정되어 있는 이유는 애플리케이션이 실행되는 샌드 박스가 카메라 하드웨어의 것에의 접근를 제한하고 있기때문입니다. Firefox OS의 개발자는 가능한 한 빨리 써드파티 앱에서도 사용할 수 있도록 하고 싶으나 첫  출시까지 구현 시간이 필요합니다.
  • desktop-notification - 사용자 데스크탑의 알림표시.
  • mobileconnection - 현재 모바일 음성·데이터 접속에 관한 정보 취득.
  • power - 스크린 끄고 켜기, CPU, 단말 전원등의 제어. 자원 잠금 이벤트의 감시와 조사.
  • settings - 단말 설정의 변경 혹은 읽어내. access 속성 필수: readonly, readwrite.
  • sms - SMS의 송수신.
  • systemclock - 현재 시각의 설정. (시간대의 정보는 settings API에 의해서 제어 됩니다)
  • telephony - 모든 통화 관련 API 에의 접근.
  • webapps-manage - 설치이 끝난 Open Web App를 관리하는 navigator.mozApps.mgmt API 에의 접근권 취득.

redirects

(옵션, 특별 권한 및 인증앱만) 특별 권한 및 인증앱은 외부 사용자 인증이 필요할 수 있습니다. 예를 들면, Facebook OAuth를 통해 친구의 주소록에 접근한다던지 하는 게 가능한데 이 때 돌아올 수 있는 URL을 지정할 수 있어야 합니다.

하지만, 이들 앱들은 돌아올만한 웹 URL을 가지고 있지 않기 때문에 (패키지 앱들은 호스팅을 하는 게 아니므로)  redirects 필드는 내부 app URL을 만들어 줍니다. 

예제:

"redirects": [
  {"from": "http://mydomain.com/oauth2/flow.html",
    "to": "/redirects/redirect.html"},
  {"from": "http://mydomain.com/oauth2/dialogs_end.html",
    "to": "/redirects/dialogs_end.html"}
]

from 필드는 웹 URL을 to 필드는 내부 앱 URL입니다. 내부 앱 URL은 상대 경로로 지정하므로 절대로 http:// 프로토콜을 앞에 쓰면 안됩니다.

redirects 선언은 그 선언된 앱에서만 가능힙니다.

Note:  from will only be recognized and handed over to the internal to path when it was requested via HTTP redirect (30x HTTP status header). Opening the URL without HTTP redirect will ignore the redirects setting.

type

(옵션) 앱의 종류. web, privileged, certified. 각 타입의 설명은 이하와 같습니다.

  • web - 원래의 앱. 허가 설정은 이 매니페스트의 permissions 항목에 설명된 것에 제한됩니다. 매니페스트로 type 항목을 지정하지 않는 경우, web이 기본 값이 됩니다.
  • privileged - Firefox OS Marketplace 등의 앱 스토어에 의해서 승인하고 인증이 끝난 웹앱. 보안이나 개인 정보에 관련되는 일부 API는 특별 권한 앱만 사용할 수 있습니다. 이것은 그러한 API 에의 접근를 요구하는 앱의 사용자에 대해서 보다 고도의 보안를 제공하기 위한 조치입니다. 특별 권한 앱은 아래 추가 특성을 가진 패키지형 앱입니다 (모든 자원이 하나의 ZIP 파일에 포함됩니다).
    • 코드의 심사나 그것과 동등의 확인을 받은 후, 앱 스토어에 의해서 승인된다.
    • 앱 스토어에 의해서 서명된 앱 매니페스트를 가진다.
    • Content Security Policy를 사용.
    • 보안에 관한 더 보기의 대책을 구현. 자세한 것은 보안를 참조해 주십시오.
  • certified - 스마트폰 위의 기존 통화 앱나 시스템 설정 앱 등 중요한 시스템 기능을 갖춘 웹앱. 앱 스토어에 등록된 써드파티 앱에게 줄 수 있는 권한이 아닙니다. 인증 앱은 특별 권한 앱을 닮은 패키지형 앱이지만, 모든 단말 허가 설정이 암시되어 있는 점이 다릅니다. 인증 앱은 그 단말을 사용하는 OEM 혹은 통신사에 의한 승인을 필요로 합니다.

예제:

"type": "privileged"

version

(옵션) 매니페스트의 버전을 나타내는 문자열. 웹 런타임은이 값을 일절 사용하지 않으므로, 임의의 값을 받을 수 있습니다. 이 문자열을 매니페스트에 추출하고, 여러가지 업데이트의 케이스에 대처하기 위해서 도움이 될 수도 있습니다. 매니페스트의 업데이트을 참조해 주십시오.

경로 처리

매니페스트 안에서 경로를 가지는 모든 항목은 절대 경로 (예를 들면 /images/myicon.png)여야 하며, 그 경로는 앱와 같은 생성원에서 제공되는 것이여야 합니다.

또한, launch_path를 설정하는 경우는 다음 두 방법의 방법이 있습니다.

  • 예를 들면 mywebapp.github.com/와 같이, 웹 서버의 루트에 저장되어 있는 경우는 launch_path/ 로 합니다.
  • 그렇지 않고, 예를 들면 mymarket.github.com/mywebapp/와 같이 웹에 서브 디렉토리에 저장되어 있는 경우는 launch_path/mywebapp/ 로 합니다.

매니페스트 검증

매니페스트를 검증하려면이 사이트를 사용해 주십시오: https://marketplace.firefox.com/developers/validator

매니페스트의 검증에 사용할 수 있는 API 도 있습니다: http://zamboni.readthedocs.org/en/latest/topics/api.html#validate

이러한 검증 방법을 사용하려면 현재로서는 무료 Firefox OS Marketplace 계정 정보가 필요합니다. 계정 정보가 없어도 유효성을 사용할 수 있도록 하는 버그는 있습니다.

매니페스트 제공

앱 매니페스트는 앱가 제공되는 것과 같은 생성원에서 제공할 필요가 있습니다.

정적 파일에서 제공하는 경우, 그 매니페스트는 파일 확장자(extension)를 .webapp 로서 저장하는 것을 추천합니다. 앱 매니페스트는 application/x-web-app-manifest+jsonContent-Type 헤더로 제공 해야 합니다 (이것은 현재 Firefox 에서는 필수가 아닙니다만, Marketplace 에서는 필수입니다). 특정 공격 리스크를 경감하기 위하고 SSL 통신을 통해서 매니페스트를 제공하는 것도 가능합니다.

Firefox OS Marketplace에 앱를 등록하는 경우, 문서의 문자 인코딩은 UTF-8 로 할 필요가 있습니다. 바이트 오더 마크 (BOM)는 생략 하는 것을 추천합니다. 다른 인코딩은 Marketplace 에서는 평가하지 않습니다만, Content-Type 헤더의 charset 파라메타로 지정 가능합니다 (예: Content-Type: application/x-web-app-manifest+json; charset=ISO-8859-4).

사용자 에이전트는 가능한 경우, 앱의 설치을 사용자에게 확인할 때, 사이트 식별 정보와 TLS 스테이터스를 의미가 있는 형태로 전합니다.

Apache 에서의 제공

.htaccess 파일에 아래 행을 추가합니다.

AddType application/x-web-app-manifest+json .webapp
주의: 이것은 .webapp를 확장자(extension)로서 사용하고 있는 것을 전제로 하고 있습니다. .json 나 더 보기의 확장자(extension)를 사용하는 경우는 거기에 대응하고 코드를 고쳐 써 주십시오.

.htaccess 파일이 없는 경우는 서버의 루트 디렉토리에 새로 만들기해 주십시오. 만약 위의 코드를 추가해도 기대 대로에 동작하지 않는 경우, AddHandler x-web-app-manifest+json .webapp 라는 행도 추가할 필요가 있습니다.

NGINX 에서의 제공

설정 디렉토리에 있는 mime.types 파일을 편집할 필요가 있습니다. 이것은 아마 /etc/nginx//opt/nginx/에 있습니다.

이하와 같은 설정이 발견될 것입니다. 마지막 행을 추가해 주십시오.

types {
 text/html html htm shtml;
 text/css css;
 text/xml xml;
 application/x-web-app-manifest+json webapp;
}
주의: 이것은 .webapp를 확장자(extension)로서 사용하고 있는 것을 전제로 하고 있습니다. .json 나 더 보기의 확장자(extension)를 사용하는 경우는 거기에 응하고 코드를 고쳐 써 주십시오.
GitHub 에서의 제공

매니페스트 파일을 GitHub Pages 에서 제공하는 경우, GitHub가 자동으로 application/x-web-app-manifest+jsonContent-Type 헤더로 제공해 줍니다. 매니페스트 파일은 .webapp 확장자(extension)를 사용할 필요가 있습니다. 예: manifest.webapp

Python 에서의 제공

Python가 설치 되어 있는 경우는 Python를 시작하고 아래 코드를 실행하는 것으로, 로컬 디렉토리에서 간단하게 서버를 실행할 수 있습니다.

import SimpleHTTPServer
import SocketServer
SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map['.webapp'] = 'application/x-web-app-manifest+json'
httpd = SocketServer.TCPServer(("", 3000), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.serve_forever()

매니페스트의 업데이트

앱의 업데이트에 관한 정보는 앱의 업데이트을 참조해 주십시오.

 

Document Tags and Contributors

Contributors to this page: Channy, chrisdavidmills
Last updated by: chrisdavidmills,