다운로드 목록에서 파일 이름을 눌렀는데 파일 대신 폴더만 열리면 한 번 더 찾아야 한다. 반대로 저장 위치를 확인하려던 사람에게 문서 프로그램부터 띄우는 것도 불편하다. 북극성에서는 파일 이름과 옆의 폴더 버튼이 각각 다른 목적을 갖게 했고, 성공을 확인하는 기준도 나눴다.
열기라는 단어에 섞인 세 가지 목적
다운로드 폴더 전체를 보는 일, 개별 파일을 탐색기에서 선택해 보는 일, 그 파일을 기본 앱으로 여는 일은 다르다. 폴더 경로는 저장 공간을 찾게 하고 개별 폴더 버튼은 해당 파일의 위치를 짚어 준다. 파일 이름 클릭은 작업을 계속할 앱으로 연결한다. 서로 비슷한 아이콘이어도 목적은 합치지 않았다.
원래 구현의 openDownload는 이름과 달리 shell.showItemInFolder를 호출하는 위치 표시 경로다. downloadAction의 open은 shell.openPath를 호출한다. 내부 함수명만 보고 사용자 동작을 설명하면 반대로 적을 수 있다. 나는 문서와 버튼의 문구뿐 아니라 실제 호출되는 마지막 함수까지 확인하는 방식으로 이 차이를 읽었다.
현재 프로필의 완료 파일만 대상으로 삼는다
두 개별 파일 동작은 completedDownload를 통과한다. 현재 프로필의 완료 기록인지 찾고 실제 경로가 파일인지 lstat으로 확인한다. 파일이 이동하거나 삭제됐으면 다른 동명 파일을 대신 찾지 않고 안내한다. 기다리는 동안 프로필이 바뀌는 경우도 검사한다.
이 검사는 파일을 잠가 두는 기능이나 파일 내용의 안전성 검사가 아니다. 완료 목록의 ID가 가리키는 현재 대상을 확인하는 경계다. 다운로드가 아직 진행 중인데 이름이 먼저 보인다고 기본 앱을 띄우는 것은 허용하지 않는다. 반쪽짜리 결과를 열어서 생기는 혼란을 버튼 상태와 호스트 검사에서 함께 줄이려 했다.
작은 창의 요청도 신뢰 경계를 통과한다
다운로드 팝업은 open·reveal·folder 같은 action을 구분한다. IPC를 받는 쪽은 요청을 보낸 창과 mainFrame이 실제 다운로드 창인지 확인하고 action 형식을 검사한다. 개별 파일 ID가 현재 목록에 있는지도 본다. 웹페이지에서 보이는 이름 문자열을 곧바로 운영체제 파일 경로로 쓰지 않는다.
reveal은 해당 파일 위치 표시 경로로, open은 파일 제어 경로로 보낸다. 파일 열기가 끝나면 아직 살아 있는 작은 창을 닫는다. 외부 창을 만들려는 동작과 팝업 자체의 페이지 이동도 막는다. 이 글은 팝업의 모든 보안 속성을 인증한 보고서는 아니며 실제 클릭이 어떤 검사를 지나 어떤 동작으로 연결되는지 설명하는 제작 기록이다.
기본 앱에 넘겼다는 결과와 문서를 읽었다는 결과
shell.openPath의 오류 문자열이 비어 있지 않으면 연결된 앱을 확인하라는 안내를 낸다. 정상 반환은 운영체제에 파일 열기를 요청한 결과이지 문서가 끝까지 렌더링됐거나 사용자가 내용을 읽었다는 증거는 아니다. PDF와 영상, 텍스트는 연결 앱과 후속 표시가 서로 다를 수 있다.
원본 네이티브 시험은 shell.openPath를 완전히 가짜로 바꾸지 않고 원래 함수를 호출한 뒤 실제 전달 경로와 반환 오류를 기록한다. 이어 그 경로와 저장 파일 내용을 비교하도록 돼 있다. 반면 다른 UI 시험의 호출 기록 대역은 정확한 대상 전달을 보는 용도다. 두 시험의 근거를 같은 실화면 검증이라고 섞지 않았다.
버튼의 설명과 실제 목적지를 함께 남긴다
폴더 네이티브 시험은 설정한 다운로드 디렉터리를 기본 앱 경로로 열고 대상과 반환 오류, 실제 디렉터리 여부를 비교한다. 파일 이름 시험은 내려받은 한 파일의 정확한 경로를 사용한다. 같은 열기 성공이라도 어느 대상을 전달했는지 빠지면 사용자가 원한 행동이었는지 판단하기 어렵다.
이번에는 해당 소스와 선택 시험 범위를 읽었으며 실제 사용자의 파일이나 기본 앱을 새로 열지 않았다. 공유 파일 영수증 모듈에도 운영체제 열기 기능은 없다. 다른 관리자 화면에 적용한다면 전체 저장 폴더, 선택한 항목 위치, 파일 자체를 문구와 동작에서 분리하고 정확한 대상이 전달됐는지 확인하는 기준을 사용할 수 있다.