1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-05 23:53:33 +00:00

Compare commits

...

1 Commits

Author SHA1 Message Date
Hinton
69cd7d79e7 WIP!!! 2022-02-23 20:40:25 +01:00
120 changed files with 391414 additions and 0 deletions

View File

@@ -44,6 +44,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "test\Common\Commo
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Test", "test\Core.Test\Core.Test.csproj", "{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Test", "test\Core.Test\Core.Test.csproj", "{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Safari", "src\iOS.Safari\iOS.Safari.csproj", "{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -414,6 +416,36 @@ Global
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhone.Build.0 = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhone.Build.0 = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|Any CPU.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|Any CPU.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|iPhone.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|iPhone.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|Any CPU.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|Any CPU.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|iPhone.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|iPhone.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|iPhoneSimulator.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|iPhoneSimulator.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|Any CPU.ActiveCfg = Debug|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|Any CPU.Build.0 = Debug|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|iPhone.ActiveCfg = Debug|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|iPhone.Build.0 = Debug|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|Any CPU.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|Any CPU.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|iPhone.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|iPhone.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|Any CPU.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|Any CPU.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|iPhone.ActiveCfg = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|iPhone.Build.0 = Release|iPhone
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -431,6 +463,7 @@ Global
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A} = {D10CA4A9-F866-40E1-B658-F69051236C71} {8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{4085B0A5-12A9-4993-B8B8-4ACE72E62E39} = {8904C536-C67D-420F-9971-51B26574C3AA} {4085B0A5-12A9-4993-B8B8-4ACE72E62E39} = {8904C536-C67D-420F-9971-51B26574C3AA}
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0} = {8904C536-C67D-420F-9971-51B26574C3AA} {8AE548D9-A567-4E97-995E-93EC7DB0FDE0} = {8904C536-C67D-420F-9971-51B26574C3AA}
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7} = {D10CA4A9-F866-40E1-B658-F69051236C71}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7D436EA3-8B7E-45D2-8D14-0730BD2E0410} SolutionGuid = {7D436EA3-8B7E-45D2-8D14-0730BD2E0410}

View File

@@ -0,0 +1,73 @@
using System;
using MobileCoreServices;
using Foundation;
using UIKit;
namespace iOS.Safari
{
public partial class ActionViewController : UIViewController
{
protected ActionViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void DidReceiveMemoryWarning()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Get the item[s] we're handling from the extension context.
// For example, look for an image and place it into an image view.
// Replace this with something appropriate for the type[s] your extension supports.
bool imageFound = false;
foreach (var item in ExtensionContext.InputItems)
{
foreach (var itemProvider in item.Attachments)
{
if (itemProvider.HasItemConformingTo(UTType.Image))
{
// This is an image. We'll load it, then place it in our image view.
itemProvider.LoadItem(UTType.Image, null, delegate (NSObject image, NSError error)
{
var url = image as NSUrl;
if (url != null)
{
NSOperationQueue.MainQueue.AddOperation(delegate
{
imageView.Image = UIImage.LoadFromData(NSData.FromUrl(url));
});
}
});
imageFound = true;
break;
}
}
if (imageFound)
{
// We only handle one image, so stop looking for more.
break;
}
}
}
partial void DoneClicked(NSObject sender)
{
// Return any edited content to the host app.
// This template doesn't do anything, so we just echo the passed-in items.
ExtensionContext.CompleteRequest(ExtensionContext.InputItems, null);
}
}
}

View File

@@ -0,0 +1,24 @@
//
// This file has been generated automatically by MonoDevelop to store outlets and
// actions made in the Xcode designer. If it is removed, they will be lost.
// Manual changes to this file may not be handled correctly.
//
using Foundation;
namespace iOS.Safari
{
[Register("ActionViewController")]
partial class ActionViewController
{
[Outlet]
UIKit.UIImageView imageView { get; set; }
[Action("DoneClicked:")]
partial void DoneClicked(Foundation.NSObject sender);
void ReleaseDesignerOutlets()
{
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
</dict>
</plist>

31
src/iOS.Safari/Info.plist Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>iOS.Safari</string>
<key>CFBundleName</key>
<string>iOS.Safari</string>
<key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden.iOS-Safari</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>2.14.3</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>MinimumOSVersion</key>
<string>15.0</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.Safari.web-extension</string>
<key>NSExtensionPrincipalClass</key>
<string>SafariWebExtensionHandler</string>
</dict>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script src="vendor.js"></script><script src="background.js"></script></body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,36 @@
@-webkit-keyframes bitwardenfill {
0% {
-webkit-transform: scale(1.0, 1.0);
}
50% {
-webkit-transform: scale(1.2, 1.2);
}
100% {
-webkit-transform: scale(1.0, 1.0);
}
}
@-moz-keyframes bitwardenfill {
0% {
transform: scale(1.0, 1.0);
}
50% {
transform: scale(1.2, 1.2);
}
100% {
transform: scale(1.0, 1.0);
}
}
span[data-bwautofill].com-bitwarden-browser-animated-fill {
display: inline-block;
}
.com-bitwarden-browser-animated-fill {
animation: bitwardenfill 200ms ease-in-out 0ms 1;
-webkit-animation: bitwardenfill 200ms ease-in-out 0ms 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/content/autofiller.ts");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/content/autofiller.ts":
/*!***********************************!*\
!*** ./src/content/autofiller.ts ***!
\***********************************/
/*! no static exports found */
/***/ (function(module, exports) {
document.addEventListener('DOMContentLoaded', event => {
let pageHref = null;
let filledThisHref = false;
let delayFillTimeout;
const enabledKey = 'enableAutoFillOnPageLoad';
chrome.storage.local.get(enabledKey, (obj) => {
if (obj != null && obj[enabledKey] === true) {
setInterval(() => doFillIfNeeded(), 500);
}
});
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.command === 'fillForm' && pageHref === msg.url) {
filledThisHref = true;
}
});
function doFillIfNeeded(force = false) {
if (force || pageHref !== window.location.href) {
if (!force) {
// Some websites are slow and rendering all page content. Try to fill again later
// if we haven't already.
filledThisHref = false;
if (delayFillTimeout != null) {
window.clearTimeout(delayFillTimeout);
}
delayFillTimeout = window.setTimeout(() => {
if (!filledThisHref) {
doFillIfNeeded(true);
}
}, 1500);
}
pageHref = window.location.href;
const msg = {
command: 'bgCollectPageDetails',
sender: 'autofiller',
};
chrome.runtime.sendMessage(msg);
}
}
});
/***/ })
/******/ });

View File

@@ -0,0 +1,159 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/content/contextMenuHandler.ts");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/content/contextMenuHandler.ts":
/*!*******************************************!*\
!*** ./src/content/contextMenuHandler.ts ***!
\*******************************************/
/*! no static exports found */
/***/ (function(module, exports) {
const inputTags = ['input', 'textarea', 'select'];
const labelTags = ['label', 'span'];
const attributes = ['id', 'name', 'label-aria', 'placeholder'];
const invalidElement = chrome.i18n.getMessage('copyCustomFieldNameInvalidElement');
const noUniqueIdentifier = chrome.i18n.getMessage('copyCustomFieldNameNotUnique');
let clickedEl = null;
// Find the best attribute to be used as the Name for an element in a custom field.
function getClickedElementIdentifier() {
var _a, _b;
if (clickedEl == null) {
return invalidElement;
}
const clickedTag = clickedEl.nodeName.toLowerCase();
let inputEl = null;
// Try to identify the input element (which may not be the clicked element)
if (labelTags.includes(clickedTag)) {
let inputId = null;
if (clickedTag === 'label') {
inputId = clickedEl.getAttribute('for');
}
else {
inputId = (_a = clickedEl.closest('label')) === null || _a === void 0 ? void 0 : _a.getAttribute('for');
}
inputEl = document.getElementById(inputId);
}
else {
inputEl = clickedEl;
}
if (inputEl == null || !inputTags.includes(inputEl.nodeName.toLowerCase())) {
return invalidElement;
}
for (const attr of attributes) {
const attributeValue = inputEl.getAttribute(attr);
const selector = '[' + attr + '="' + attributeValue + '"]';
if (!isNullOrEmpty(attributeValue) && ((_b = document.querySelectorAll(selector)) === null || _b === void 0 ? void 0 : _b.length) === 1) {
return attributeValue;
}
}
return noUniqueIdentifier;
}
function isNullOrEmpty(s) {
return s == null || s === '';
}
// We only have access to the element that's been clicked when the context menu is first opened.
// Remember it for use later.
document.addEventListener('contextmenu', event => {
clickedEl = event.target;
});
// Runs when the 'Copy Custom Field Name' context menu item is actually clicked.
chrome.runtime.onMessage.addListener(event => {
if (event.command === 'getClickedElement') {
const identifier = getClickedElementIdentifier();
chrome.runtime.sendMessage({
command: 'getClickedElementResponse',
sender: 'contextMenuHandler',
identifier: identifier,
});
}
});
/***/ })
/******/ });

View File

@@ -0,0 +1,126 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/content/message_handler.ts");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/content/message_handler.ts":
/*!****************************************!*\
!*** ./src/content/message_handler.ts ***!
\****************************************/
/*! no static exports found */
/***/ (function(module, exports) {
window.addEventListener('message', event => {
if (event.source !== window)
return;
if (event.data.command && (event.data.command === 'authResult')) {
chrome.runtime.sendMessage({
command: event.data.command,
code: event.data.code,
state: event.data.state,
referrer: event.source.location.hostname,
});
}
if (event.data.command && (event.data.command === 'webAuthnResult')) {
chrome.runtime.sendMessage({
command: event.data.command,
data: event.data.data,
remember: event.data.remember,
referrer: event.source.location.hostname,
});
}
}, false);
const forwardCommands = ['promptForLogin', 'addToLockedVaultPendingNotifications', 'unlockCompleted'];
chrome.runtime.onMessage.addListener(event => {
if (forwardCommands.includes(event.command)) {
chrome.runtime.sendMessage(event);
}
});
/***/ })
/******/ });

View File

@@ -0,0 +1,592 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/content/notificationBar.ts");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/content/notificationBar.ts":
/*!****************************************!*\
!*** ./src/content/notificationBar.ts ***!
\****************************************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
document.addEventListener('DOMContentLoaded', event => {
if (window.location.hostname.indexOf('vault.bitwarden.com') > -1) {
return;
}
const pageDetails = [];
const formData = [];
let barType = null;
let pageHref = null;
let observer = null;
const observeIgnoredElements = new Set(['a', 'i', 'b', 'strong', 'span', 'code', 'br', 'img', 'small', 'em', 'hr']);
let domObservationCollectTimeout = null;
let collectIfNeededTimeout = null;
let observeDomTimeout = null;
const inIframe = isInIframe();
const cancelButtonNames = new Set(['cancel', 'close', 'back']);
const logInButtonNames = new Set(['log in', 'sign in', 'login', 'go', 'submit', 'continue', 'next']);
const changePasswordButtonNames = new Set(['save password', 'update password', 'change password', 'change']);
const changePasswordButtonContainsNames = new Set(['pass', 'change', 'contras', 'senha']);
let disabledAddLoginNotification = false;
let disabledChangedPasswordNotification = false;
chrome.storage.local.get('neverDomains', (ndObj) => {
const domains = ndObj.neverDomains;
if (domains != null && domains.hasOwnProperty(window.location.hostname)) {
return;
}
chrome.storage.local.get('disableAddLoginNotification', (disAddObj) => {
disabledAddLoginNotification = disAddObj != null && disAddObj.disableAddLoginNotification === true;
chrome.storage.local.get('disableChangedPasswordNotification', (disChangedObj) => {
disabledChangedPasswordNotification = disChangedObj != null &&
disChangedObj.disableChangedPasswordNotification === true;
if (!disabledAddLoginNotification || !disabledChangedPasswordNotification) {
collectIfNeededWithTimeout();
}
});
});
});
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
processMessages(msg, sendResponse);
});
function processMessages(msg, sendResponse) {
if (msg.command === 'openNotificationBar') {
if (inIframe) {
return;
}
closeExistingAndOpenBar(msg.data.type, msg.data.typeData);
sendResponse();
return true;
}
else if (msg.command === 'closeNotificationBar') {
if (inIframe) {
return;
}
closeBar(true);
sendResponse();
return true;
}
else if (msg.command === 'adjustNotificationBar') {
if (inIframe) {
return;
}
adjustBar(msg.data);
sendResponse();
return true;
}
else if (msg.command === 'notificationBarPageDetails') {
pageDetails.push(msg.data.details);
watchForms(msg.data.forms);
sendResponse();
return true;
}
}
function isInIframe() {
try {
return window.self !== window.top;
}
catch (_a) {
return true;
}
}
function observeDom() {
const bodies = document.querySelectorAll('body');
if (bodies && bodies.length > 0) {
observer = new MutationObserver(mutations => {
if (mutations == null || mutations.length === 0 || pageHref !== window.location.href) {
return;
}
let doCollect = false;
for (let i = 0; i < mutations.length; i++) {
const mutation = mutations[i];
if (mutation.addedNodes == null || mutation.addedNodes.length === 0) {
continue;
}
for (let j = 0; j < mutation.addedNodes.length; j++) {
const addedNode = mutation.addedNodes[j];
if (addedNode == null) {
continue;
}
const tagName = addedNode.tagName != null ? addedNode.tagName.toLowerCase() : null;
if (tagName != null && tagName === 'form' &&
(addedNode.dataset == null || !addedNode.dataset.bitwardenWatching)) {
doCollect = true;
break;
}
if ((tagName != null && observeIgnoredElements.has(tagName)) ||
addedNode.querySelectorAll == null) {
continue;
}
const forms = addedNode.querySelectorAll('form:not([data-bitwarden-watching])');
if (forms != null && forms.length > 0) {
doCollect = true;
break;
}
}
if (doCollect) {
break;
}
}
if (doCollect) {
if (domObservationCollectTimeout != null) {
window.clearTimeout(domObservationCollectTimeout);
}
domObservationCollectTimeout = window.setTimeout(collect, 1000);
}
});
observer.observe(bodies[0], { childList: true, subtree: true });
}
}
function collectIfNeededWithTimeout() {
if (collectIfNeededTimeout != null) {
window.clearTimeout(collectIfNeededTimeout);
}
collectIfNeededTimeout = window.setTimeout(collectIfNeeded, 1000);
}
function collectIfNeeded() {
if (pageHref !== window.location.href) {
pageHref = window.location.href;
if (observer) {
observer.disconnect();
observer = null;
}
collect();
if (observeDomTimeout != null) {
window.clearTimeout(observeDomTimeout);
}
observeDomTimeout = window.setTimeout(observeDom, 1000);
}
if (collectIfNeededTimeout != null) {
window.clearTimeout(collectIfNeededTimeout);
}
collectIfNeededTimeout = window.setTimeout(collectIfNeeded, 1000);
}
function collect() {
sendPlatformMessage({
command: 'bgCollectPageDetails',
sender: 'notificationBar',
});
}
function watchForms(forms) {
if (forms == null || forms.length === 0) {
return;
}
forms.forEach((f) => {
const formId = f.form != null ? f.form.htmlID : null;
let formEl = null;
if (formId != null && formId !== '') {
formEl = document.getElementById(formId);
}
if (formEl == null) {
const index = parseInt(f.form.opid.split('__')[2], null);
formEl = document.getElementsByTagName('form')[index];
}
if (formEl != null && formEl.dataset.bitwardenWatching !== '1') {
const formDataObj = {
data: f,
formEl: formEl,
usernameEl: null,
passwordEl: null,
passwordEls: null,
};
locateFields(formDataObj);
formData.push(formDataObj);
listen(formEl);
formEl.dataset.bitwardenWatching = '1';
}
});
}
function listen(form) {
form.removeEventListener('submit', formSubmitted, false);
form.addEventListener('submit', formSubmitted, false);
const submitButton = getSubmitButton(form, logInButtonNames);
if (submitButton != null) {
submitButton.removeEventListener('click', formSubmitted, false);
submitButton.addEventListener('click', formSubmitted, false);
}
}
function locateFields(formDataObj) {
const inputs = Array.from(document.getElementsByTagName('input'));
formDataObj.usernameEl = locateField(formDataObj.formEl, formDataObj.data.username, inputs);
if (formDataObj.usernameEl != null && formDataObj.data.password != null) {
formDataObj.passwordEl = locatePassword(formDataObj.formEl, formDataObj.data.password, inputs, true);
}
else if (formDataObj.data.passwords != null) {
formDataObj.passwordEls = [];
formDataObj.data.passwords.forEach((pData) => {
const el = locatePassword(formDataObj.formEl, pData, inputs, false);
if (el != null) {
formDataObj.passwordEls.push(el);
}
});
if (formDataObj.passwordEls.length === 0) {
formDataObj.passwordEls = null;
}
}
}
function locatePassword(form, passwordData, inputs, doLastFallback) {
let el = locateField(form, passwordData, inputs);
if (el != null && el.type !== 'password') {
el = null;
}
if (doLastFallback && el == null) {
el = form.querySelector('input[type="password"]');
}
return el;
}
function locateField(form, fieldData, inputs) {
if (fieldData == null) {
return;
}
let el = null;
if (fieldData.htmlID != null && fieldData.htmlID !== '') {
try {
el = form.querySelector('#' + fieldData.htmlID);
}
catch (_a) {
// Ignore error, we perform fallbacks below.
}
}
if (el == null && fieldData.htmlName != null && fieldData.htmlName !== '') {
el = form.querySelector('input[name="' + fieldData.htmlName + '"]');
}
if (el == null && fieldData.elementNumber != null) {
el = inputs[fieldData.elementNumber];
}
return el;
}
function formSubmitted(e) {
let form = null;
if (e.type === 'click') {
form = e.target.closest('form');
if (form == null) {
const parentModal = e.target.closest('div.modal');
if (parentModal != null) {
const modalForms = parentModal.querySelectorAll('form');
if (modalForms.length === 1) {
form = modalForms[0];
}
}
}
}
else {
form = e.target;
}
if (form == null || form.dataset.bitwardenProcessed === '1') {
return;
}
for (let i = 0; i < formData.length; i++) {
if (formData[i].formEl !== form) {
continue;
}
const disabledBoth = disabledChangedPasswordNotification && disabledAddLoginNotification;
if (!disabledBoth && formData[i].usernameEl != null && formData[i].passwordEl != null) {
const login = {
username: formData[i].usernameEl.value,
password: formData[i].passwordEl.value,
url: document.URL,
};
if (login.username != null && login.username !== '' &&
login.password != null && login.password !== '') {
processedForm(form);
sendPlatformMessage({
command: 'bgAddLogin',
login: login,
});
break;
}
}
if (!disabledChangedPasswordNotification && formData[i].passwordEls != null) {
const passwords = formData[i].passwordEls
.filter((el) => el.value != null && el.value !== '')
.map((el) => el.value);
let curPass = null;
let newPass = null;
let newPassOnly = false;
if (formData[i].passwordEls.length === 3 && passwords.length === 3) {
newPass = passwords[1];
if (passwords[0] !== newPass && newPass === passwords[2]) {
curPass = passwords[0];
}
else if (newPass !== passwords[2] && passwords[0] === newPass) {
curPass = passwords[2];
}
}
else if (formData[i].passwordEls.length === 2 && passwords.length === 2) {
if (passwords[0] === passwords[1]) {
newPassOnly = true;
newPass = passwords[0];
curPass = null;
}
else {
const buttonText = getButtonText(getSubmitButton(form, changePasswordButtonNames));
const matches = Array.from(changePasswordButtonContainsNames)
.filter(n => buttonText.indexOf(n) > -1);
if (matches.length > 0) {
curPass = passwords[0];
newPass = passwords[1];
}
}
}
if (newPass != null && curPass != null || (newPassOnly && newPass != null)) {
processedForm(form);
const changePasswordRuntimeMessage = {
newPassword: newPass,
currentPassword: curPass,
url: document.URL,
};
sendPlatformMessage({
command: 'bgChangedPassword',
data: changePasswordRuntimeMessage,
});
break;
}
}
}
}
function getSubmitButton(wrappingEl, buttonNames) {
if (wrappingEl == null) {
return null;
}
const wrappingElIsForm = wrappingEl.tagName.toLowerCase() === 'form';
let submitButton = wrappingEl.querySelector('input[type="submit"], input[type="image"], ' +
'button[type="submit"]');
if (submitButton == null && wrappingElIsForm) {
submitButton = wrappingEl.querySelector('button:not([type])');
if (submitButton != null) {
const buttonText = getButtonText(submitButton);
if (buttonText != null && cancelButtonNames.has(buttonText.trim().toLowerCase())) {
submitButton = null;
}
}
}
if (submitButton == null) {
const possibleSubmitButtons = Array.from(wrappingEl.querySelectorAll('a, span, button[type="button"], ' +
'input[type="button"], button:not([type])'));
let typelessButton = null;
possibleSubmitButtons.forEach(button => {
if (submitButton != null || button == null || button.tagName == null) {
return;
}
const buttonText = getButtonText(button);
if (buttonText != null) {
if (typelessButton != null && button.tagName.toLowerCase() === 'button' &&
button.getAttribute('type') == null &&
!cancelButtonNames.has(buttonText.trim().toLowerCase())) {
typelessButton = button;
}
else if (buttonNames.has(buttonText.trim().toLowerCase())) {
submitButton = button;
}
}
});
if (submitButton == null && typelessButton != null) {
submitButton = typelessButton;
}
}
if (submitButton == null && wrappingElIsForm) {
// Maybe it's in a modal?
const parentModal = wrappingEl.closest('div.modal');
if (parentModal != null) {
const modalForms = parentModal.querySelectorAll('form');
if (modalForms.length === 1) {
submitButton = getSubmitButton(parentModal, buttonNames);
}
}
}
return submitButton;
}
function getButtonText(button) {
let buttonText = null;
if (button.tagName.toLowerCase() === 'input') {
buttonText = button.value;
}
else {
buttonText = button.innerText;
}
return buttonText;
}
function processedForm(form) {
form.dataset.bitwardenProcessed = '1';
window.setTimeout(() => {
form.dataset.bitwardenProcessed = '0';
}, 500);
}
function closeExistingAndOpenBar(type, typeData) {
let barPage = 'notification/bar.html';
switch (type) {
case 'add':
barPage = barPage + '?add=1&isVaultLocked=' + typeData.isVaultLocked;
break;
case 'change':
barPage = barPage + '?change=1&isVaultLocked=' + typeData.isVaultLocked;
break;
default:
break;
}
const frame = document.getElementById('bit-notification-bar-iframe');
if (frame != null && frame.src.indexOf(barPage) >= 0) {
return;
}
closeBar(false);
openBar(type, barPage);
}
function openBar(type, barPage) {
barType = type;
if (document.body == null) {
return;
}
const barPageUrl = chrome.extension.getURL(barPage);
const iframe = document.createElement('iframe');
iframe.style.cssText = 'height: 42px; width: 100%; border: 0; min-height: initial;';
iframe.id = 'bit-notification-bar-iframe';
iframe.src = barPageUrl;
const frameDiv = document.createElement('div');
frameDiv.setAttribute('aria-live', 'polite');
frameDiv.id = 'bit-notification-bar';
frameDiv.style.cssText = 'height: 42px; width: 100%; top: 0; left: 0; padding: 0; position: fixed; ' +
'z-index: 2147483647; visibility: visible;';
frameDiv.appendChild(iframe);
document.body.appendChild(frameDiv);
iframe.contentWindow.location = barPageUrl;
const spacer = document.createElement('div');
spacer.id = 'bit-notification-bar-spacer';
spacer.style.cssText = 'height: 42px;';
document.body.insertBefore(spacer, document.body.firstChild);
}
function closeBar(explicitClose) {
const barEl = document.getElementById('bit-notification-bar');
if (barEl != null) {
barEl.parentElement.removeChild(barEl);
}
const spacerEl = document.getElementById('bit-notification-bar-spacer');
if (spacerEl) {
spacerEl.parentElement.removeChild(spacerEl);
}
if (!explicitClose) {
return;
}
switch (barType) {
case 'add':
sendPlatformMessage({
command: 'bgAddClose',
});
break;
case 'change':
sendPlatformMessage({
command: 'bgChangeClose',
});
break;
default:
break;
}
}
function adjustBar(data) {
if (data != null && data.height !== 42) {
const newHeight = data.height + 'px';
doHeightAdjustment('bit-notification-bar-iframe', newHeight);
doHeightAdjustment('bit-notification-bar', newHeight);
doHeightAdjustment('bit-notification-bar-spacer', newHeight);
}
}
function doHeightAdjustment(elId, heightStyle) {
const el = document.getElementById(elId);
if (el != null) {
el.style.height = heightStyle;
}
}
function sendPlatformMessage(msg) {
chrome.runtime.sendMessage(msg);
}
});
/***/ })
/******/ });

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -0,0 +1,144 @@
{
"manifest_version": 2,
"name": "__MSG_extName__",
"short_name": "__MSG_appName__",
"version": "1.54.0",
"description": "__MSG_extDesc__",
"default_locale": "en",
"author": "Bitwarden Inc.",
"homepage_url": "https://bitwarden.com",
"icons": {
"16": "images/icon16.png",
"32": "images/icon32.png",
"48": "images/icon48.png",
"96": "images/icon96.png",
"128": "images/icon128.png"
},
"content_scripts": [
{
"all_frames": true,
"js": [
"content/autofill.js",
"content/autofiller.js",
"content/notificationBar.js",
"content/contextMenuHandler.js"
],
"matches": [
"http://*/*",
"https://*/*",
"file:///*"
],
"run_at": "document_start"
},
{
"all_frames": false,
"js": [
"content/shortcuts.js"
],
"matches": [
"http://*/*",
"https://*/*",
"file:///*"
],
"run_at": "document_start"
},
{
"all_frames": false,
"js": [
"content/message_handler.js"
],
"matches": [
"http://*/*",
"https://*/*",
"file:///*"
],
"run_at": "document_start"
},
{
"all_frames": true,
"css": [
"content/autofill.css"
],
"matches": [
"http://*/*",
"https://*/*",
"file:///*"
],
"run_at": "document_end"
}
],
"background": {
"page": "background.html",
"persistent": false
},
"browser_action": {
"default_icon": {
"19": "images/icon19.png",
"38": "images/icon38.png"
},
"default_title": "Bitwarden",
"default_popup": "popup/index.html"
},
"permissions": [
"tabs",
"contextMenus",
"storage",
"unlimitedStorage",
"clipboardRead",
"clipboardWrite",
"idle",
"http://*/*",
"https://*/*",
"webRequestBlocking",
"nativeMessaging"
],
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"commands": {
"_execute_browser_action": {
"suggested_key": {
"default": "Ctrl+Shift+Y",
"linux": "Ctrl+Shift+U"
},
"description": "__MSG_commandOpenPopup__"
},
"_execute_sidebar_action": {
"suggested_key": {
"default": "Alt+Shift+Y",
"linux": "Alt+Shift+U"
},
"description": "__MSG_commandOpenSidebar__"
},
"autofill_login": {
"suggested_key": {
"default": "Ctrl+Shift+L"
},
"description": "__MSG_commandAutofillDesc__"
},
"generate_password": {
"suggested_key": {
"default": "Ctrl+Shift+9"
},
"description": "__MSG_commandGeneratePasswordDesc__"
},
"lock_vault": {
"description": "__MSG_commandLockVaultDesc__"
}
},
"web_accessible_resources": [
"notification/bar.html",
"images/icon38.png",
"images/icon38_locked.png",
"images/close.png"
],
"applications": {
"gecko": {
"id": "{446900e4-71c2-419f-a6a7-df9c091e268b}",
"strict_min_version": "42.0"
}
},
"sidebar_action": {
"default_title": "Bitwarden",
"default_panel": "popup/index.html?uilocation=sidebar",
"default_icon": "images/icon19.png"
}
}

View File

@@ -0,0 +1,92 @@
body {
background-color: #ffffff;
padding: 0;
margin: 0;
height: 100%;
font-size: 14px;
line-height: 16px;
color: #333333;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.outer-wrapper {
padding: 0 10px;
border-bottom: 2px solid #175ddc;
display: grid;
grid-template-columns: 24px auto 55px;
grid-column-gap: 10px;
box-sizing: border-box;
min-height: 42px;
}
.inner-wrapper {
display: grid;
grid-template-columns: auto max-content;
}
.outer-wrapper > *, .inner-wrapper > * {
align-self: center;
}
img {
border: 0;
margin: 0;
padding: 0;
}
#logo {
width: 24px;
height: 24px;
display: block;
}
#close {
width: 15px;
height: 15px;
display: block;
padding: 5px 0;
margin-right: 10px;
}
button:not(.link),
button:not(.neutral) {
background-color: #175DDC;
padding: 5px 15px;
border-radius: 3px;
color: #ffffff;
border: 0;
}
button:not(.link):hover,
button:not(.neutral):hover {
cursor: pointer;
background-color: #1751bd;
}
button.link,
button.neutral {
background: none;
padding: 5px 15px;
color: #175DDC;
border: 0;
}
button.link:hover,
button.neutral:hover {
cursor: pointer;
background: none;
text-decoration: underline;
}
.select-folder[isVaultLocked=true] {
display: none;
}
@media screen and (max-width: 768px) {
.select-folder {
display: none;
}
}
@media (print) {
body {
display: none;
}
}

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Bitwarden</title>
<meta charset="utf-8" />
<link href="../notification/bar.css" rel="stylesheet"></head>
<body>
<div class="outer-wrapper">
<div class="logo">
<a href="https://vault.bitwarden.com" target="_blank" id="logo-link">
<img id="logo" alt="Bitwarden" />
</a>
</div>
<div id="content"></div>
<div>
<button type="button" class="neutral" id="close-button">
<img id="close" alt="Close" />
</button>
</div>
</div>
<div id="templates" style="display: none;">
<div class="inner-wrapper" id="template-add">
<div class="add-text"></div>
<div class="add-buttons">
<button type="button" class="never-save link"></button>
<select class="select-folder" isVaultLocked="false"></select>
<button type="button" class="add-save"></button>
</div>
</div>
<div class="inner-wrapper" id="template-change">
<div class="change-text"></div>
<div class="change-buttons">
<button type="button" class="change-save"></button>
</div>
</div>
</div>
<script src="../notification/bar.js"></script></body>
</html>

View File

@@ -0,0 +1,273 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/notification/bar.js");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/notification/bar.js":
/*!*********************************!*\
!*** ./src/notification/bar.js ***!
\*********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__(/*! ./bar.scss */ "./src/notification/bar.scss");
document.addEventListener('DOMContentLoaded', () => {
var i18n = {};
var lang = window.navigator.language;
i18n.appName = chrome.i18n.getMessage('appName');
i18n.close = chrome.i18n.getMessage('close');
i18n.never = chrome.i18n.getMessage('never');
i18n.folder = chrome.i18n.getMessage('folder');
i18n.notificationAddSave = chrome.i18n.getMessage('notificationAddSave');
i18n.notificationAddDesc = chrome.i18n.getMessage('notificationAddDesc');
i18n.notificationChangeSave = chrome.i18n.getMessage('notificationChangeSave');
i18n.notificationChangeDesc = chrome.i18n.getMessage('notificationChangeDesc');
lang = chrome.i18n.getUILanguage();
// delay 50ms so that we get proper body dimensions
setTimeout(load, 50);
function load() {
const isVaultLocked = getQueryVariable('isVaultLocked') == 'true';
document.getElementById('logo').src = isVaultLocked
? chrome.runtime.getURL('images/icon38_locked.png')
: chrome.runtime.getURL('images/icon38.png');
document.getElementById('logo-link').title = i18n.appName;
var neverButton = document.querySelector('#template-add .never-save');
neverButton.textContent = i18n.never;
var selectFolder = document.querySelector('#template-add .select-folder');
selectFolder.setAttribute('aria-label', i18n.folder);
selectFolder.setAttribute('isVaultLocked', isVaultLocked.toString());
var addButton = document.querySelector('#template-add .add-save');
addButton.textContent = i18n.notificationAddSave;
var changeButton = document.querySelector('#template-change .change-save');
changeButton.textContent = i18n.notificationChangeSave;
var closeIcon = document.getElementById('close');
closeIcon.src = chrome.runtime.getURL('images/close.png');
closeIcon.alt = i18n.close;
var closeButton = document.getElementById('close-button')
closeButton.title = i18n.close;
closeButton.setAttribute('aria-label', i18n.close);
document.querySelector('#template-add .add-text').textContent = i18n.notificationAddDesc;
document.querySelector('#template-change .change-text').textContent = i18n.notificationChangeDesc;
if (getQueryVariable('add')) {
setContent(document.getElementById('template-add'));
var addButton = document.querySelector('#template-add-clone .add-save'),
neverButton = document.querySelector('#template-add-clone .never-save');
addButton.addEventListener('click', (e) => {
e.preventDefault();
const folderId = document.querySelector('#template-add-clone .select-folder').value;
const bgAddSaveMessage = {
command: 'bgAddSave',
folder: folderId,
};
sendPlatformMessage(bgAddSaveMessage);
});
neverButton.addEventListener('click', (e) => {
e.preventDefault();
sendPlatformMessage({
command: 'bgNeverSave'
});
});
if (!isVaultLocked) {
const responseFoldersCommand = 'notificationBarGetFoldersList';
chrome.runtime.onMessage.addListener((msg) => {
if (msg.command === responseFoldersCommand && msg.data) {
fillSelectorWithFolders(msg.data.folders);
}
});
sendPlatformMessage({
command: 'bgGetDataForTab',
responseCommand: responseFoldersCommand
});
}
} else if (getQueryVariable('change')) {
setContent(document.getElementById('template-change'));
var changeButton = document.querySelector('#template-change-clone .change-save');
changeButton.addEventListener('click', (e) => {
e.preventDefault();
const bgChangeSaveMessage = {
command: 'bgChangeSave'
};
sendPlatformMessage(bgChangeSaveMessage);
});
}
closeButton.addEventListener('click', (e) => {
e.preventDefault();
sendPlatformMessage({
command: 'bgCloseNotificationBar'
});
});
window.addEventListener("resize", adjustHeight);
adjustHeight();
}
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (pair[0] === variable) {
return pair[1];
}
}
return null;
}
function setContent(element) {
const content = document.getElementById('content');
while (content.firstChild) {
content.removeChild(content.firstChild);
}
var newElement = element.cloneNode(true);
newElement.id = newElement.id + '-clone';
content.appendChild(newElement);
}
function sendPlatformMessage(msg) {
chrome.runtime.sendMessage(msg);
}
function fillSelectorWithFolders(folders) {
const select = document.querySelector('#template-add-clone .select-folder');
select.appendChild(new Option(chrome.i18n.getMessage('selectFolder'), null, true));
folders.forEach((folder) => {
//Select "No Folder" (id=null) folder by default
select.appendChild(new Option(folder.name, folder.id || '', false));
});
}
function adjustHeight() {
sendPlatformMessage({
command: 'bgAdjustNotificationBar',
data: {
height: document.querySelector('body').scrollHeight
}
});
}
});
/***/ }),
/***/ "./src/notification/bar.scss":
/*!***********************************!*\
!*** ./src/notification/bar.scss ***!
\***********************************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin
/***/ })
/******/ });

Some files were not shown because too many files have changed in this diff Show More