1Password Core Developer

Wanted: 1Password Core Developer

Do you like back ends and cannot lie? We’re expanding the 1Password team and are looking for a developer to set up shop in the common code layer that lives between 1Password for Mac and 1Password for iOS.

Who are you?

Well, you are an experienced individual who’s passionate about code and security (you’ll get bonus points for being extra passionate about 1Password too!); and you are someone who can help us raise the bar in terms of code quality, testability, and reliability.

You will be working with all sorts of fascinating things: data model, sync, security, and many other features shared between the apps. You’ll be tasked with awesome responsibilities like re-engineering core parts of the apps, fixing bugs whose reproducibility is minimal, and helping us define the future of 1Password. (With great responsibility comes great power, but don’t let it go to your head!)

Here are a few points we’d love to see in your resume:

  • Has expert knowledge of Objective-C and its runtime
  • Is intimately familiar with Foundation & CoreFoundation
  • Knows memory management rules like the back of their hand
  • Has the scars of experience with threading
  • Loves SQLite
  • Has a strong working knowledge of libdispatch

Want to impress us? Tell us about…

  • A sync system you’ve built
  • The socket servers you’ve designed
  • Crypto stuff you’ve used
  • XPC services you’ve deployed
  • The time you were put in charge of a designing a system that uses all of the above and had it successfully deployed to millions of customers

Curiously absent from this list is AppKit and UIKit experience. While you’ll be expected to contribute to both the Mac and iOS user interfaces at some point, it isn’t the focus of this position.

Who are we?

We’re a team devoted to our customers and the quality of our software. While we are physically headquartered in Toronto, Ontario, Canada, the majority of our ‘Bits work remotely from around the globe (mostly the States, other parts of Canada, and Europe).

Everyone on our team gets the opportunity to interact directly with our customers. Experiencing customer reactions and feedback first-hand is extremely valuable and empowers everyone at AgileBits to do something to continually improve 1Password, whether that’s by writing great articles, refactoring and perfecting code, or supporting our customers around the clock.

If your interest has been piqued, we’d love to hear from you. Email us a resume and an overview of the apps you’ve worked on.

We can’t wait to work with you!

<3 The 1Password for Mac & iOS Teams

Featured Image: Google Chrome (Scenery)

Adventures in beta testing, continued: Google Chrome Canary

Or, If you’re living on the bleeding edge, expect some paper cuts.

The Chromium team (the open-source project behind Google Chrome) is doing an amazing job of constantly moving the web forward and making the web a safer place for users of Google Chrome.

Recently, many users of the latest pre-release versions of Google Chrome have notified us that the 1Password extension refuses to work in OS X and Windows, showing the following error message:

1Password extension looking for app

What is going on?

The Google Chrome developers have started implementing changes to the types of connections extensions are allowed to establish. These changes are part of a larger and more complex plan to harden Google Chrome against certain kinds of web-based attacks (like cross-site request forgery attacks), in which a malicious website or extension attempts to compromise internal network devices and processes listening on the localhost IP address.

Unfortunately, in the process of implementing these new security measures, something was broken in a way that results in many Chrome extensions, including 1Password, not working anymore in the Canary build and the dev channel of Chrome.

What seems to be the issue?

The 1Password web browser extension needs to communicate with a helper process that runs in the background to access your 1Password data (1Password mini in OS X and 1Password Helper in Windows). This is facilitated by establishing WebSocket protocol connections at the localhost address of a computer. WebSocket connections are similar to the typical HTTP requests your web browser performs when visiting a website.

The way we understand the current situation is this:

  1. An extension tries to open a ws:// (WebSocket) connection.
  2. Chrome recognises the chrome-extension protocol and checks whether the connection attempt has a secure origin.
  3. If Chrome determines that the connection is not secure, it rejects the attempt and any further connection requests are never even attempted beyond that.

In the case of 1Password, this results in the extension thinking that the 1Password application does not exist on the PC/Mac in the first place or that something is blocking the WebSocket connection.

What is going to happen?

This is an ongoing issue that we’re still investigating but so far it is clear that the Chromium development community has recognised that many extensions communicate with host applications using WebSocket and other protocols. To our current knowledge, they are treating this issue as a regression in need of fixing, but any fix requires careful consideration in light of their efforts to increase security.

There are various active discussion threads and bug reports related to this situation in the Chromium project. To name only a few:

What to do now?

Testing pre-release software can be fun and is incredibly useful for the developers of that software and the developers of apps that interact with it — seriously, we love our beta testers. 1Password supports the latest stable builds of Safari, Chrome, Firefox, and Opera. While we make every effort to maintain compatibility with Beta, Dev, Nightly, Canary builds or other birds or browsers, we can’t guarantee that 1Password will always work as browsers go through their various development and release cycles.

If 1Password is as essential to your daily life as it is to ours, our suggestion is to temporarily return your browser to the stable version and check out the new Canary build/dev channel releases in a week or two — did I mention how much we appreciate beta testers sending in feedback? If you do want to live on the bleeding edge, please be aware of the potential for bugs in development and public beta versions of browsers and software in general and be patient with the developers of browsers, apps, and extensions as they negotiate a shifting landscape. We’ve added the article, “Prerelease (beta, dev, nightly) browser builds,” to our knowledge base to keep you apprised of any issues with unfinished versions of browsers.

As with any other questions regarding 1Password, please sound off about any issues you run into when using 1Password with pre-release versions of browsers in our discussion forums.

Unspeakable Passwords

Unspeakable Passwords: Jeff Goldberg talks to Passwords15

Passwords! They safeguard our most important information, but they’re such a pain, aren’t they? Every site imposes a different set of restrictions on password creation and they seem to get stolen from one place or another every other day, but they are absolutely necessary.

Given that passwords aren’t going anywhere anytime soon, it stands to reason that something must be done to thwart the increasing numbers of Not Nice People who would do us harm. I don’t know about you, but thinking about this stuff makes my brain hurt, which is why I’ve been using 1Password for almost 10 years.

Fortunately, there are some very, very smart folks who don their proverbial white hats and convene twice a year at an event called Passwords, where they figure out how to keep us safe. Launched in 2010, this conference focuses on the analysis of authentication solutions, in an effort to better understand and meet the challenges of digital authentication.

This year, our very own Jeff Goldberg was in attendance at #passwords15. If you don’t know who he is, allow me to introduce you. He’s our Chief Defender Against the Dark Arts, and a self-proclaimed explanation junkie. Seriously, he explains everything. At length. And very, very well. This makes him an excellent candidate to give a talk at such a conference, which is fantastic, because that’s exactly what he did.

In his presentation, Jeff talks about pronounceable passwords, entering them on various devices, Diceware, the successor to PBKDF2, and more. Check it out! You’ll learn, you’ll laugh, it’ll be great.

Presentation slides

Windows v4 blog

1Password and Windows 10: On the Edge of greatness

With the release of Microsoft’s latest operating system, you might be asking yourself, “Self, am I ready for Windows 10?” And while we at AgileBits wouldn’t presume to answer that question for you, we’re pleased to announce that 1Password is ready when you are!

Using Windows 10

A number of us have already been using Windows 10 regularly—and loving it. And it turns out that 1Password loves Windows 10 too! But while you’ll be able to hit the ground running and use 1Password as you always have, just be sure that your other hardware and software are ready to make the leap. And back up, back up, and back up some more.

Livin’ on the Edge

One significant change in Windows 10 that will be of interest to 1Password users is the addition of Microsoft’s latest and greatest web browser, Edge. Previously known as “Spartan,” we’ve found it to be fast, stable, and rather pleasant to use.

However, there’s a catch: Edge does not yet support extensions, so at this time there is no way to use the 1Password extension in Edge as you do in Firefox, Chrome, and Internet Explorer.

The good news is that Internet Explorer is still around, and 1Password works great in IE 11, along with our other favourite browsers. Word on the street is that Microsoft Edge will support extensions in the near future; we’re looking forward to seeing if that will enable us to provide 1Password extension support in the new browser.

Wi-Fi Sense, and the cost of convenience

One thing that you should know about is a new feature called Wi-Fi Sense. This feature has been present on Windows Phone for a while now, but it’s a new addition to the desktop OS. Wi-Fi Sense shares Wi-Fi network access between you and your Outlook, Skype, and Facebook contacts. While this may be convenient (even magical) for some, it also presents some security fodder for your consideration. With Windows 10 now unleashed, it’s especially important to understand how Wi-Fi Sense works, and then make an informed decision.

The Lowdown

Wi-Fi Sense can share most of your saved Wi-Fi connections. Windows keeps your saved Wi-Fi connections when you upgrade, so if you’ve been using Windows for a while, this might be a lengthy list. All the networks to which you’ve previously connected have the potential to be shared using Wi-Fi Sense.

It’s also important to note that Wi-Fi Sense doesn’t let you individually choose with whom you share your Wi-Fi connections; rather, they’re available to all of your contacts on a service (Outlook, Skype, Facebook) if that service is enabled.

The Downlow

One aspect of Wi-Fi Sense that is easy to overlook is that sharing is a two-way street: not only are you sharing your saved Wi-Fi connection information with your contacts, they’re also sharing theirs with you. Additionally, open hotspots are crowdsourced; unless you opt out, your Windows 10 devices will automatically connect to many unsecured Wi-Fi networks. Since these can be compromised or spoofed, we definitely recommend using protection (such as VPNs and encryption) any time you connect to Wi-Fi networks you don’t control.

The more you know…

If you’ve only ever used a wired connection, Windows won’t have a Wi-Fi connection saved, and therefore won’t be able to give it away to Facebook Guy and the rest. You can disable Wi-Fi Sense in Windows 10 by going to Wi-Fi > Network settings > Manage Wi-Fi settings and flipping the switch to turn it off. If you add “_optout” to end of your SSID (network name), your Wi-Fi network will be opted out of Wi-Fi Sense.

Windows 10 Wi-Fi Sense

Microsoft’s Wi-Fi Sense FAQ contains a lot of information to help you decide whether to keep this feature enabled. Here are some highlights:

  • When using Express setup, many of the Wi-Fi Sense options are enabled by default
  • Your contacts don’t see your Wi-Fi network password
  • You choose which Wi-Fi network connections you want to share
  • Network connections are shared only with contacts who also have Wi-Fi Sense enabled
  • Network connections are shared with your contacts, but not their contacts

If you’re a Windows Insider or early adopter, we hope you’re enjoying Windows 10. If you have any questions or feedback about 1Password, please share your thoughts in our discussion forums. We love hearing from you.

DevBits header

Accessibility in 1Password for iOS

At AgileBits we believe that everyone should be secure online. That means we want 1Password to be usable by as many people as possible. We have worked hard to implement many features that make 1Password more accessible. In this post I will explain some of the technologies we’ve taken advantage of to improve accessibility in 1Password for iOS.

What We Have Done

While our efforts are ongoing, here are some of the areas in 1Password where we offer accessibility features.

Colour Vision Deficiency and Password Readability

You may have noticed that when viewing a password, 1Password colours numbers and symbols differently. This is not only for convenience. We have carefully chosen colours easily seen by those who have trouble distinguishing different shades of a colour. We have tested for deficiencies related to protan, deutan, and tritan.

Those with achromatopsia (no ability to distinguish colour) must rely on character shapes to tell them apart. 1Password therefore offers a choice of fonts to make it easy to distinguish between the letter o and the number zero; and between lowercase l, capital I, and the number one.


Large Type

Sometimes you have to enter a password on another device that cannot run 1Password (e.g. a combination lock, employer’s computer, etc.). For this reason, we provide the large type feature that, when activated, displays the password as large as possible for easy reading when entering it elsewhere.


Dynamic Type

iOS provides a great feature called dynamic type. This allows apps to dynamically adjust the size of text to user settings. You can experiment with dynamic type in the iOS Settings app in General > Accessibility > Larger Text.

As a developer, it’d be too easy just to turn the feature on and leave it at that. But that would result in text that grows too large for the screen and ends up getting truncated to the point that it is unreadable, or it would push interface elements so far out of the way that they are unusable. Less important text could also crowd out more important text.

We’ve taken care to limit text size where necessary and ensure inevitable truncation happens such that the most important part of the text is still shown. We’re even looking at ways to rework the UI when the text is too large to fit.



Apple has a fantastically comprehensive voice-over system in iOS. In 1Password we take advantage of that by ensuring all of our interface elements and data values are properly labeled for accessibility so VoiceOver can read them aloud in a context that makes the app more usable. We have also minimized redundancies in describing the interface to make sure relevant interface elements are described quickly and effectively. To keep your passwords secure, 1Password will not read your passwords aloud unless you explicitly request it.

Work in Progress

As interfaces in software change and new features get added, accessibility support can change too. If there’s an accessibility feature you would like to have, or something you feel is not implemented as well as it could be, please let us know! We welcome feedback and want to make 1Password more usable for all of our awesome users!

DevBits header

The endless waltz: making custom UI for Windows Modern

Branding is a promise. It’s a guarantee of what to expect and a derivation of an identity. Here at AgileBits, we have strong brand identity and our customers can immediately recognize our app, no matter the platform on which they see it. As a recent addition to the AgileBits family, working on the latest addition to the 1Password application family, one of my priorities has been to ensure our new app feels like 1Password. But this, like so many other things, is easier said than done.

At first blush (and second, and third, and…), Windows Modern applications look nothing like apps on Mac, iOS, Android or any other platform; right out of the gate, we had our work cut out for us and we had to decide how to balance the unique Windows Modern style with what has come to be recognized as the 1Password style. In the end, we decided to keep the Windows Modern app as true to the 1Password style as possible. Despite having to deal with an overly verbose pattern for overriding the style template (in some cases 100 lines of code just to change a single property for a button) we continued to customize nearly every area of the app; when the dust had finally settled, our shared stylesheet (for phone and desktop) was the largest single file in our entire project (~1200 lines of code).

But we were able to stay true to the 1Password brand, as evident in our lock screen:

So it was well worth the effort, and we certainly learned a few new tricks along the way! But styling with such reckless abandon does have a cost.

There will be blood (and hacks)

Issues first began to arise when we started testing theme-switching for Windows Phone. Windows Phone gives users the ability to switch between a dark and a light theme. This is a hallmark feature of Windows Phone and one that users have come to expect. But of course, this feature is only available on Windows Phone; the iOS and Android platforms don’t have this capability by default, which added a new wrinkle: do we introduce a feature on Windows Phone that is not available on our other mobile platforms? We also noticed very poor performance with accessibility features when using high-contrast themes, and ease-of-access font scaling had a very low ceiling before the majority of text was cut off.

Why did we perform so poorly? In part, it was because of all the customization we had done. We became so focused on achieving the 1Password look and feel that we customized nearly everything, including many things that we never needed to touch. We also used the RequestedTheme property heavily, which allowed us to force a page to always render in a specific theme; this is a big no-no for a universal app. But more than anything else, it’s how the platform handles custom styles. The moment you create a custom style, you’re entirely accountable for it: you must tell it exactly how to behave under every single scenario a user may throw at you; and on the Windows Modern platform, there are a lot of possible scenarios. There are two default themes for Windows Phone (and two other high-contrast themes), and Windows desktop has the default theme (not light, not dark, just right) along with four other high-contrast themes. Yep, that’s eight themes developers need to support when they choose to add some of their own styling and branding to their apps. The moment you decide to change a background colour, adjust a font’s opacity, or change letter spacing, you’re abandoned by the Windows app platform, and left to your own devices. This desertion isn’t too much of an issue for developers working primarily on Windows modern, as the support the platform gives you to handle all of these scenarios right out of the box is excellent. But it’s an unfeasible expectation for Windows to extend this support to developers who customize their apps so heavily, so we got to work and began getting our stylesheets under control.

The taming of the shrew

After all of our customization, we had to take a step back and see how we could make 1Password work with the Windows Modern ecosystem, instead of against it.

We had no desire to rewrite all of the styles and themes that Microsoft had given us for free with the operating system. The code was ready and available; all we had to do was let the platform do its work without losing our brand in the platform.

Our first order of business was getting our stylesheets under control. We went through the entire app, page by page, and removed any properties we could live without, thereby giving responsibility back to Windows. We then rebuilt support for all the missing themes by first including them explicitly in our stylesheets, and only overriding the system colors in the default or base theme; for high contrast and light/dark themes, we once again passed responsibility back to Windows.


Prior to coming to work at AgileBits, I gained a lot of experience working on web accessibility for the Canadian Government, and we often discussed how different platforms handled accessibility.  On the Mac, instead of separate themes, users are given sliders in the OS preferences to adjust contrast and invert colours when necessary. Keeping these preferences at the OS level takes a lot of the responsibility away from app developers. While it can seem a bit daunting to oversee eight themes (at least) on Windows, the aesthetic and practical usefulness of these themes cannot be denied. For example, users can create custom themes that can be saved to their profile and be made available on the different PCs they use. Also, these themes being predefined make selecting appropriate themes much easier for users.


Branding is a promise. This is our endless waltz, and we cannot fail our dance partners. It’s a delicate balance that we must strike between Windows Modern and the 1Password experience, so that we may engender harmony among 1Password and Windows users.

1Password 5 for Mac logo

Adventures in beta testing: 1Password, El Capitan, and iOS 9

Let’s talk about betas. Specifically, let’s talk about Apple’s operating system betas. It used to be that you had to be an active member of the Apple Developer Program to get access to the betas. Last year, Apple launched a beta software program that enables anyone to sign up to test-drive pre-release versions of OS X. This year, for the first time, anyone can sign up to evaluate iOS 9 beta in addition to OS X 10.11 El Capitan beta.


There’s something thrilling about using beta software. It’s exciting to experience the software development process, with frequent updates that fix and improve things before our very eyes. It’s gratifying to participate in that process, seeing our bug reports get resolved and change requests considered and sometimes implemented. I don’t know about you, but I love feeling like I’ve helped make an improvement from which everyone using the software will benefit.

Hark, the cheers from developers far and wide

One of the most difficult things for software developers is getting the feedback they need before an application version goes public. This is because the pool of beta testers is generally so small. We could think everything is just fine, and then it gets out there and—BOOM—suddenly there are all these edge cases that never came up during the beta, because there are so many more people using it.

Public betas can be a real boon to developers, in that they help to increase the size of the beta pool and the degree to which the beta application is tested.

Hard hats required

under construction

Perhaps you remember those “Under construction” images from the early days of web publishing? It’s a very real metaphor for beta software. The most important thing to remember1 is that beta software is incomplete. Some things will not be implemented yet, some will be broken, and some may cause unexpected system kerfufflery.

Here are a few tips to help make your beta experience safe and enjoyable:

Spare a square

Ideally, beta software should be installed on spare hardware. If you have only one Mac, you can install El Capitan beta on separate partition of your Mac’s hard drive. If the iPhone you use every day is your only iOS device, it’s probably best not to install iOS 9 beta. If you have a non-critical iPad or an iPod touch, that would be a good place to install the beta.

Back that thang up

I know some of you are going to ignore me completely and install the betas on your mission-critical devices. Before you do that, please make sure to create a reliable backup!

We hear you

Your feedback is indispensable. If you notice anything wonky, be sure to report it to developers. I’ve seen beta issues reported in App Store reviews. While developers certainly read those and learn from them, they have no way of reaching out to the customer to help. It is best to contact developers directly with your beta feedback.

If you’re using 1Password beta, we have dedicated beta discussion forums. The beta forums are monitored by our developers and our support team is around to help you seven days a week!

If something you report isn’t immediately addressed, don’t worry. Developers may not be able to do anything about it just yet. Rest assured that the issue will be resolved as quickly as possible.

1Password 5, El Capitan, and iOS 9

I’m happy to tell you that we have thus far encountered no major issues in our testing. I have noticed a couple of graphical and layout issues in El Capitan beta, but it’s too early to tell whether the issues are in 1Password 5 for Mac or in El Capitan beta. We don’t want to spend time fixing something that may not actually be broken on our end, so for the moment we’re waiting to see how things pan out. We’ve documented the issues so we don’t lose track of them.

How to test 1Password beta for Mac

You are warmly invited to join our family of beta testers. The more, the merrier! 1Password 5.4 beta for Mac doesn’t require El Capitan beta, but it does require that you use the AgileBits Store version of 1Password, not the Mac App Store version. It’s very easy to switch over, but you will not be able to sync with iCloud.

How to test 1Password beta for iOS

Apple’s TestFlight Beta Testing program enables developers to extend a limited number of invitations to customers. There has been a great deal of interest in 1Password beta for iOS, and we are not looking for additional testers at this time. You can be the first to hear about opportunities to join our beta family for iOS by following @1PasswordBeta on Twitter.

1Password beta for Mac does not require 1Password beta for iOS.

1Password happy face

Have fun!

I lied earlier. The most important thing is to have fun, but keeping in mind the foibles of beta software and protecting yourself against them are a close second. =)

DevBits header

Debugging Next Key View Loops

When you create a window and populate it with views, AppKit automatically links your controls into a tab loop by setting the nextKeyView property on each view. This process is handled by the recalculateKeyViewLoop method inside NSWindow. The order of your views in this loop is based on the geometric location of each view in the window. Most of the time, this automatic mechanism works great, and you don’t have to think about it. But sometimes a window is too complex, and the automatic method produces incorrect results. When this happens, manual adjustment of the nextKeyView loop is required.

This is the situation we faced with the item detail view in 1Password for Mac 5. The detail view consists of a view-based NSTableView with multiple custom cell views. During the development of this view, we were constantly breaking the nextKeyView loop. Every time a new text field was added, or a button moved, some part of the nextKeyView loop would invariably break.

To make this debugging simpler, we wrote a utility class to visually overlay nextKeyView information on top of the detail view. Here is how it works.

The header

Let’s start with the header (.h):

//  OPTestKeyLoopView.h

#import <Cocoa/Cocoa.h>

@interface OPTestKeyLoopView : NSView

+ (void)enableForView:(NSView *)startView;
+ (void)disable;


The header provides a simple interface to enable and disable key loop debugging on a particular view. OPTestKeyLoopView is a Singleton, so these methods operate on the Class.

Private class to store visual overlay info

Moving on to the implementation (.m):

First, let’s define a simple private class used to store the visual overlay information about a particular view.

//  OPTestKeyLoopView.m

#import "OPTestKeyLoopView.h"

@interface OPTestKeyView : NSObject

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *subtitle;
@property (nonatomic, strong) NSColor *color;
@property (nonatomic, strong) NSFont *font;
@property (nonatomic, assign) NSRect frame;


@implementation OPTestKeyView


This class doesn’t do anything other than store the properties of a view overlay.

OPTestKeyLoopView implementation

Next, we begin implementing OPTestKeyLoopView by writing the Singleton and Class methods.

@interface OPTestKeyLoopView ()

@property (nonatomic, strong) NSView *rootView;
@property (nonatomic, strong) NSMutableArray *keyViews;
@property (nonatomic) NSRect rootFrame;


@implementation OPTestKeyLoopView

+ (OPTestKeyLoopView *)sharedTestKeyLoopView {
    static OPTestKeyLoopView *sharedView = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedView = [[self alloc] init];
        sharedView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
    return sharedView;

+ (void)enableForView:(NSView *)startView {
    [self sharedTestKeyLoopView].rootView = startView;
    [[NSNotificationCenter defaultCenter] addObserver:[self sharedTestKeyLoopView] selector:@selector(mainWindowFlagsChanged:) name:OPMainWindowFlagsChangedNotification object:nil];

+ (void)disable {
    [self sharedTestKeyLoopView].rootView = nil;
    [[self sharedTestKeyLoopView] clear];
    [[NSNotificationCenter defaultCenter] removeObserver:self];

Sidebar: OPMainWindowFlagsChangedNotification

This is a good time to pause and talk about the OPMainWindowFlagsChangedNotification notification. We want our overlay to appear when you press the Option key. The standard way to catch an Option key down event is to override

- (void)flagsChanged:(NSEvent *)theEvent

in your NSWindow or NSWindowController subclass. In our case, our window controller overrides this method and posts a notification so that other parts of the UI can easily respond to modifier key events. Here is what it looks like:

// From our NSWindowController subclass
- (void)flagsChanged:(NSEvent *)theEvent {
    [super flagsChanged:theEvent];
    [[NSNotificationCenter defaultCenter] postNotificationName:OPMainWindowFlagsChangedNotification object:nil];

Add the notification handler

Moving back to the implementation of OPTestKeyLoopView, next we’ll add the notification handler:

- (void)mainWindowFlagsChanged:(NSNotification *)aNotification {
    NSUInteger modifierFlags = ([NSApp currentEvent].modifierFlags & NSDeviceIndependentModifierFlagsMask);
    if (modifierFlags & NSAlternateKeyMask) {
        NSView *hitView = self.rootView;
        while (YES) {
            NSPoint mouse = [hitView convertPoint:[[self.rootView window] mouseLocationOutsideOfEventStream] fromView:nil];
            BOOL hitSubView = NO;
            for (NSView *subview in hitView.subviews) {
                if (subview == self) {
                if (NSMouseInRect(mouse, subview.frame, hitView.isFlipped)) {
                    hitView = subview;
                    hitSubView = YES;
            if (!hitSubView) {
        if (modifierFlags & NSShiftKeyMask) {
            [self showPreviousKeyViewLoopForView:hitView];
        else {
            [self showNextKeyViewLoopForView:hitView];
    else {
        [self clear];

This method checks for the Option key down and locates the furthest child view under the mouse. This child view will be the start of our next key view loop. Then we call a method to show the next key view loop overlay. If the shift key is also held down, we reverse the loop and show the previous key view loop.

Insert overlay view into view hierarchy

Next, we implement methods to insert our overlay view into the view hierarchy, and to build our list of keyViews. We do this by following the nextKeyView (or previousKeyView) property of the starting view and recording information about each view we encounter.

- (void)insertIntoViewHirarchy {
    if (self.superview) {
        [self removeFromSuperview];
    self.frame = [[[self.rootView window] contentView] frame];
    [[[self.rootView window] contentView] addSubview:self positioned:NSWindowAbove relativeTo:nil];

- (void)showPreviousKeyViewLoopForView:(NSView *)startView {
    [self insertIntoViewHirarchy];
    if (!self.keyViews) self.keyViews = [NSMutableArray new];
    [self.keyViews removeAllObjects];
    NSView *view = startView;
    NSMutableSet *visitedViews = [NSMutableSet new];
    NSInteger num = 0;
    do {
        NSRect frameInWindow = [view convertRect:view.bounds toView:nil];
        OPTestKeyView *keyView = [[OPTestKeyView alloc] init];
        keyView.frame = [self convertRect:frameInWindow fromView:nil];
        keyView.title = [NSString stringWithFormat:@"%ld", num];
        keyView.color = [NSColor redColor];
        keyView.font = [NSFont fontWithName:@"Menlo" size:12];
        NSLog(@"%ld %@", num, [view className]);
        [self.keyViews addObject:keyView];
        [visitedViews addObject:view];
        view = view.previousKeyView;
    } while (view && ![visitedViews containsObject:view]);
    self.rootFrame = [self convertRect:[startView convertRect:startView.bounds toView:nil] fromView:nil];
    [self setNeedsDisplay:YES];

- (void)showNextKeyViewLoopForView:(NSView *)startView {
    [self insertIntoViewHirarchy];
    if (!self.keyViews) self.keyViews = [NSMutableArray new];
    [self.keyViews removeAllObjects];
    NSView *view = startView;
    NSMutableSet *visitedViews = [NSMutableSet new];
    NSInteger num = 0;
    do {
        NSRect frameInWindow = [view convertRect:view.bounds toView:nil];
        OPTestKeyView *keyView = [[OPTestKeyView alloc] init];
        keyView.frame = [self convertRect:frameInWindow fromView:nil];
        keyView.title = [NSString stringWithFormat:@"%ld", num];
        keyView.color = [NSColor blueColor];
        keyView.font = [NSFont fontWithName:@"Menlo" size:12];
        NSLog(@"%ld %@", num, [view className]);
        [self.keyViews addObject:keyView];
        [visitedViews addObject:view];
        view = view.nextKeyView;
    } while (view && ![visitedViews containsObject:view]);
    self.rootFrame = [self convertRect:[startView convertRect:startView.bounds toView:nil] fromView:nil];
    [self setNeedsDisplay:YES];

- (void)clear {
    [self.keyViews removeAllObjects];
    [self removeFromSuperview];

Draw the overlay

Now that we have overlay information to display, and our OPTestKeyLoopView is in the view hierarchy, we can draw the overlay.

- (NSDictionary *)attributesWithFont:(NSFont *)font color:(NSColor *)color {
    NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    [paragraphStyle setAlignment:NSCenterTextAlignment];
    [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
    [paragraphStyle setLineSpacing:0];
    NSDictionary *attributes = [[NSDictionary alloc] initWithObjectsAndKeys:
                                font, NSFontAttributeName,
                                color, NSForegroundColorAttributeName,
                                paragraphStyle, NSParagraphStyleAttributeName, nil];
    return attributes;

- (void)drawRect:(NSRect)dirtyRect {
    if (self.keyViews.count > 0) {
        [[NSColor colorWithDeviceRed:1 green:0 blue:0 alpha:0.03] set];
        NSRectFillUsingOperation(self.rootFrame, NSCompositeSourceOver);
    for (OPTestKeyView *keyView in self.keyViews) {
        [keyView.color set];
        [NSBezierPath setDefaultLineWidth:0.5];
        [NSBezierPath strokeRect:NSOffsetRect(NSIntegralRect(keyView.frame), 0.25, 0.25)];
        NSDictionary *attributes = [self attributesWithFont:keyView.font color:keyView.color];
        NSSize size = [keyView.title sizeWithAttributes:attributes];
        NSRect textRect = NSIntegralRectWithOptions(NSInsetRect(keyView.frame, (keyView.frame.size.width - size.width)/2, (keyView.frame.size.height - size.height)/2), NSAlignMinXOutward|NSAlignMaxXInward|NSAlignMinYOutward|NSAlignMaxYInward);
        [[NSColor whiteColor] set];
        [keyView.title drawInRect:textRect withAttributes:attributes];

In drawRect: we loop through our keyView array and draw the overlay information for each keyView.

Tidy up

Lastly, we do some housekeeping by making sure our OPTestKeyLoopView is non-opaque and does not respond to mouse clicks.

- (BOOL)isOpaque {
    return NO;

- (NSView *)hitTest:(NSPoint)aPoint {
    return nil;


Here is what this looks like in action:

Debugging Next Key View Loops

Here is the code contained in this article (under an MIT license):

We’ve found this technique extremely useful when dealing with complex windows, and we hope you find it helpful too.

1Password for Android header

Wi-Fi Sync comes to 1Password for Android

Yesterday evening, after several weeks of collaboration with our beta family, we published the highly anticipated 1Password version 4.5 for Android. The big news, of course, is that it is now possible to sync your primary vault with 1Password for Mac or Windows using the new Wi-Fi Sync feature.

Look, Ma, no hands! (or clouds)

1Password for Android Wi-Fi logo

We’re thrilled to offer you even greater control over how you sync your 1Password data. If you prefer to keep your vault on your local Wi-Fi network and not fuss with manually copying your 1Password vault to and from your Android phone or tablet, you’ll enjoy the convenience of Wi-Fi Sync. You can read about setting up Wi-Fi Sync in our user guide. If you’re interested in reading more about Wi-Fi Sync from a developer’s perspective, we posted a DevBits article about this on our blog last month.

In related news, you know that “pull to refresh” gesture, where you tap your screen and drag it down? Well, we kind of love it. But that’s not a good enough reason to use it. After all, we don’t just throw things into 1Password, all willy nilly-like. While we were working on improvements for 4.5, we thought, What if you could use that easy, convenient gesture to manually trigger a sync? That would be cool! So now you can.

Polyglottery, levelled up.

One of the ways in which we make 1Password more accessible to folks is by localizing it, and we were immensely proud when we began doing that last year. Today, we add Korean to the list of available localizations.

You are awesome and we love you.

You are some seriously passionate people! Every day, our inbox and forums are filled with new conversations. The time you take to submit feature requests and bug reports means the world to us. It helps our developers prioritize resource allocation so we can make 1Password even better for you. The complete rundown of the improvements in version 4.5 can be found on our version history page.

If you use 1Password beta for Android, we have to extend an extra special thank you to you. We love our beta families on every platform, but especially on Android! There are so many different Android devices and without your help, it would be exponentially more difficult for us to make sure every 1Password update is a solid one. Thank you for all that you do.

1Password 4.5 for Android is available now in your local Google Play Store. If you’d like to join our beta team, you’re most welcome! Please sign up on our website. Got feedback? That’s fantastic, we love to hear from you. Please share your thoughts with us in our Android forum.

Windows v4 blog

1Password 4.6 for Windows: Fine-tuning the air conditioner

I’m not sure what it’s like where you are, but it’s been HOT lately, here in Germany. Recent days have had many on the team wishing they could work in their underwear. (Spoiler alert: I believe many already do.)
And just like fine-tuning an air conditioner in the house can make the difference between melting like ice in the sunshine and constantly looking like a plucked goose, we’re using version 4.6 of 1Password for Windows to make some useful improvements and fix a few bugs, to make things extra comfy for you.

Here’s the new coolness:

1Password + Yandex = best pals

The 1Password extension now works nicely in the privacy-focused Yandex browser. To install it, simply visit our browser extensions page in Yandex. Yandex will identify itself as Google Chrome (it’s based on the Chromium project) and from there you can install the extension like you usually would in Google Chrome.

Usernames column in the Logins category

You asked for it, we’ve listened. Now you can have a username column in the Logins category. To enable it, select View > Columns > Show Username in Logins in the menu bar.

Reordering Favorites

Don’t like the order of your favorites? Now you can reorder them by right-clicking the item you want to move up or down and selecting the appropriate menu option.

New custom field type: Phone

Once you add a custom phone field to an item, clicking the phone number will allow you to dial it with your favorite VoIP application or hand off the call to your smartphone by using a remote phone app for Android or Windows Phone.

More cool stuff…

  • The reliability of 1Click Bookmarks in Internet Explorer has been vastly improved.
  • The date picker in all categories now includes month digits next to the month name.
  • Our translators have further refined the localization of the app.

You can find the entire list of new features, improvements, and bug fixes in the release notes.

1Password 4.6 for Windows is available now as a free update for all existing owners. Choose Help > Check for New Version in the menu bar, or grab the new version from our downloads page.